"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { useQuery, useMutation } from "@tanstack/react-query"; import { useForm, useFieldArray } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { transmittalService } from "@/lib/services/transmittal.service"; import { correspondenceService } from "@/lib/services/correspondence.service"; import { projectService } from "@/lib/services/project.service"; import { organizationService } from "@/lib/services/organization.service"; import { CreateTransmittalDto } from "@/types/dto/transmittal/transmittal.dto"; // UI Components import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Check, ChevronsUpDown, Trash2, Plus, Loader2 } from "lucide-react"; import { toast } from "sonner"; import { cn } from "@/lib/utils"; // Schema for items const itemSchema = z.object({ itemType: z.enum(["DRAWING", "RFA", "CORRESPONDENCE"]), itemId: z.number().min(1, "Document is required"), description: z.string().optional(), // Virtual fields for UI display documentNumber: z.string().optional(), }); // Main form schema const formSchema = z.object({ projectId: z.string().min(1, "Project is required"), // ADR-019: UUID recipientOrganizationId: z.string().min(1, "Recipient is required"), // ADR-019: UUID correspondenceId: z.string().min(1, "Correspondence is required"), // ADR-019: UUID string subject: z.string().min(1, "Subject is required"), purpose: z.enum(["FOR_APPROVAL", "FOR_INFORMATION", "FOR_REVIEW", "OTHER"]), remarks: z.string().optional(), items: z.array(itemSchema).min(1, "At least one item is required"), }); type FormData = z.infer; export function TransmittalForm() { const router = useRouter(); const [docOpen, setDocOpen] = useState(false); const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { projectId: "", recipientOrganizationId: "", correspondenceId: "", subject: "", purpose: "FOR_APPROVAL", remarks: "", items: [ { itemType: "DRAWING", itemId: 0, description: "" }, // Initial empty row ], }, }); const { fields, append, remove } = useFieldArray({ control: form.control, name: "items", }); // ADR-019: Fetch projects and organizations for UUID-based selectors const { data: projectsData, isLoading: isLoadingProjects } = useQuery({ queryKey: ["projects-dropdown"], queryFn: () => projectService.getAll(), }); const projectsList = projectsData?.data || projectsData || []; const { data: orgsData, isLoading: isLoadingOrgs } = useQuery({ queryKey: ["organizations-dropdown"], queryFn: () => organizationService.getAll(), }); const orgsList = orgsData?.data || orgsData || []; // Fetch correspondences (for header linkage) const { data: correspondences } = useQuery({ queryKey: ["correspondences-dropdown"], queryFn: () => correspondenceService.getAll({ limit: 50 }), }); const createMutation = useMutation({ mutationFn: (data: CreateTransmittalDto) => transmittalService.create(data), onSuccess: (result) => { toast.success("Transmittal created successfully"); // ADR-019: Navigate using UUID from correspondence router.push(`/transmittals/${result.correspondence?.uuid || result.uuid}`); }, onError: () => { toast.error("Failed to create transmittal"); }, }); const onSubmit = (data: FormData) => { // ADR-019: All IDs are now UUID strings from the form const cleanPayload: CreateTransmittalDto = { projectId: data.projectId, recipientOrganizationId: data.recipientOrganizationId, correspondenceId: data.correspondenceId, subject: data.subject, purpose: data.purpose as string, remarks: data.remarks, items: data.items.map(item => ({ itemType: item.itemType, itemId: item.itemId, description: item.description })) }; createMutation.mutate(cleanPayload); }; const selectedDocId = form.watch("correspondenceId"); const selectedDoc = correspondences?.data?.find( (c: { uuid: string }) => c.uuid === selectedDocId ); return (
{/* Main Info */} Transmittal Details {/* ADR-019: Project & Recipient Organization selectors */}
( Project )} /> ( Recipient Organization )} />
{/* Linked Correspondence (Ref No) */} ( Reference Document No document found. {correspondences?.data?.map( (doc: { uuid: string; correspondence_number: string }) => ( { form.setValue("correspondenceId", doc.uuid); setDocOpen(false); }} > {doc.correspondence_number} ) )} )} /> {/* Purpose */} ( Purpose )} />
{/* Subject */} ( Subject )} /> {/* Remarks */} ( Remarks (Optional)