'use client'; /** * Confirms a "mark as signed externally without file" action on an * interest's contract / reservation / EOI sub-status. Used by the * relevant interest tabs when the rep has paper or a digital copy * filed elsewhere and doesn't want to duplicate-store it in the CRM * just to flip the doc-status forward. * * The action is destructive in the sense that downstream berth-rules * fire (eoi_signed / contract_signed triggers), so a confirmation * step + optional reason capture is required. */ import { useState } from 'react'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Loader2 } from 'lucide-react'; import { toast } from 'sonner'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { apiFetch } from '@/lib/api/client'; import { toastError } from '@/lib/api/toast-error'; type DocType = 'eoi' | 'reservation' | 'contract'; const LABELS: Record = { eoi: { title: 'Mark EOI as signed externally?', description: 'Flips the EOI sub-status to "signed" without uploading a file. Audit log captures who marked it + your reason. If a file turns up later, you can still upload it via the regular flow.', }, reservation: { title: 'Mark reservation as signed externally?', description: 'Flips the reservation sub-status to "signed" without uploading a file. Audit log captures who marked it + your reason.', }, contract: { title: 'Mark contract as signed externally?', description: 'Flips the contract sub-status to "signed" without uploading a file. The contract-signed berth-rule fires automatically (you can disable in admin/berth-rules).', }, }; export function MarkExternallySignedDialog({ open, onOpenChange, interestId, docType, onSuccess, }: { open: boolean; onOpenChange: (o: boolean) => void; interestId: string; docType: DocType; onSuccess?: () => void; }) { const [reason, setReason] = useState(''); const qc = useQueryClient(); const labels = LABELS[docType]; const mutation = useMutation({ mutationFn: async () => { await apiFetch(`/api/v1/interests/${interestId}/mark-externally-signed`, { method: 'POST', body: { docType, reason: reason.trim() || undefined }, }); }, onSuccess: () => { toast.success(`Marked ${docType} as signed externally`); qc.invalidateQueries({ queryKey: ['interest', interestId] }); qc.invalidateQueries({ queryKey: ['interests'] }); qc.invalidateQueries({ queryKey: ['documents'] }); onOpenChange(false); onSuccess?.(); }, onError: (e) => toastError(e), }); return ( {labels.title} {labels.description}