"use client"; import * as React from "react"; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; import { Loader } from "lucide-react"; import { toast } from "sonner"; import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, } from "@/components/ui/sheet"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage, } from "@/components/ui/form"; import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue, } from "@/components/ui/select"; import { DataTableColumnJSON } from "./form-data-table-columns"; import { updateFormDataInDB } from "@/lib/forms/services"; interface UpdateTagSheetProps extends React.ComponentPropsWithoutRef { open: boolean; onOpenChange: (open: boolean) => void; columns: DataTableColumnJSON[]; rowData: Record | null; formCode: string; contractItemId: number; /** 업데이트 성공 시 호출될 콜백 */ onUpdateSuccess?: (updatedValues: Record) => void; } export function UpdateTagSheet({ open, onOpenChange, columns, rowData, formCode, contractItemId, onUpdateSuccess, ...props }: UpdateTagSheetProps) { const [isPending, startTransition] = React.useTransition(); // 1) zod 스키마 const dynamicSchema = React.useMemo(() => { const shape: Record> = {}; for (const col of columns) { if (col.type === "NUMBER") { shape[col.key] = z .union([z.coerce.number(), z.nan()]) .transform((val) => (isNaN(val) ? undefined : val)) .optional(); } else { shape[col.key] = z.string().optional(); } } return z.object(shape); }, [columns]); // 2) form init const form = useForm({ resolver: zodResolver(dynamicSchema), defaultValues: React.useMemo(() => { if (!rowData) return {}; const defaults: Record = {}; for (const col of columns) { defaults[col.key] = rowData[col.key] ?? ""; } return defaults; }, [rowData, columns]), }); React.useEffect(() => { if (!rowData) { form.reset({}); return; } const defaults: Record = {}; for (const col of columns) { defaults[col.key] = rowData[col.key] ?? ""; } form.reset(defaults); }, [rowData, columns, form]); async function onSubmit(values: Record) { startTransition(async () => { const { success, message } = await updateFormDataInDB( formCode, contractItemId, values ); if (!success) { toast.error(message); return; } toast.success("Updated successfully!"); // (A) 수정된 값(폼 데이터)을 부모 콜백에 전달 onUpdateSuccess?.({ // rowData(원본)와 values를 합쳐서 최종 "수정된 row"를 만든다. // tagNumber는 기존 그대로 ...rowData, ...values, tagNumber: rowData?.tagNumber, }); onOpenChange(false); }); } return ( Update Row Modify the fields below and save changes
{columns.map((col) => { const isTagNumberField = col.key === "tagNumber" || col.key === "tagDescription"; return ( { switch (col.type) { case "NUMBER": return ( {col.displayLabel} { const num = parseFloat(e.target.value); field.onChange(isNaN(num) ? "" : num); }} value={field.value ?? ""} /> ); case "LIST": return ( {col.label} ); // case "date": // return ( // // {col.label} // // // // // // ) case "STRING": default: return ( {col.label} ); } }} /> ); })}
); }