"use client"; import { useActionState, useState } from "react"; import { Loader2Icon } from "lucide-react"; import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, } from "@/components/ui/sheet"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Field, FieldLabel, FieldError } from "@/components/ui/field"; import type { FormState } from "@/lib/server-action"; // Hanya untuk input teks biasa. Form yang butuh select, textarea, atau lookup ditulis sendiri // di _components fitur itu, jangan menambah opsi ke config ini. export type MasterField = { name: F; label: string; type?: React.HTMLInputTypeAttribute; required?: boolean; }; type MasterSheetFormProps = { action: ( prevState: FormState, formData: FormData, ) => Promise>; fields: readonly MasterField[]; defaultValues?: Partial>; hiddenFields?: Record; title: string; description: string; trigger: React.ReactElement; }; export function MasterSheetForm({ action, fields, defaultValues, hiddenFields, title, description, trigger, }: MasterSheetFormProps) { const [open, setOpen] = useState(false); const [state, formAction, pending] = useActionState( async (prevState: FormState, formData: FormData) => { const result = await action(prevState, formData); if (result.ok) setOpen(false); return result; }, { ok: false }, ); return ( {title} {description}
{hiddenFields && Object.entries(hiddenFields).map(([name, value]) => ( ))} {fields.map((field) => { const errors = state.fieldErrors?.[field.name]; return ( {field.label} {field.required && " *"} e.currentTarget.blur() : undefined } defaultValue={ state.values?.[field.name] ?? defaultValues?.[field.name] ?? "" } aria-invalid={!!errors} required={field.required} /> ({ message }))} /> ); })} {state.error && (

{state.error}

)}
); }