Files
edr-platform/apps/edr-freight-web/backoffice/src/components/bookings/detail/AdditionalDocsRequestCard.tsx

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>
);
}