mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 07:10:57 +00:00
114 lines
3.3 KiB
TypeScript
114 lines
3.3 KiB
TypeScript
import { useState } from "react";
|
|
import { useMutation } from "@tanstack/react-query";
|
|
import {
|
|
Box,
|
|
Button,
|
|
Group,
|
|
Paper,
|
|
Stack,
|
|
Text,
|
|
Textarea,
|
|
} from "@mantine/core";
|
|
import { MessageSquarePlus, Send } from "lucide-react";
|
|
import toast from "react-hot-toast";
|
|
import type { Freight } from "@edr/types";
|
|
|
|
import { SectionCard } from "./SectionCard";
|
|
import { bookingsService } from "@/services/bookings.service";
|
|
import { formatDateTime } from "@/lib/format";
|
|
import { extractErrorMessage } from "@/utils/errorExtractor";
|
|
|
|
export interface AdditionalDocsRequestCardProps {
|
|
bookingId: string;
|
|
/** Past requests, newest first. */
|
|
requests: Freight.ClearanceDocRequest[];
|
|
/** False once the shipment is paid — documents (and requests) are closed. */
|
|
canRequest: boolean;
|
|
onSent?: () => void;
|
|
}
|
|
|
|
/**
|
|
* GL asks the customer for additional clearance document(s) in plain words.
|
|
* The message, its author and its time show on the customer's portal beside
|
|
* the upload box, so the customer knows exactly what to send and who asked.
|
|
*/
|
|
export function AdditionalDocsRequestCard({
|
|
bookingId,
|
|
requests,
|
|
canRequest,
|
|
onSent,
|
|
}: AdditionalDocsRequestCardProps) {
|
|
const [note, setNote] = useState("");
|
|
|
|
const send = useMutation({
|
|
mutationFn: () => bookingsService.requestAdditionalDocuments(bookingId, note),
|
|
onSuccess: () => {
|
|
toast.success("Request sent to the customer");
|
|
setNote("");
|
|
onSent?.();
|
|
},
|
|
onError: (e) =>
|
|
toast.error(extractErrorMessage(e, "Could not send the request")),
|
|
});
|
|
|
|
return (
|
|
<SectionCard
|
|
icon={MessageSquarePlus}
|
|
title="Ask for a document"
|
|
subtitle="The customer sees your message, who wrote it, and uploads the file from their portal."
|
|
accent="edr-green"
|
|
>
|
|
<Stack gap="sm">
|
|
{canRequest ? (
|
|
<Box>
|
|
<Textarea
|
|
placeholder="e.g. Please send the amended commercial invoice showing the revised unit price."
|
|
value={note}
|
|
onChange={(e) => setNote(e.currentTarget.value)}
|
|
autosize
|
|
minRows={3}
|
|
radius="md"
|
|
size="sm"
|
|
/>
|
|
<Group justify="flex-end" mt={8}>
|
|
<Button
|
|
size="compact-sm"
|
|
color="edr-green"
|
|
radius="md"
|
|
leftSection={<Send size={14} />}
|
|
loading={send.isPending}
|
|
disabled={!note.trim()}
|
|
onClick={() => send.mutate()}
|
|
>
|
|
Send request
|
|
</Button>
|
|
</Group>
|
|
</Box>
|
|
) : (
|
|
<Text fz="12.5px" c="dimmed">
|
|
This shipment is settled — document requests are closed.
|
|
</Text>
|
|
)}
|
|
|
|
{requests.length > 0 && (
|
|
<Stack gap={8}>
|
|
<Text fz="11px" fw={700} tt="uppercase" c="dimmed" lts="0.05em">
|
|
Sent requests
|
|
</Text>
|
|
{requests.map((r) => (
|
|
<Paper key={r.id} withBorder radius="md" p="xs">
|
|
<Text fz="12.5px" c="edr-text">
|
|
{r.note}
|
|
</Text>
|
|
<Text fz="11px" c="dimmed" mt={4}>
|
|
{r.byName ?? "Staff"} · {formatDateTime(r.at)}
|
|
</Text>
|
|
</Paper>
|
|
))}
|
|
</Stack>
|
|
)}
|
|
</Stack>
|
|
</SectionCard>
|
|
);
|
|
}
|