From fb436a915c56e431b34cc09014397b540bbf93ff Mon Sep 17 00:00:00 2001
From: joonhoekim <26rote@gmail.com>
Date: Tue, 18 Nov 2025 18:37:53 +0900
Subject: (김준회) SWP 추가요청사항: 정렬 및 데이터 표현량 추가, 사용성 개선
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/swp/table/swp-document-detail-dialog.tsx | 176 ++++++++++++++-------------
 1 file changed, 90 insertions(+), 86 deletions(-)

(limited to 'lib/swp/table/swp-document-detail-dialog.tsx')

diff --git a/lib/swp/table/swp-document-detail-dialog.tsx b/lib/swp/table/swp-document-detail-dialog.tsx
index a87cd0e2..77ef77f7 100644
--- a/lib/swp/table/swp-document-detail-dialog.tsx
+++ b/lib/swp/table/swp-document-detail-dialog.tsx
@@ -192,85 +192,97 @@ export function SwpDocumentDetailDialog({
     }
   };
 
-  // Revision별로 Activity 그룹핑 (rowspan용)
+  // Revision별로 Activity 그룹핑 및 정렬 (rowspan용)
   const groupedActivities = useMemo(() => {
+    // 1. REV 내림차순, createDate 내림차순으로 정렬
+    const sortedActivities = [...activities].sort((a, b) => {
+      // REV 비교 (내림차순)
+      const revCompare = b.revNo.localeCompare(a.revNo);
+      if (revCompare !== 0) return revCompare;
+      
+      // 같은 REV 내에서는 createDate 내림차순
+      return b.createDate.localeCompare(a.createDate);
+    });
+
+    // 2. 그룹핑
     const groups: Map<string, ActivityRow[]> = new Map();
-    activities.forEach((activity) => {
+    sortedActivities.forEach((activity) => {
       const key = `${activity.revNo}|${activity.stage}`;
       if (!groups.has(key)) {
         groups.set(key, []);
       }
       groups.get(key)!.push(activity);
     });
+    
     return groups;
   }, [activities]);
 
   return (
     <Dialog open={open} onOpenChange={onOpenChange}>
-      <DialogContent className="max-w-[95vw] max-h-[80vh] overflow-hidden flex flex-col">
+      <DialogContent className="max-w-[95vw] h-[90vh] overflow-hidden flex flex-col">
         <DialogHeader>
-          <DialogTitle>문서 리비전 히스토리</DialogTitle>
+          <DialogTitle className="text-base">문서 리비전 히스토리</DialogTitle>
           {document && (
-            <DialogDescription>
+            <DialogDescription className="text-xs">
               {document.DOC_NO} - {document.DOC_TITLE}
             </DialogDescription>
           )}
         </DialogHeader>
 
         {document && (
-          <div className="flex-1 flex flex-col space-y-4 overflow-hidden min-h-0">
+          <div className="flex-1 flex flex-col space-y-2 overflow-hidden">
             {/* 문서 정보 */}
-            <div className="grid grid-cols-1 md:grid-cols-5 gap-4 p-4 bg-muted/30 rounded-lg">
-              <div>
-                <span className="text-sm font-semibold">프로젝트:</span>
-                <div className="text-sm">{document.PROJ_NO}</div>
+            <div className="flex items-center gap-4 px-3 py-2 bg-muted/30 rounded text-xs">
+              <div className="flex items-center gap-1">
+                <span className="font-semibold">프로젝트:</span>
+                <span>{document.PROJ_NO}</span>
                 {document.PROJ_NM && (
-                  <div className="text-xs text-muted-foreground">{document.PROJ_NM}</div>
+                  <span className="text-muted-foreground">({document.PROJ_NM})</span>
                 )}
               </div>
-              <div>
-                <span className="text-sm font-semibold">패키지:</span>
-                <div className="text-sm">{document.PKG_NO || "-"}</div>
+              <div className="flex items-center gap-1">
+                <span className="font-semibold">패키지:</span>
+                <span>{document.PKG_NO || "-"}</span>
               </div>
-              <div>
-                <span className="text-sm font-semibold">업체:</span>
-                <div className="text-sm">{document.CPY_NM || "-"}</div>
+              <div className="flex items-center gap-1">
+                <span className="font-semibold">업체:</span>
+                <span>{document.CPY_NM || "-"}</span>
                 {document.VNDR_CD && (
-                  <div className="text-xs text-muted-foreground">{document.VNDR_CD}</div>
+                  <span className="text-muted-foreground">({document.VNDR_CD})</span>
                 )}
               </div>
-              <div>
-                <span className="text-sm font-semibold">최신 리비전:</span>
-                <div className="text-sm">{document.LTST_REV_NO || "-"}</div>
+              <div className="flex items-center gap-1">
+                <span className="font-semibold">최신 리비전:</span>
+                <span>{document.LTST_REV_NO || "-"}</span>
               </div>
-              <div>
-                <span className="text-sm font-semibold">총 Activity:</span>
-                <div className="text-sm">{activities.length}개</div>
+              <div className="flex items-center gap-1">
+                <span className="font-semibold">총 Activity:</span>
+                <span>{activities.length}개</span>
               </div>
             </div>
 
             {/* Activity 테이블 */}
             {isLoading ? (
               <div className="flex items-center justify-center p-8">
-                <Loader2 className="h-6 w-6 animate-spin" />
-                <span className="ml-2">리비전 트리 로딩 중...</span>
+                <Loader2 className="h-5 w-5 animate-spin" />
+                <span className="ml-2 text-sm">리비전 트리 로딩 중...</span>
               </div>
             ) : activities.length > 0 ? (
               <>
                 {/* Activity 테이블 (위) */}
-                <div className="flex-1 overflow-auto border rounded-lg min-h-0">
+                <div className="h-[40vh] overflow-auto border rounded-lg">
                   <Table>
                     <TableHeader className="sticky top-0 bg-background z-10">
-                      <TableRow>
-                        <TableHead className="w-[80px]">Rev</TableHead>
-                        <TableHead className="w-[80px]">Stage</TableHead>
-                        <TableHead className="w-[80px]">IN/OUT</TableHead>
-                        <TableHead className="w-[100px]">Status</TableHead>
-                        <TableHead className="min-w-[150px]">Transmittal No</TableHead>
-                        <TableHead className="min-w-[150px]">Activity No</TableHead>
-                        <TableHead className="min-w-[100px]">Ref Activity</TableHead>
-                        <TableHead className="w-[120px]">Modified</TableHead>
-                        <TableHead className="w-[80px]">By</TableHead>
+                      <TableRow className="text-xs">
+                        <TableHead className="w-[70px] text-xs h-8">Rev</TableHead>
+                        <TableHead className="w-[70px] text-xs h-8">Stage</TableHead>
+                        <TableHead className="w-[70px] text-xs h-8">IN/OUT</TableHead>
+                        <TableHead className="w-[90px] text-xs h-8">Status</TableHead>
+                        <TableHead className="min-w-[130px] text-xs h-8">Transmittal No</TableHead>
+                        <TableHead className="min-w-[130px] text-xs h-8">Activity No</TableHead>
+                        <TableHead className="min-w-[90px] text-xs h-8">Ref Activity</TableHead>
+                        <TableHead className="w-[100px] text-xs h-8">Modified</TableHead>
+                        <TableHead className="w-[70px] text-xs h-8">By</TableHead>
                       </TableRow>
                     </TableHeader>
                     <TableBody>
@@ -280,7 +292,7 @@ export function SwpDocumentDetailDialog({
                           <TableRow
                             key={activity.actvNo}
                             className={cn(
-                              "cursor-pointer hover:bg-muted/50",
+                              "cursor-pointer hover:bg-muted/50 h-8",
                               selectedActivity?.actvNo === activity.actvNo &&
                                 "bg-blue-50 hover:bg-blue-100"
                             )}
@@ -289,7 +301,7 @@ export function SwpDocumentDetailDialog({
                             {/* Rev 컬럼 (첫 행만 표시, rowspan) */}
                             {idx === 0 && (
                               <TableCell 
-                                className="font-mono text-sm font-semibold align-top border-r"
+                                className="font-mono text-xs font-semibold align-top border-r py-1"
                                 rowSpan={groupActivities.length}
                               >
                                 {revNo}
@@ -298,45 +310,41 @@ export function SwpDocumentDetailDialog({
                             {/* Stage 컬럼 (첫 행만 표시, rowspan) */}
                             {idx === 0 && (
                               <TableCell 
-                                className="align-top border-r text-sm"
+                                className="align-top border-r text-xs py-1"
                                 rowSpan={groupActivities.length}
                               >
                                 {stage}
                               </TableCell>
                             )}
-                            <TableCell>
+                            <TableCell className="py-1">
                               <Badge
                                 variant="outline"
-                                className={
+                                className={cn(
+                                  "text-[10px] h-4 px-1",
                                   activity.inOut === "IN"
                                     ? "bg-blue-100 text-blue-800"
                                     : "bg-green-100 text-green-800"
-                                }
+                                )}
                               >
                                 {activity.inOut}
                               </Badge>
                             </TableCell>
-                            <TableCell>
-                              <div className="text-sm">
-                                <div className="font-medium">{activity.statusName}</div>
-                                <div className="text-xs text-muted-foreground">
-                                  {activity.statusCode}
-                                </div>
-                              </div>
+                            <TableCell className="text-xs py-1">
+                              <div className="font-medium">{activity.statusName}</div>
                             </TableCell>
-                            <TableCell className="text-sm">
+                            <TableCell className="text-xs py-1">
                               {activity.transmittalNo || "-"}
                             </TableCell>
-                            <TableCell className="font-mono text-xs">
+                            <TableCell className="font-mono text-xs py-1">
                               {activity.actvNo}
                             </TableCell>
-                            <TableCell className="font-mono text-xs">
+                            <TableCell className="font-mono text-xs py-1">
                               {activity.refActivityNo || "-"}
                             </TableCell>
-                            <TableCell className="text-xs">
+                            <TableCell className="text-xs py-1">
                               {formatSwpDateShort(activity.createDate)}
                             </TableCell>
-                            <TableCell className="text-xs">
+                            <TableCell className="text-xs py-1">
                               {activity.createEmpNo}
                             </TableCell>
                           </TableRow>
@@ -347,57 +355,53 @@ export function SwpDocumentDetailDialog({
                 </div>
 
                 {/* 파일 목록 (아래) */}
-                <div className="border rounded-lg overflow-hidden" style={{ height: "250px" }}>
-                  <div className="p-3 bg-muted/50 border-b">
-                    <h3 className="font-semibold text-sm">파일 목록</h3>
+                <div className="border rounded-lg overflow-hidden h-[30vh] flex flex-col">
+                  <div className="px-3 py-1.5 bg-muted/50 border-b flex-shrink-0">
+                    <h3 className="font-semibold text-xs">파일 목록</h3>
                     {selectedActivity ? (
-                      <>
-                        <p className="text-xs text-muted-foreground mt-1">
-                          Activity: {selectedActivity.actvNo}
-                        </p>
-                        <p className="text-xs text-muted-foreground">
-                          Rev {selectedActivity.revNo} ({selectedActivity.stage}) / {selectedActivity.inOut}
-                        </p>
-                      </>
+                      <p className="text-[10px] text-muted-foreground mt-0.5">
+                        Activity: {selectedActivity.actvNo} / Rev {selectedActivity.revNo} ({selectedActivity.stage}) / {selectedActivity.inOut}
+                      </p>
                     ) : (
-                      <p className="text-xs text-muted-foreground mt-1">
+                      <p className="text-[10px] text-muted-foreground mt-0.5">
                         Activity를 선택하면 파일 목록이 표시됩니다
                       </p>
                     )}
                   </div>
-                  <div className="overflow-auto p-3" style={{ height: "calc(250px - 80px)" }}>
+                  <div className="overflow-auto flex-1">
                     {selectedActivity ? (
                       isLoadingFiles ? (
                         <div className="flex items-center justify-center h-full">
-                          <Loader2 className="h-5 w-5 animate-spin" />
-                          <span className="ml-2 text-sm">파일 로딩 중...</span>
+                          <Loader2 className="h-4 w-4 animate-spin" />
+                          <span className="ml-2 text-xs">파일 로딩 중...</span>
                         </div>
                       ) : activityFiles.length > 0 ? (
                         <Table>
-                          <TableHeader>
+                          <TableHeader className="sticky top-0 bg-background">
                             <TableRow>
-                              <TableHead className="min-w-[200px]">파일명</TableHead>
-                              <TableHead className="w-[100px]">크기</TableHead>
-                              <TableHead className="w-[120px]">날짜</TableHead>
-                              <TableHead className="w-[100px]">다운로드</TableHead>
+                              <TableHead className="min-w-[200px] text-xs h-8">파일명</TableHead>
+                              <TableHead className="w-[90px] text-xs h-8">크기</TableHead>
+                              <TableHead className="w-[100px] text-xs h-8">날짜</TableHead>
+                              <TableHead className="w-[90px] text-xs h-8">다운로드</TableHead>
                             </TableRow>
                           </TableHeader>
                           <TableBody>
                             {activityFiles.map((file) => (
-                              <TableRow key={file.FILE_SEQ}>
-                                <TableCell className="font-medium">
+                              <TableRow key={file.FILE_SEQ} className="h-8">
+                                <TableCell className="font-medium text-xs py-1">
                                   {file.FILE_NM}
                                 </TableCell>
-                                <TableCell className="text-sm text-muted-foreground">
+                                <TableCell className="text-xs text-muted-foreground py-1">
                                   {file.FILE_SZ ? formatFileSize(file.FILE_SZ) : "-"}
                                 </TableCell>
-                                <TableCell className="text-sm text-muted-foreground">
+                                <TableCell className="text-xs text-muted-foreground py-1">
                                   {file.CRTE_DTM ? formatSwpDateShort(file.CRTE_DTM) : "-"}
                                 </TableCell>
-                                <TableCell>
+                                <TableCell className="py-1">
                                   <Button
                                     variant="outline"
                                     size="sm"
+                                    className="h-6 px-2 text-[10px]"
                                     onClick={() => handleDownloadFile(file.FILE_NM, document.OWN_DOC_NO || document.DOC_NO)}
                                   >
                                     <Download className="h-3 w-3 mr-1" />
@@ -409,17 +413,17 @@ export function SwpDocumentDetailDialog({
                           </TableBody>
                         </Table>
                       ) : (
-                        <div className="flex items-center justify-center h-full text-sm text-muted-foreground">
+                        <div className="flex items-center justify-center h-full text-xs text-muted-foreground">
                           <div className="text-center">
-                            <AlertCircle className="h-8 w-8 mx-auto mb-2 opacity-50" />
+                            <AlertCircle className="h-6 w-6 mx-auto mb-1 opacity-50" />
                             <p>파일이 없습니다</p>
                           </div>
                         </div>
                       )
                     ) : (
-                      <div className="flex items-center justify-center h-full text-sm text-muted-foreground">
+                      <div className="flex items-center justify-center h-full text-xs text-muted-foreground">
                         <div className="text-center">
-                          <FileIcon className="h-12 w-12 mx-auto mb-2 opacity-30" />
+                          <FileIcon className="h-8 w-8 mx-auto mb-1 opacity-30" />
                           <p>Activity를 선택해주세요</p>
                         </div>
                       </div>
@@ -429,8 +433,8 @@ export function SwpDocumentDetailDialog({
               </>
             ) : (
               <div className="p-8 text-center text-muted-foreground">
-                <AlertCircle className="h-12 w-12 mx-auto mb-2 opacity-50" />
-                <p>Activity 정보가 없습니다</p>
+                <AlertCircle className="h-10 w-10 mx-auto mb-2 opacity-50" />
+                <p className="text-sm">Activity 정보가 없습니다</p>
               </div>
             )}
           </div>
-- 
cgit v1.2.3

