"use client" import * as React from "react" import { useForm, useWatch } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from "@/components/ui/dialog" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { createTagSchema, type CreateTagSchema } from "@/lib/tags/validations" import { createTag } from "@/lib/tags/service" import { toast } from "sonner" import { Loader2 } from "lucide-react" import { cn } from "@/lib/utils" import { useRouter } from "next/navigation" // Popover + Command import { Popover, PopoverTrigger, PopoverContent, } from "@/components/ui/popover" import { Command, CommandInput, CommandList, CommandGroup, CommandItem, CommandEmpty, } from "@/components/ui/command" import { ChevronsUpDown, Check } from "lucide-react" // The dynamic Tag Type definitions import { tagTypeDefinitions } from "./tag-type-definitions" // Add Select component for dropdown fields import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { ScrollArea } from "@/components/ui/scroll-area" interface AddTagDialogProps { selectedPackageId: number | null } export function AddTagDialog({ selectedPackageId }: AddTagDialogProps) { const [open, setOpen] = React.useState(false) const [isPending, startTransition] = React.useTransition() const router = useRouter() const form = useForm({ resolver: zodResolver(createTagSchema), defaultValues: { tagType: "", // user picks tagNo: "", // auto-generated description: "", functionCode: "", seqNumber: "", valveAcronym: "", processUnit: "", }, }) const watchAll = useWatch({ control: form.control }) // 1) Find the selected tag type definition const currentTagTypeDef = React.useMemo(() => { return tagTypeDefinitions.find((def) => def.id === watchAll.tagType) || null }, [watchAll.tagType]) // 2) Whenever the user changes sub-fields, re-generate `tagNo` React.useEffect(() => { if (!currentTagTypeDef) { // if no type selected, no auto-generation return } // Prevent infinite loop by excluding tagNo from the watched dependencies // This is crucial because setting tagNo would trigger another update const { tagNo, ...fieldsToWatch } = watchAll const newTagNo = currentTagTypeDef.generateTagNo(fieldsToWatch as CreateTagSchema) // Only update if different to avoid unnecessary re-renders if (form.getValues("tagNo") !== newTagNo) { form.setValue("tagNo", newTagNo, { shouldValidate: false }) } }, [currentTagTypeDef, watchAll, form]) // Check if tag number is valid (doesn't contain '??' and is not empty) const isTagNoValid = React.useMemo(() => { const tagNo = form.getValues("tagNo"); return tagNo && tagNo.trim() !== "" && !tagNo.includes("??"); }, [form, watchAll.tagNo]); // onSubmit async function onSubmit(data: CreateTagSchema) { startTransition(async () => { if (!selectedPackageId) { toast.error("No selectedPackageId.") return } const result = await createTag(data, selectedPackageId) if ("error" in result) { toast.error(`Error: ${result.error}`) return } toast.success("Tag created successfully!") form.reset() setOpen(false) router.refresh() }) } function handleDialogOpenChange(nextOpen: boolean) { if (!nextOpen) { form.reset() } setOpen(nextOpen) } // 3) TagType selection UI (like your Command menu) function renderTagTypeSelector(field: any) { const [popoverOpen, setPopoverOpen] = React.useState(false) return ( Tag Type No tag type found. {tagTypeDefinitions.map((def,index) => ( { field.onChange(def.id) // store the 'id' setPopoverOpen(false) }} value={def.id} > {def.label} ))} ) } // 4) Render sub-fields based on currentTagTypeDef // Updated to handle different field types (text, select) function renderSubFields() { if (!currentTagTypeDef) return null return currentTagTypeDef.subFields.map((subField, index) => ( ( {subField.label} {subField.type === "select" && subField.options ? ( ) : ( )} {subField.formatHint && (

{subField.formatHint}

)}
)} /> )) } return ( Add New Tag Select a Tag Type and fill in sub-fields. The Tag No will be generated automatically.
{/* Tag Type - Outside ScrollArea as it's always visible */} renderTagTypeSelector(field)} />
{/* ScrollArea for dynamic fields */}
{/* sub-fields from the selected tagType */} {renderSubFields()} {/* Tag No (auto-generated) */} ( Tag No (auto-generated) )} /> {/* Description (optional) */} ( Description field.onChange(e.target.value)} /> )} />
) }