diff options
| author | joonhoekim <26rote@gmail.com> | 2025-11-27 13:48:44 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-11-27 13:48:44 +0900 |
| commit | b43b1d92ef3d7e57b5df5cd72f75dc3a1c3f1c7a (patch) | |
| tree | 943e2a52c9e56bdce2fa3a35ef61b795370f47e0 /lib/dolce/dialogs/add-and-modify-detail-drawing-dialog.tsx | |
| parent | 79cfa7ea8f21ae227dbb2843ae536fe876ba7c55 (diff) | |
(김준회) swp 파일 개수 컬럼 삭제 (API에서 주지 않는 데이터), dolce rebuild 에서 상태값 수정, bulk upload MatchBatchFileDwg API 사용해 Edit 으로 보내도록 수정 (Category, status 하드코딩 값 넣어주도록 처리), 상세도면, 파일 추가시 확인 다이얼로그 추가
Diffstat (limited to 'lib/dolce/dialogs/add-and-modify-detail-drawing-dialog.tsx')
| -rw-r--r-- | lib/dolce/dialogs/add-and-modify-detail-drawing-dialog.tsx | 415 |
1 files changed, 244 insertions, 171 deletions
diff --git a/lib/dolce/dialogs/add-and-modify-detail-drawing-dialog.tsx b/lib/dolce/dialogs/add-and-modify-detail-drawing-dialog.tsx index 673d48d6..0253228b 100644 --- a/lib/dolce/dialogs/add-and-modify-detail-drawing-dialog.tsx +++ b/lib/dolce/dialogs/add-and-modify-detail-drawing-dialog.tsx @@ -72,6 +72,8 @@ export function AddAndModifyDetailDrawingDialog({ const [comment, setComment] = useState<string>(""); const [isSubmitting, setIsSubmitting] = useState(false); + const [showConfirmation, setShowConfirmation] = useState(false); + // Edit 모드일 때 초기값 설정 useEffect(() => { if (mode === "edit" && detailDrawing && open) { @@ -155,9 +157,10 @@ export function AddAndModifyDetailDrawingDialog({ setRevisionError(""); setComment(""); clearFiles(); + setShowConfirmation(false); }; - // 제출 + // 제출 (확인 단계 포함) const handleSubmit = async () => { // 유효성 검사 if (!registerKind) { @@ -200,6 +203,12 @@ export function AddAndModifyDetailDrawingDialog({ return; } + // 확인 단계가 아니면 확인 단계로 이동 + if (!showConfirmation) { + setShowConfirmation(true); + return; + } + try { setIsSubmitting(true); @@ -212,7 +221,7 @@ export function AddAndModifyDetailDrawingDialog({ dwgList: [ { Mode: "ADD", - Status: "Submitted", + Status: "Standby", RegisterId: 0, ProjectNo: drawing.ProjectNo, Discipline: drawing.Discipline, @@ -329,8 +338,12 @@ export function AddAndModifyDetailDrawingDialog({ }; const handleCancel = () => { - resetForm(); - onOpenChange(false); + if (showConfirmation) { + setShowConfirmation(false); + } else { + resetForm(); + onOpenChange(false); + } }; // DrawingUsage가 변경되면 RegisterKind 초기화 @@ -355,219 +368,279 @@ export function AddAndModifyDetailDrawingDialog({ return ( <Dialog open={open} onOpenChange={onOpenChange}> - <DialogContent className="max-w-2xl"> + <DialogContent className="max-w-2xl max-h-[85vh] overflow-y-auto"> <DialogHeader> <DialogTitle> - {mode === "edit" ? t("editDetailDialog.title") : t("addDetailDialog.title")} + {showConfirmation + ? t("addDetailDialog.confirmTitle", "확인") + : (mode === "edit" ? t("editDetailDialog.title") : t("addDetailDialog.title")) + } </DialogTitle> </DialogHeader> - <div className="space-y-6"> - {/* 도면 정보 표시 */} - {mode === "add" && drawing && ( + {showConfirmation ? ( + <div className="space-y-6"> <Alert> <Info className="h-4 w-4" /> <AlertDescription> - <div className="font-medium">{drawing.DrawingNo}</div> - <div className="text-sm text-muted-foreground">{drawing.DrawingName}</div> + {t("addDetailDialog.confirmMessage", "아래 내용으로 제출하시겠습니까?")} </AlertDescription> </Alert> - )} - {mode === "edit" && detailDrawing && ( - <Alert> - <Info className="h-4 w-4" /> - <AlertDescription> - <div className="font-medium">{detailDrawing.DrawingNo} - Rev. {detailDrawing.DrawingRevNo}</div> - <div className="text-sm text-muted-foreground">{detailDrawing.DrawingName}</div> - </AlertDescription> - </Alert> - )} + <div className="grid grid-cols-2 gap-4 border rounded-lg p-4 bg-muted/20"> + <div className="space-y-1"> + <Label className="text-xs text-muted-foreground">{t("addDetailDialog.drawingUsageLabel")}</Label> + <p className="text-sm font-medium"> + {drawingUsageOptions.find(opt => opt.value === drawingUsage)?.label || drawingUsage} + </p> + </div> + <div className="space-y-1"> + <Label className="text-xs text-muted-foreground">{t("addDetailDialog.registerKindLabel")}</Label> + <p className="text-sm font-medium"> + {registerKindOptions.find(opt => opt.value === registerKind)?.label || registerKind} + </p> + </div> + {drawingUsage !== "CMT" && ( + <div className="space-y-1"> + <Label className="text-xs text-muted-foreground">{t("addDetailDialog.revisionLabel")}</Label> + <p className="text-sm font-medium">{revision}</p> + </div> + )} + <div className="space-y-1 col-span-2"> + <Label className="text-xs text-muted-foreground">{t("addDetailDialog.commentLabel")}</Label> + <p className="text-sm">{comment || "-"}</p> + </div> + </div> + + {files.length > 0 && ( + <div className="space-y-2"> + <Label>{t("addDetailDialog.selectedFiles", { count: files.length })}</Label> + <div className="max-h-60 overflow-y-auto space-y-2 border rounded-lg p-2"> + {isSubmitting ? ( + <FileUploadProgressList fileProgresses={fileProgresses} /> + ) : ( + files.map((file, index) => ( + <div key={index} className="flex items-center gap-2 p-2 rounded bg-muted/50 text-sm"> + <FileIcon className="h-4 w-4 text-muted-foreground shrink-0" /> + <span className="truncate flex-1">{file.name}</span> + <span className="text-xs text-muted-foreground whitespace-nowrap"> + {(file.size / 1024 / 1024).toFixed(2)} MB + </span> + </div> + )) + )} + </div> + </div> + )} + </div> + ) : ( + <div className="space-y-6"> + {/* 도면 정보 표시 */} + {mode === "add" && drawing && ( + <Alert> + <Info className="h-4 w-4" /> + <AlertDescription> + <div className="font-medium">{drawing.DrawingNo}</div> + <div className="text-sm text-muted-foreground">{drawing.DrawingName}</div> + </AlertDescription> + </Alert> + )} + + {mode === "edit" && detailDrawing && ( + <Alert> + <Info className="h-4 w-4" /> + <AlertDescription> + <div className="font-medium">{detailDrawing.DrawingNo} - Rev. {detailDrawing.DrawingRevNo}</div> + <div className="text-sm text-muted-foreground">{detailDrawing.DrawingName}</div> + </AlertDescription> + </Alert> + )} - {/* 도면용도 선택 (Add 모드에서만 표시) */} - {mode === "add" && ( + {/* 도면용도 선택 (Add 모드에서만 표시) */} + {mode === "add" && ( + <div className="space-y-2"> + <Label>{t("addDetailDialog.drawingUsageLabel")}</Label> + <Select value={drawingUsage} onValueChange={handleDrawingUsageChange}> + <SelectTrigger> + <SelectValue placeholder={t("addDetailDialog.drawingUsagePlaceholder")} /> + </SelectTrigger> + <SelectContent> + {drawingUsageOptions.map((option) => ( + <SelectItem key={option.value} value={option.value}> + {option.label} + </SelectItem> + ))} + </SelectContent> + </Select> + </div> + )} + + {/* 등록종류 선택 */} <div className="space-y-2"> - <Label>{t("addDetailDialog.drawingUsageLabel")}</Label> - <Select value={drawingUsage} onValueChange={handleDrawingUsageChange}> + <Label>{t("addDetailDialog.registerKindLabel")}</Label> + <Select + value={registerKind} + onValueChange={setRegisterKind} + disabled={mode === "add" && !drawingUsage} + > <SelectTrigger> - <SelectValue placeholder={t("addDetailDialog.drawingUsagePlaceholder")} /> + <SelectValue placeholder={t("addDetailDialog.registerKindPlaceholder")} /> </SelectTrigger> <SelectContent> - {drawingUsageOptions.map((option) => ( + {registerKindOptions.map((option) => ( <SelectItem key={option.value} value={option.value}> {option.label} </SelectItem> ))} </SelectContent> </Select> + {revisionRule && ( + <p className="text-sm text-muted-foreground"> + {t("addDetailDialog.revisionFormatPrefix")}{revisionRule} + </p> + )} </div> - )} - - {/* 등록종류 선택 */} - <div className="space-y-2"> - <Label>{t("addDetailDialog.registerKindLabel")}</Label> - <Select - value={registerKind} - onValueChange={setRegisterKind} - disabled={mode === "add" && !drawingUsage} - > - <SelectTrigger> - <SelectValue placeholder={t("addDetailDialog.registerKindPlaceholder")} /> - </SelectTrigger> - <SelectContent> - {registerKindOptions.map((option) => ( - <SelectItem key={option.value} value={option.value}> - {option.label} - </SelectItem> - ))} - </SelectContent> - </Select> - {revisionRule && ( - <p className="text-sm text-muted-foreground"> - {t("addDetailDialog.revisionFormatPrefix")}{revisionRule} - </p> + + {/* Revision 입력 */} + {drawingUsage !== "CMT" && ( + <div className="space-y-2"> + <Label>{t("addDetailDialog.revisionLabel")}</Label> + <Input + value={revision} + onChange={(e) => handleRevisionChange(e.target.value)} + placeholder={t("addDetailDialog.revisionPlaceholder")} + disabled={!registerKind} + className={revisionError ? "border-red-500 focus-visible:ring-red-500" : ""} + /> + {revisionError && ( + <p className="text-sm text-red-500 flex items-center gap-1"> + {revisionError} + </p> + )} + {!revisionError && revision && ( + <p className="text-sm text-green-600 flex items-center gap-1"> + {t("addDetailDialog.revisionValid")} + </p> + )} + </div> )} - </div> - {/* Revision 입력 */} - {drawingUsage !== "CMT" && ( + {/* Comment 입력 */} <div className="space-y-2"> - <Label>{t("addDetailDialog.revisionLabel")}</Label> - <Input - value={revision} - onChange={(e) => handleRevisionChange(e.target.value)} - placeholder={t("addDetailDialog.revisionPlaceholder")} - disabled={!registerKind} - className={revisionError ? "border-red-500 focus-visible:ring-red-500" : ""} + <Label>{t("addDetailDialog.commentLabel")}</Label> + <Textarea + value={comment} + onChange={(e) => setComment(e.target.value)} + placeholder={t("addDetailDialog.commentPlaceholder")} + rows={3} + className="resize-none" /> - {revisionError && ( - <p className="text-sm text-red-500 flex items-center gap-1"> - {revisionError} - </p> - )} - {!revisionError && revision && ( - <p className="text-sm text-green-600 flex items-center gap-1"> - {t("addDetailDialog.revisionValid")} - </p> - )} + <p className="text-xs text-muted-foreground"> + {t("addDetailDialog.commentMaxLength")} + </p> </div> - )} - - {/* Comment 입력 */} - <div className="space-y-2"> - <Label>{t("addDetailDialog.commentLabel")}</Label> - <Textarea - value={comment} - onChange={(e) => setComment(e.target.value)} - placeholder={t("addDetailDialog.commentPlaceholder")} - rows={3} - className="resize-none" - /> - <p className="text-xs text-muted-foreground"> - {t("addDetailDialog.commentMaxLength")} - </p> - </div> - {/* 파일 업로드 (Add 모드에서만 표시) */} - {mode === "add" && ( - <div className="space-y-2"> - <Label>{t("addDetailDialog.attachmentLabel")}</Label> - <div - {...getRootProps()} - className={` - border-2 border-dashed rounded-lg p-8 text-center cursor-pointer - transition-colors - ${isDragActive ? "border-primary bg-primary/5" : "border-muted-foreground/25"} - ${files.length > 0 ? "py-4" : ""} - `} - > - <input {...getInputProps()} /> - {files.length === 0 ? ( - <div className="space-y-2"> - <Upload className="h-8 w-8 mx-auto text-muted-foreground" /> - <div> + {/* 파일 업로드 (Add 모드에서만 표시) */} + {mode === "add" && ( + <div className="space-y-2"> + <Label>{t("addDetailDialog.attachmentLabel")}</Label> + <div + {...getRootProps()} + className={` + border-2 border-dashed rounded-lg p-8 text-center cursor-pointer + transition-colors + ${isDragActive ? "border-primary bg-primary/5" : "border-muted-foreground/25"} + ${files.length > 0 ? "py-4" : ""} + `} + > + <input {...getInputProps()} /> + {files.length === 0 ? ( + <div className="space-y-2"> + <Upload className="h-8 w-8 mx-auto text-muted-foreground" /> + <div> + <p className="text-sm font-medium"> + {t("addDetailDialog.dragDropText")} + </p> + <p className="text-xs text-muted-foreground"> + {t("addDetailDialog.fileInfo")} + </p> + </div> + </div> + ) : ( + <div className="space-y-2"> <p className="text-sm font-medium"> - {t("addDetailDialog.dragDropText")} + {t("addDetailDialog.filesSelected", { count: files.length })} </p> <p className="text-xs text-muted-foreground"> - {t("addDetailDialog.fileInfo")} + {t("addDetailDialog.addMoreFiles")} </p> </div> - </div> - ) : ( - <div className="space-y-2"> - <p className="text-sm font-medium"> - {t("addDetailDialog.filesSelected", { count: files.length })} - </p> - <p className="text-xs text-muted-foreground"> - {t("addDetailDialog.addMoreFiles")} - </p> - </div> - )} - </div> + )} + </div> - {/* 선택된 파일 목록 */} - {files.length > 0 && ( - <div className="space-y-2 mt-4"> - {isSubmitting ? ( - // 업로드 중: 진행도 표시 - <FileUploadProgressList fileProgresses={fileProgresses} /> - ) : ( - // 대기 중: 삭제 버튼 표시 - <> - <div className="flex items-center justify-between mb-2"> - <h4 className="text-sm font-medium"> - {t("addDetailDialog.selectedFiles", { count: files.length })} - </h4> - <Button - variant="ghost" - size="sm" - onClick={clearFiles} - > - {t("addDetailDialog.removeAll")} - </Button> - </div> - <div className="max-h-60 overflow-y-auto space-y-2"> - {files.map((file, index) => ( - <div - key={index} - className="flex items-center gap-2 p-2 border rounded-lg bg-muted/50" + {/* 선택된 파일 목록 */} + {files.length > 0 && ( + <div className="space-y-2 mt-4"> + {isSubmitting ? ( + // 업로드 중: 진행도 표시 + <FileUploadProgressList fileProgresses={fileProgresses} /> + ) : ( + // 대기 중: 삭제 버튼 표시 + <> + <div className="flex items-center justify-between mb-2"> + <h4 className="text-sm font-medium"> + {t("addDetailDialog.selectedFiles", { count: files.length })} + </h4> + <Button + variant="ghost" + size="sm" + onClick={clearFiles} > - <FileIcon className="h-4 w-4 text-muted-foreground shrink-0" /> - <div className="flex-1 min-w-0"> - <p className="text-sm truncate">{file.name}</p> - <p className="text-xs text-muted-foreground"> - {(file.size / 1024 / 1024).toFixed(2)} MB - </p> - </div> - <Button - variant="ghost" - size="sm" - onClick={() => removeFile(index)} + {t("addDetailDialog.removeAll")} + </Button> + </div> + <div className="max-h-60 overflow-y-auto space-y-2"> + {files.map((file, index) => ( + <div + key={index} + className="flex items-center gap-2 p-2 border rounded-lg bg-muted/50" > - <X className="h-4 w-4" /> - </Button> - </div> - ))} - </div> - </> - )} + <FileIcon className="h-4 w-4 text-muted-foreground shrink-0" /> + <div className="flex-1 min-w-0"> + <p className="text-sm truncate">{file.name}</p> + <p className="text-xs text-muted-foreground"> + {(file.size / 1024 / 1024).toFixed(2)} MB + </p> + </div> + <Button + variant="ghost" + size="sm" + onClick={() => removeFile(index)} + > + <X className="h-4 w-4" /> + </Button> + </div> + ))} + </div> + </> + )} + </div> + )} </div> )} - </div> - )} - </div> + </div> + )} <DialogFooter> <Button variant="outline" onClick={handleCancel} disabled={isSubmitting}> - {t("addDetailDialog.cancelButton")} + {showConfirmation ? t("addDetailDialog.backButton", "뒤로") : t("addDetailDialog.cancelButton")} </Button> <Button onClick={handleSubmit} disabled={isSubmitting || !isFormValid}> {isSubmitting ? t("addDetailDialog.processingButton") - : mode === "edit" - ? t("editDetailDialog.updateButton") - : t("addDetailDialog.addButton") + : showConfirmation + ? t("addDetailDialog.confirmSubmit", "제출") + : t("addDetailDialog.nextButton", "다음") } </Button> </DialogFooter> |
