summaryrefslogtreecommitdiff
path: root/lib/swp/table/swp-document-detail-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/swp/table/swp-document-detail-dialog.tsx')
-rw-r--r--lib/swp/table/swp-document-detail-dialog.tsx176
1 files changed, 90 insertions, 86 deletions
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>