From 7a1524ba54f43d0f2a19e4bca2c6a2e0b01c5ef1 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Tue, 17 Jun 2025 09:02:32 +0000 Subject: (대표님) 20250617 18시 작업사항 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/b-rfq/attachment/request-revision-dialog.tsx | 205 +++ lib/b-rfq/attachment/vendor-responses-panel.tsx | 229 ++- lib/b-rfq/initial/add-initial-rfq-dialog.tsx | 326 ++-- lib/b-rfq/initial/delete-initial-rfq-dialog.tsx | 149 ++ lib/b-rfq/initial/initial-rfq-detail-columns.tsx | 358 +++-- lib/b-rfq/initial/initial-rfq-detail-table.tsx | 74 +- .../initial/initial-rfq-detail-toolbar-actions.tsx | 301 ++-- lib/b-rfq/initial/update-initial-rfq-sheet.tsx | 496 +++++++ lib/b-rfq/service.ts | 1558 ++++++++++++++++++-- lib/b-rfq/validations.ts | 139 ++ lib/b-rfq/vendor-response/comment-edit-dialog.tsx | 187 +++ .../vendor-response/response-detail-columns.tsx | 653 ++++++++ .../vendor-response/response-detail-sheet.tsx | 358 +++++ .../vendor-response/response-detail-table.tsx | 161 ++ .../vendor-response/upload-response-dialog.tsx | 325 ++++ .../vendor-responses-table-columns.tsx | 351 +++++ .../vendor-response/vendor-responses-table.tsx | 160 ++ .../vendor-response/waive-response-dialog.tsx | 210 +++ lib/mail/templates/initial-rfq-invitation.hbs | 165 +++ .../tech-sales-quotation-submitted-manager-ko.hbs | 18 +- .../tech-sales-quotation-submitted-vendor-ko.hbs | 18 +- lib/mail/templates/tech-sales-rfq-invite-ko.hbs | 35 +- .../table/vendor-quotations-table-columns.tsx | 2 +- lib/techsales-rfq/service.ts | 773 ++-------- .../table/detail-table/rfq-detail-column.tsx | 2 +- lib/welding/table/ocr-table-toolbar-actions.tsx | 667 ++++++++- 26 files changed, 6654 insertions(+), 1266 deletions(-) create mode 100644 lib/b-rfq/attachment/request-revision-dialog.tsx create mode 100644 lib/b-rfq/initial/delete-initial-rfq-dialog.tsx create mode 100644 lib/b-rfq/initial/update-initial-rfq-sheet.tsx create mode 100644 lib/b-rfq/vendor-response/comment-edit-dialog.tsx create mode 100644 lib/b-rfq/vendor-response/response-detail-columns.tsx create mode 100644 lib/b-rfq/vendor-response/response-detail-sheet.tsx create mode 100644 lib/b-rfq/vendor-response/response-detail-table.tsx create mode 100644 lib/b-rfq/vendor-response/upload-response-dialog.tsx create mode 100644 lib/b-rfq/vendor-response/vendor-responses-table-columns.tsx create mode 100644 lib/b-rfq/vendor-response/vendor-responses-table.tsx create mode 100644 lib/b-rfq/vendor-response/waive-response-dialog.tsx create mode 100644 lib/mail/templates/initial-rfq-invitation.hbs (limited to 'lib') diff --git a/lib/b-rfq/attachment/request-revision-dialog.tsx b/lib/b-rfq/attachment/request-revision-dialog.tsx new file mode 100644 index 00000000..90d5b543 --- /dev/null +++ b/lib/b-rfq/attachment/request-revision-dialog.tsx @@ -0,0 +1,205 @@ +// components/rfq/request-revision-dialog.tsx +"use client"; + +import { useState, useTransition } from "react"; +import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Textarea } from "@/components/ui/textarea"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import { AlertTriangle, Loader2 } from "lucide-react"; +import { useToast } from "@/hooks/use-toast"; +import { requestRevision } from "../service"; + +const revisionFormSchema = z.object({ + revisionReason: z + .string() + .min(10, "수정 요청 사유를 최소 10자 이상 입력해주세요") + .max(500, "수정 요청 사유는 500자를 초과할 수 없습니다"), +}); + +type RevisionFormData = z.infer; + +interface RequestRevisionDialogProps { + responseId: number; + attachmentType: string; + serialNo: string; + vendorName?: string; + currentRevision: string; + trigger?: React.ReactNode; + onSuccess?: () => void; +} + +export function RequestRevisionDialog({ + responseId, + attachmentType, + serialNo, + vendorName, + currentRevision, + trigger, + onSuccess, +}: RequestRevisionDialogProps) { + const [open, setOpen] = useState(false); + const [isPending, startTransition] = useTransition(); + const { toast } = useToast(); + + const form = useForm({ + resolver: zodResolver(revisionFormSchema), + defaultValues: { + revisionReason: "", + }, + }); + + const handleOpenChange = (newOpen: boolean) => { + setOpen(newOpen); + // 다이얼로그가 닫힐 때 form 리셋 + if (!newOpen) { + form.reset(); + } + }; + + const handleCancel = () => { + form.reset(); + setOpen(false); + }; + + const onSubmit = async (data: RevisionFormData) => { + startTransition(async () => { + try { + const result = await requestRevision(responseId, data.revisionReason); + + if (!result.success) { + throw new Error(result.message); + } + + toast({ + title: "수정 요청 완료", + description: result.message, + }); + + setOpen(false); + form.reset(); + onSuccess?.(); + + } catch (error) { + console.error("Request revision error:", error); + toast({ + title: "수정 요청 실패", + description: error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다.", + variant: "destructive", + }); + } + }); + }; + + return ( + + + {trigger || ( + + )} + + + + + + 수정 요청 + +
+ {serialNo} + {attachmentType} + {currentRevision} + {vendorName && ( + <> + + {vendorName} + + )} +
+
+ +
+
+
+ +
+

수정 요청 안내

+

+ 벤더에게 현재 제출된 응답에 대한 수정을 요청합니다. + 수정 요청 후 벤더는 새로운 파일을 다시 제출할 수 있습니다. +

+
+
+
+ +
+ + ( + + + 수정 요청 사유 * + + +