"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} ) } }} /> ) })}
) }