"use client"; import { useState, useEffect, useCallback } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; import { Plus, RefreshCw, Upload, Loader2 } from "lucide-react"; import { toast } from "sonner"; import { useTranslation } from "@/i18n/client"; import { UnifiedDwgReceiptItem, DetailDwgReceiptItem, FileInfoItem, fetchDetailDwgReceiptList, fetchFileInfoList, } from "../actions"; import { DrawingListTable } from "../table/drawing-list-table"; import { createDetailDrawingColumns } from "../table/detail-drawing-columns"; import { createFileListColumns } from "../table/file-list-columns"; import { AddDetailDrawingDialog } from "./add-detail-drawing-dialog"; import { UploadFilesToDetailDialog } from "./upload-files-to-detail-dialog"; interface DetailDrawingDialogProps { drawing: UnifiedDwgReceiptItem | null; open: boolean; onOpenChange: (open: boolean) => void; vendorCode: string; userId: string; userName: string; userEmail: string; drawingKind: "B3" | "B4"; lng: string; } export function DetailDrawingDialog({ drawing, open, onOpenChange, vendorCode, userId, userName, userEmail, drawingKind, lng, }: DetailDrawingDialogProps) { const { t } = useTranslation(lng, "dolce"); const [detailDrawings, setDetailDrawings] = useState([]); const [selectedDetail, setSelectedDetail] = useState(null); const [files, setFiles] = useState([]); const [isLoading, setIsLoading] = useState(false); const [isLoadingFiles, setIsLoadingFiles] = useState(false); const [addDialogOpen, setAddDialogOpen] = useState(false); const [uploadFilesDialogOpen, setUploadFilesDialogOpen] = useState(false); // 상세도면 목록 로드 const loadDetailDrawings = useCallback(async () => { if (!drawing) return; try { setIsLoading(true); const data = await fetchDetailDwgReceiptList({ project: drawing.ProjectNo, drawingNo: drawing.DrawingNo, discipline: drawing.Discipline, drawingKind: drawing.DrawingKind, userId: "", // 조회 시 모든 사용자의 상세도면을 보기 위해 빈 문자열 전달 }); setDetailDrawings(data); // 첫 번째 상세도면 자동 선택 if (data.length > 0 && !selectedDetail) { setSelectedDetail(data[0]); } } catch (error) { console.error("상세도면 로드 실패:", error); toast.error(t("detailDialog.detailLoadError")); } finally { setIsLoading(false); } }, [drawing, selectedDetail, t]); // 파일 목록 로드 const loadFiles = useCallback(async () => { if (!selectedDetail) { setFiles([]); return; } try { setIsLoadingFiles(true); const data = await fetchFileInfoList(selectedDetail.UploadId); setFiles(data); } catch (error) { console.error("파일 목록 로드 실패:", error); toast.error(t("detailDialog.fileLoadError")); } finally { setIsLoadingFiles(false); } }, [selectedDetail, t]); // 다이얼로그 열릴 때 데이터 로드 useEffect(() => { if (open && drawing) { loadDetailDrawings(); } else { setDetailDrawings([]); setSelectedDetail(null); setFiles([]); } }, [open, drawing, loadDetailDrawings]); // 선택된 상세도면 변경 시 파일 목록 로드 useEffect(() => { if (selectedDetail) { loadFiles(); } }, [selectedDetail, loadFiles]); const handleDownload = async (file: FileInfoItem) => { try { toast.info(t("detailDialog.downloadPreparing")); // 파일 생성자의 userId를 사용하여 다운로드 const response = await fetch("/api/dolce/download", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ fileId: file.FileId, userId: file.CreateUserId, // 파일 생성자의 ID 사용 fileName: file.FileName, }), }); if (!response.ok) { throw new Error(t("detailDialog.downloadError")); } const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = file.FileName; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); toast.success(t("detailDialog.downloadSuccess")); } catch (error) { console.error("파일 다운로드 실패:", error); toast.error(t("detailDialog.downloadError")); } }; const handleRefresh = () => { loadDetailDrawings(); }; const handleAddComplete = () => { setAddDialogOpen(false); loadDetailDrawings(); }; const handleUploadComplete = () => { setUploadFilesDialogOpen(false); loadFiles(); }; const fileColumns = createFileListColumns({ onDownload: handleDownload, lng }); // RegisterId + UploadId 조합으로 고유 ID 생성 const getDetailDrawingId = (detail: DetailDwgReceiptItem) => { return `${detail.RegisterId}_${detail.UploadId}`; }; // B4인 경우 "도면입수"인 건만 상세도면 추가 및 파일 첨부 가능 // B3인 경우 모든 건에 대해 가능 const canAddDetailDrawing = drawingKind === "B3" || (drawingKind === "B4" && drawing && 'DrawingMoveGbn' in drawing && drawing.DrawingMoveGbn === "도면입수"); return ( <> {t("detailDialog.title")} {drawing && ( {t("detailDialog.subtitle", { drawingNo: drawing.DrawingNo, projectNo: drawing.ProjectNo, discipline: drawing.Discipline, drawingKind: drawing.DrawingKind })} )}
{/* 상단: 상세도면 리스트 */} {t("detailDialog.detailListTitle")}
{canAddDetailDrawing && ( )}
columns={createDetailDrawingColumns(lng, t)} data={detailDrawings} onRowClick={setSelectedDetail} selectedRow={selectedDetail || undefined} getRowId={(row) => getDetailDrawingId(row)} />
{/* 하단: 첨부파일 리스트 */} {t("detailDialog.fileListTitle")} {selectedDetail && t("detailDialog.fileListSubtitle", { revNo: selectedDetail.DrawingRevNo })} {selectedDetail && canAddDetailDrawing && ( )} {!selectedDetail ? (
{t("detailDialog.selectDetailDrawing")}
) : isLoadingFiles ? (
{t("detailDialog.loadingFiles")}
) : ( )}
{selectedDetail && ( )} ); }