mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 23:28:11 +00:00
feat(train-scheduling): add wagon type, tare, equated length, station, seal no and note columns to import marshalling doc
Import Load List / Marshalling Document only rendered Seq, Wagon, Booking, Company, Load, Container numbers, Weight T — missing fields present on the physical marshaling sheet (wagon type, tare, equated length, departure/arrival station, seal no) and a blank note column for yard staff. Export marshalling doc already had most of these; import doc now matches. Existing columns kept in place, unchanged.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import { Truck } from "lucide-react";
|
||||
import { SimpleGrid } from "@mantine/core";
|
||||
import { Download, Truck } from "lucide-react";
|
||||
import { Button, Group, SimpleGrid, Stack, Text } from "@mantine/core";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
|
||||
import { lastMileRequestsService } from "@/services/last-mile-requests.service";
|
||||
import type { BookingDetail } from "@/types/booking";
|
||||
|
||||
import { SectionCard } from "./SectionCard";
|
||||
@@ -10,12 +13,37 @@ export interface BookingMileServicesCardProps {
|
||||
booking: BookingDetail;
|
||||
}
|
||||
|
||||
/** First / last mile addresses. Renders nothing when neither is present. */
|
||||
/**
|
||||
* First / last mile addresses, plus the stored last-mile contract reference
|
||||
* (signed status + PDF download) for Truck & Machinery once a request on this
|
||||
* booking is approved. Renders nothing when neither address is present.
|
||||
*/
|
||||
export function BookingMileServicesCard({ booking }: BookingMileServicesCardProps) {
|
||||
const { data: requestsResponse } = useQuery({
|
||||
queryKey: QUERY_KEYS.LAST_MILE_REQUESTS.list({ bookingId: booking.id }),
|
||||
queryFn: async () =>
|
||||
(await lastMileRequestsService.list({ bookingId: booking.id })).data,
|
||||
enabled: Boolean(booking.lastMileDeliveryAddress),
|
||||
});
|
||||
const approvedRequest = (requestsResponse?.data ?? []).find(
|
||||
(r) => r.status === "APPROVED",
|
||||
);
|
||||
|
||||
if (!booking.firstMilePickupAddress && !booking.lastMileDeliveryAddress) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const downloadContract = async () => {
|
||||
if (!approvedRequest) return;
|
||||
const blob = (await lastMileRequestsService.contractDocument(approvedRequest.id)).data;
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = `last-mile-contract-${booking.reference ?? booking.id}.pdf`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
return (
|
||||
<SectionCard icon={Truck} title="Mile services" accent="grape">
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }} spacing="sm">
|
||||
@@ -26,6 +54,32 @@ export function BookingMileServicesCard({ booking }: BookingMileServicesCardProp
|
||||
<MetricTile label="Last mile delivery" value={booking.lastMileDeliveryAddress} />
|
||||
)}
|
||||
</SimpleGrid>
|
||||
{approvedRequest && (
|
||||
<Group justify="space-between" align="center" wrap="wrap" mt="sm">
|
||||
<Stack gap={0}>
|
||||
<Text size="sm" fw={600}>
|
||||
Last-mile contract
|
||||
</Text>
|
||||
<Text size="xs" c={approvedRequest.customerSignedAt ? "green.8" : "orange.8"}>
|
||||
{approvedRequest.customerSignedAt
|
||||
? `Signed ${new Date(approvedRequest.customerSignedAt).toLocaleDateString()}${
|
||||
approvedRequest.signerDisplayName
|
||||
? ` by ${approvedRequest.signerDisplayName}`
|
||||
: ""
|
||||
}`
|
||||
: "Awaiting customer signature"}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Button
|
||||
size="xs"
|
||||
variant="light"
|
||||
leftSection={<Download size={14} />}
|
||||
onClick={() => void downloadContract()}
|
||||
>
|
||||
Download PDF
|
||||
</Button>
|
||||
</Group>
|
||||
)}
|
||||
</SectionCard>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user