From 65a68325658401dd8a90ea900c1542c17c63d7ce Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Mon, 27 Oct 2025 09:49:34 +0900 Subject: (김준회) swp-upload 다이얼로그로 결과 알림, vendorCode 자동 선택 처리 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/swp/table/swp-table-toolbar.tsx | 179 ++++++++++++++--------------- lib/swp/table/swp-upload-result-dialog.tsx | 108 +++++++++++++++++ 2 files changed, 193 insertions(+), 94 deletions(-) create mode 100644 lib/swp/table/swp-upload-result-dialog.tsx (limited to 'lib') diff --git a/lib/swp/table/swp-table-toolbar.tsx b/lib/swp/table/swp-table-toolbar.tsx index 03082b26..fc8337f5 100644 --- a/lib/swp/table/swp-table-toolbar.tsx +++ b/lib/swp/table/swp-table-toolbar.tsx @@ -3,13 +3,6 @@ import { useState, useTransition, useMemo } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; import { Popover, PopoverContent, @@ -23,17 +16,20 @@ import { useRouter } from "next/navigation"; import { cn } from "@/lib/utils"; import { useRef } from "react"; import { SwpUploadHelpDialog } from "./swp-help-dialog"; +import { SwpUploadResultDialog } from "./swp-upload-result-dialog"; interface SwpTableToolbarProps { filters: SwpTableFilters; onFiltersChange: (filters: SwpTableFilters) => void; projects?: Array<{ PROJ_NO: string; PROJ_NM: string }>; + vendorCode?: string; // 벤더가 접속했을 때 고정할 벤더 코드 } export function SwpTableToolbar({ filters, onFiltersChange, projects = [], + vendorCode, }: SwpTableToolbarProps) { const [isSyncing, startSync] = useTransition(); const [isUploading, startUpload] = useTransition(); @@ -43,6 +39,8 @@ export function SwpTableToolbar({ const [projectSearchOpen, setProjectSearchOpen] = useState(false); const [projectSearch, setProjectSearch] = useState(""); const fileInputRef = useRef(null); + const [uploadResults, setUploadResults] = useState>([]); + const [showResultDialog, setShowResultDialog] = useState(false); // 동기화 핸들러 const handleSync = () => { @@ -96,7 +94,7 @@ export function SwpTableToolbar({ const handleUploadFiles = () => { // 프로젝트와 벤더 코드 체크 const projectNo = localFilters.projNo; - const vndrCd = localFilters.vndrCd; + const vndrCd = vendorCode || localFilters.vndrCd; if (!projectNo) { toast({ @@ -130,7 +128,7 @@ export function SwpTableToolbar({ } const projectNo = localFilters.projNo!; - const vndrCd = localFilters.vndrCd!; + const vndrCd = vendorCode || localFilters.vndrCd!; startUpload(async () => { try { @@ -153,41 +151,27 @@ export function SwpTableToolbar({ // 서버 액션 호출 const result = await uploadSwpFilesAction(projectNo, vndrCd, fileInfos); - if (result.success) { - toast({ - title: "업로드 완료", - description: result.message, - }); + // 결과 저장 및 다이얼로그 표시 + setUploadResults(result.details); + setShowResultDialog(true); - // 페이지 새로고침 + // 성공한 파일이 있으면 페이지 새로고침 + const successCount = result.details.filter((d) => d.success).length; + if (successCount > 0) { router.refresh(); - } else { - toast({ - variant: "destructive", - title: "업로드 실패", - description: result.message, - }); - } - - // 실패한 파일이 있으면 상세 정보 표시 - const failedFiles = result.details.filter((d) => !d.success); - if (failedFiles.length > 0) { - console.error("실패한 파일:", failedFiles); - failedFiles.forEach((f) => { - toast({ - variant: "destructive", - title: `${f.fileName} 업로드 실패`, - description: f.error || "알 수 없는 오류", - }); - }); } } catch (error) { console.error("파일 업로드 실패:", error); - toast({ - variant: "destructive", - title: "업로드 실패", - description: error instanceof Error ? error.message : "알 수 없는 오류", - }); + + // 예외 발생 시에도 결과 다이얼로그 표시 + const errorResults = Array.from(selectedFiles).map((file) => ({ + fileName: file.name, + success: false, + error: error instanceof Error ? error.message : "알 수 없는 오류", + })); + + setUploadResults(errorResults); + setShowResultDialog(true); } finally { // 파일 입력 초기화 if (fileInputRef.current) { @@ -222,46 +206,59 @@ export function SwpTableToolbar({ }, [projects, projectSearch]); return ( -
- {/* 상단 액션 바 */} -
-
- - -
+ <> + {/* 업로드 결과 다이얼로그 */} + + +
+ {/* 상단 액션 바 */} +
+
+ +
-
- SWP 문서 관리 시스템 -
-
- - +
+ SWP 문서 관리 시스템 +
- +
+ {/* 벤더만 파일 업로드 기능 사용 가능 */} + {vendorCode && ( + <> + + + + + + )} +
-
{/* 검색 필터 */}
@@ -423,33 +420,26 @@ export function SwpTableToolbar({ setLocalFilters({ ...localFilters, vndrCd: e.target.value }) } + disabled={!!vendorCode} // 벤더 코드가 제공되면 입력 비활성화 + className={vendorCode ? "bg-muted" : ""} />
{/* 스테이지 */}
- + setLocalFilters({ ...localFilters, stage: e.target.value }) } - > - - - - - 전체 - IFA - IFC - AFC - BFC - - + />
@@ -459,8 +449,9 @@ export function SwpTableToolbar({ 검색
+
- + ); } diff --git a/lib/swp/table/swp-upload-result-dialog.tsx b/lib/swp/table/swp-upload-result-dialog.tsx new file mode 100644 index 00000000..7b79fa68 --- /dev/null +++ b/lib/swp/table/swp-upload-result-dialog.tsx @@ -0,0 +1,108 @@ +"use client"; + +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { CheckCircle2, XCircle, FileText } from "lucide-react"; +import { ScrollArea } from "@/components/ui/scroll-area"; + +interface UploadResult { + fileName: string; + success: boolean; + error?: string; +} + +interface SwpUploadResultDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + results: UploadResult[]; +} + +export function SwpUploadResultDialog({ + open, + onOpenChange, + results, +}: SwpUploadResultDialogProps) { + const successCount = results.filter((r) => r.success).length; + const failCount = results.filter((r) => !r.success).length; + const totalCount = results.length; + + return ( + + + + 파일 업로드 결과 + + 총 {totalCount}개 파일 중 성공 {successCount}개, 실패 {failCount}개 + + + + +
+ {results.map((result, index) => ( +
+
+ {result.success ? ( + + ) : ( + + )} +
+ +
+
+ + + {result.fileName} + +
+ + {result.success ? ( +

+ 업로드 성공 +

+ ) : ( +
+

+ 업로드 실패 +

+ {result.error && ( +

+ 사유: {result.error} +

+ )} +
+ )} +
+
+ ))} +
+
+ +
+
+ {failCount > 0 && ( + + 실패한 파일을 확인하고 다시 업로드해주세요. + + )} +
+ +
+
+
+ ); +} + -- cgit v1.2.3