import { useState } from "react"; import { Button, Group, Modal, Stack, Text } from "@mantine/core"; import { DateInput } from "@mantine/dates"; import { Ship, Upload } from "lucide-react"; import toast from "react-hot-toast"; import { PhasedFileDropzone } from "@/components/contracts/PhasedFileDropzone"; import { findWorkflowFile } from "@/components/contracts/PhasedUploadedFileRow"; import { contractsService } from "@/services/contracts.service"; import { bookingsService } from "@/services/bookings.service"; import type { Freight } from "@edr/types"; export type GlClearanceUploadKind = "do" | "ro"; export interface GlClearanceUploadModalProps { opened: boolean; kind: GlClearanceUploadKind | null; onClose: () => void; entityId: string; isBooking: boolean; workflowFiles?: Freight.ClearanceWorkflowFile[]; vesselDepartureDate?: string | null; onSuccess?: () => void; onPreview?: (file: { name: string; url: string }) => void; } export function GlClearanceUploadModal({ opened, kind, onClose, entityId, isBooking, workflowFiles = [], vesselDepartureDate, onSuccess, onPreview, }: GlClearanceUploadModalProps) { const [file, setFile] = useState(null); const [vesselDate, setVesselDate] = useState( vesselDepartureDate ? new Date(vesselDepartureDate) : null, ); const [loading, setLoading] = useState(false); const isDo = kind === "do"; const isRo = kind === "ro"; const replaceMode = isDo ? Boolean(findWorkflowFile(workflowFiles, "delivery_order")) : Boolean(findWorkflowFile(workflowFiles, "release_order")); const close = () => { setFile(null); onClose(); }; const submit = async () => { if (!file || !kind) return; if (isRo && !vesselDate) { toast.error("Vessel departure date is required."); return; } setLoading(true); try { if (isDo) { if (isBooking) { await bookingsService.uploadDeliveryOrder(entityId, file); } else { await contractsService.uploadDeliveryOrder(entityId, file); } toast.success(replaceMode ? "Delivery Order updated" : "Delivery Order uploaded"); } else { const iso = vesselDate!.toISOString().slice(0, 10); const result = isBooking ? await bookingsService.uploadReleaseOrder(entityId, file, iso) : await contractsService.uploadReleaseOrder(entityId, file, iso); if (result.hold) { toast.error(result.holdReason ?? "Vessel date too soon"); } else { toast.success(replaceMode ? "Release Order updated" : "Release Order uploaded"); } } setFile(null); onSuccess?.(); close(); } catch (e) { toast.error(e instanceof Error ? e.message : "Upload failed"); } finally { setLoading(false); } }; return ( {isDo ? "Upload Delivery Order" : "Upload Release Order"} } radius="md" size="md" > {isDo ? "Upload the Djibouti Delivery Order (DO) for this import shipment." : "Upload the Release Order and confirm the vessel departure date."} {isRo ? ( setVesselDate(v ? new Date(v) : null)} size="sm" required /> ) : null} ); }