"use client"; import * as React from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { format } from "date-fns"; import { ko } from "date-fns/locale/ko"; import { toast } from "sonner"; import { Loader2, CalendarIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter, SheetClose } from "@/components/ui/sheet"; import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover"; import { Calendar } from "@/components/ui/calendar"; import { cn } from "@/lib/utils"; import { updateTechSalesRfq, getTechSalesRfqById } from "@/lib/techsales-rfq/service"; import { getProjectSeriesForProject } from "@/lib/bidding-projects/service"; import { type ProjectSeries } from "@/db/schema/projects"; // Zod schema for form validation const updateRfqSchema = z.object({ rfqId: z.number().min(1, "RFQ ID is required"), description: z.string(), remark: z.string(), dueDate: z.string(), }); type UpdateRfqSchema = z.infer; interface UpdateSheetProps { open: boolean; onOpenChange?: (open: boolean) => void; rfqId: number; onUpdated?: () => void; } export default function UpdateSheet({ open, onOpenChange, rfqId, onUpdated }: UpdateSheetProps) { const [isPending, startTransition] = React.useTransition(); const [projectInfo, setProjectInfo] = React.useState({ projNm: "", sector: "", projMsrm: "", ptypeNm: "", rfqNo: "", pspid: "", }); const [rfqInfo, setRfqInfo] = React.useState({ status: "", createdAt: "", updatedAt: "", createdByName: "", updatedByName: "", sentByName: "", rfqSendDate: "", }); const [seriesInfo, setSeriesInfo] = React.useState([]); const [isLoading, setIsLoading] = React.useState(false); const [isLoadingSeries, setIsLoadingSeries] = React.useState(false); // K/L 날짜를 4분기로 변환하는 함수 const convertKLToQuarter = React.useCallback((klDate: string | null): string => { if (!klDate) return "정보 없음" try { // YYYYMMDD 형식의 날짜를 파싱 const year = parseInt(klDate.substring(0, 4)) const month = parseInt(klDate.substring(4, 6)) // 4분기 계산 (1-3월: 1Q, 4-6월: 2Q, 7-9월: 3Q, 10-12월: 4Q) const quarter = Math.ceil(month / 3) return `${year} ${quarter}Q` } catch (error) { console.error("K/L 날짜 변환 오류:", error) return "날짜 오류" } }, []) // Initialize form with React Hook Form and Zod const form = useForm({ resolver: zodResolver(updateRfqSchema), defaultValues: { rfqId, description: "", remark: "", dueDate: "", }, }); // Load RFQ data when sheet opens React.useEffect(() => { if (open && rfqId) { loadRfqData(); } }, [open, rfqId]); const loadRfqData = async () => { try { setIsLoading(true); const result = await getTechSalesRfqById(rfqId); if (result.error) { toast.error(result.error); onOpenChange?.(false); return; } if (result.data) { form.reset({ rfqId, description: result.data.description || "", remark: result.data.remark || "", dueDate: result.data.dueDate ? new Date(result.data.dueDate).toISOString().slice(0, 10) : "", }); const pspid = result.data.project[0].pspid || ""; setProjectInfo({ projNm: result.data.project[0].projectName || "", sector: result.data.project[0].pjtType || "", projMsrm: result.data.project[0].projMsrm || "", ptypeNm: result.data.project[0].ptypeNm || "", rfqNo: result.data.rfqCode || "", pspid: pspid, }); setRfqInfo({ status: result.data.status || "", createdAt: result.data.createdAt ? format(new Date(result.data.createdAt), "yyyy-MM-dd HH:mm") : "", updatedAt: result.data.updatedAt ? format(new Date(result.data.updatedAt), "yyyy-MM-dd HH:mm") : "", createdByName: (result.data as any).createdByName || (result.data as any).createdBy || "", updatedByName: (result.data as any).updatedByName || (result.data as any).updatedBy || "", sentByName: (result.data as any).sentByName || (result.data as any).sentBy || "", rfqSendDate: result.data.rfqSendDate ? format(new Date(result.data.rfqSendDate), "yyyy-MM-dd HH:mm") : "", }); // 시리즈 정보 로드 if (pspid) { setIsLoadingSeries(true); try { const seriesResult = await getProjectSeriesForProject(pspid); setSeriesInfo(seriesResult); } catch (error) { console.error("시리즈 정보 로드 오류:", error); setSeriesInfo([]); } finally { setIsLoadingSeries(false); } } else { setSeriesInfo([]); } } } catch (error: any) { toast.error("RFQ 정보를 불러오는 중 오류가 발생했습니다: " + error.message); onOpenChange?.(false); } finally { setIsLoading(false); } }; // Form submission handler with debug logs async function onSubmit(values: UpdateRfqSchema) { console.log("Form submitted with values:", values); startTransition(async () => { try { console.log("Submitting RFQ update for ID:", values.rfqId); const result = await updateTechSalesRfq({ id: values.rfqId, description: values.description, remark: values.remark, dueDate: new Date(values.dueDate), updatedBy: 1, // Replace with actual user ID }); if (result.error) { console.error("Update error:", result.error); toast.error(result.error); } else { console.log("RFQ updated successfully"); toast.success("RFQ가 성공적으로 업데이트되었습니다!"); onUpdated?.(); onOpenChange?.(false); form.reset(); } } catch (error: any) { console.error("Update failed with error:", error.message); toast.error("업데이트 중 오류 발생: " + error.message); } }); } // Debug form errors on change React.useEffect(() => { const subscription = form.watch(() => { console.log("Form values changed:", form.getValues()); console.log("Form errors:", form.formState.errors); }); return () => subscription.unsubscribe(); }, [form]); return ( RFQ 미리보기 RFQ 정보를 확인하고 필요한 항목을 수정하세요. RFQ Title, Context, 마감일만 수정 가능합니다.
{isLoading ? (
) : (
{/* 프로젝트 정보 */}

프로젝트 정보

프로젝트명: {projectInfo.projNm}
섹터: {projectInfo.sector}
척수: {projectInfo.projMsrm}
선종: {projectInfo.ptypeNm}
RFQ No: {projectInfo.rfqNo}
{/* 시리즈 정보 - 프로젝트 정보 아래에 배치 */}

시리즈 정보

{isLoadingSeries ? (
시리즈 정보 로딩 중...
) : seriesInfo && seriesInfo.length > 0 ? (
{seriesInfo.map((series) => (
시리즈번호:
{series.sersNo}
K/L (Keel Laying):
{convertKLToQuarter(series.klDt)}
도크코드:
{series.dockNo || "N/A"}
도크명:
{series.dockNm || "N/A"}
))}
) : (
시리즈 데이터가 없습니다.
)}
{/* RFQ 정보 */} {/*

RFQ 정보

상태: {rfqInfo.status}
생성자: {rfqInfo.createdByName}
생성일: {rfqInfo.createdAt}
수정자: {rfqInfo.updatedByName}
수정일: {rfqInfo.updatedAt}
발송자: {rfqInfo.sentByName}
발송일: {rfqInfo.rfqSendDate}
*/}
( RFQ Title )} /> ( RFQ Context