"use client" import { useState, useEffect } from "react" import { z } from "zod" import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" import { toast } from "sonner" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion" import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Input } from "@/components/ui/input" import { Button } from "@/components/ui/button" import { Checkbox } from "@/components/ui/checkbox" import { ScrollArea } from "@/components/ui/scroll-area" import { ContractDetail, ContractDetailParsed } from "@/db/schema/contract" import { getVendorContacts } from "../service" // Type for vendor contact interface VendorContact { id: number contactName: string contactEmail: string contactPosition: string | null isPrimary: boolean } // Form schema for signature request const signatureRequestSchema = z.object({ // Requester signer information includeRequesterSigner: z.boolean().default(true), requesterEmail: z.string().email("Please enter a valid email address").optional(), requesterName: z.string().min(1, "Please enter the signer's name").optional(), requesterPosition: z.string().optional(), // Vendor signer information includeVendorSigner: z.boolean().default(true), vendorContactId: z.number().optional(), }).refine(data => data.includeRequesterSigner || data.includeVendorSigner, { message: "At least one signer must be included", path: ["includeRequesterSigner"] }).refine(data => !data.includeRequesterSigner || (data.requesterEmail && data.requesterName), { message: "Requester email and name are required", path: ["requesterEmail"] }).refine(data => !data.includeVendorSigner || data.vendorContactId, { message: "Please select a vendor contact", path: ["vendorContactId"] }); type SignatureRequestFormValues = z.infer // Interface for signing parties interface SigningParty { signerEmail: string; signerName: string; signerPosition: string; signerType: "REQUESTER" | "VENDOR"; vendorContactId?: number; } // Updated interface to accept multiple signers interface SignatureRequestModalProps { contract: ContractDetailParsed open: boolean onOpenChange: (open: boolean) => void onSubmit: ( values: { signers: SigningParty[] }, contractId: number ) => Promise<{ success: boolean; message: string } | void> } export function SignatureRequestModal({ contract, open, onOpenChange, onSubmit, }: SignatureRequestModalProps) { const [isSubmitting, setIsSubmitting] = useState(false) const [vendorContacts, setVendorContacts] = useState([]) const [selectedVendorContact, setSelectedVendorContact] = useState(null) const form = useForm({ resolver: zodResolver(signatureRequestSchema), defaultValues: { includeRequesterSigner: true, requesterEmail: "", requesterName: "", requesterPosition: "", includeVendorSigner: true, vendorContactId: undefined, }, }) // Load vendor contacts when the modal opens useEffect(() => { if (open && contract?.vendorId) { const loadVendorContacts = async () => { try { const contacts = await getVendorContacts(contract.vendorId); setVendorContacts(contacts); // Auto-select primary contact if available const primaryContact = contacts.find(c => c.isPrimary); if (primaryContact) { handleVendorContactSelect(primaryContact.id.toString()); } } catch (error) { console.error("Error loading vendor contacts:", error); toast.error("Failed to load vendor contacts"); } }; loadVendorContacts(); } }, [open, contract]); // Handle selection of a vendor contact const handleVendorContactSelect = (contactId: string) => { const id = Number(contactId); form.setValue("vendorContactId", id); // Find the selected contact to show details const contact = vendorContacts.find(c => c.id === id); if (contact) { setSelectedVendorContact(contact); } }; async function handleSubmit(values: SignatureRequestFormValues) { setIsSubmitting(true); try { const signers: SigningParty[] = []; // Add requester signer if included if (values.includeRequesterSigner && values.requesterEmail && values.requesterName) { signers.push({ signerEmail: values.requesterEmail, signerName: values.requesterName, signerPosition: values.requesterPosition || "", signerType: "REQUESTER" }); } // Add vendor signer if included if (values.includeVendorSigner && values.vendorContactId && selectedVendorContact) { signers.push({ signerEmail: selectedVendorContact.contactEmail, signerName: selectedVendorContact.contactName, signerPosition: selectedVendorContact.contactPosition || "", vendorContactId: values.vendorContactId, signerType: "VENDOR" }); } if (signers.length === 0) { throw new Error("At least one signer must be included"); } const result = await onSubmit({ signers }, contract.id); // Handle the result if it exists if (result && typeof result === 'object') { if (result.success) { toast.success(result.message || "Signature requests sent successfully"); } else { toast.error(result.message || "Failed to send signature requests"); } } else { // If no result is returned, assume success toast.success("Electronic signature requests sent successfully"); } form.reset(); onOpenChange(false); } catch (error) { console.error("Error sending signature requests:", error); toast.error(error instanceof Error ? error.message : "Failed to send signature requests. Please try again."); } finally { setIsSubmitting(false); } } return ( Request Electronic Signatures Send signature requests for contract: {contract?.contractName || ""}
{/* Requester Signature Section */}
(
Requester Signature
)} />
{form.watch("includeRequesterSigner") && ( ( Signer Email )} /> ( Signer Name )} /> ( Signer Position )} /> )}
{/* Vendor Signature Section */}
(
Vendor Signature
)} />
{form.watch("includeVendorSigner") && ( ( Select Vendor Contact )} /> {/* Display selected contact info (read-only) */} {selectedVendorContact && ( <> Contact Email
{selectedVendorContact.contactEmail}
Contact Name
{selectedVendorContact.contactName}
Contact Position
{selectedVendorContact.contactPosition || "N/A"}
)}
)}
) }