mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 12:18:11 +00:00
changes
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Badge } from "@mantine/core";
|
||||
import { Badge, Group } from "@mantine/core";
|
||||
import { Link2 } from "lucide-react";
|
||||
import { BOOKING_STATUS_STYLES } from "@/features/bookings/booking-status.config";
|
||||
|
||||
const statusColorMap: Record<string, string> = {
|
||||
@@ -24,14 +25,26 @@ const statusColorMap: Record<string, string> = {
|
||||
CONSOLIDATED: "indigo",
|
||||
};
|
||||
|
||||
export function BookingStatusBadge({ status }: { status: string }) {
|
||||
interface BookingStatusBadgeProps {
|
||||
status: string;
|
||||
/** When the booking is part of a consolidation, show a sibling badge. */
|
||||
consolidated?: boolean;
|
||||
/** Partner booking reference for the consolidated badge tooltip. */
|
||||
partnerReference?: string | null;
|
||||
}
|
||||
|
||||
export function BookingStatusBadge({
|
||||
status,
|
||||
consolidated,
|
||||
partnerReference,
|
||||
}: BookingStatusBadgeProps) {
|
||||
const style = BOOKING_STATUS_STYLES[status] ?? {
|
||||
label: status,
|
||||
color: "gray",
|
||||
};
|
||||
const color = statusColorMap[status] ?? "gray";
|
||||
|
||||
return (
|
||||
const statusBadge = (
|
||||
<Badge
|
||||
color={color}
|
||||
variant="light"
|
||||
@@ -51,4 +64,34 @@ export function BookingStatusBadge({ status }: { status: string }) {
|
||||
{style.label}
|
||||
</Badge>
|
||||
);
|
||||
|
||||
if (!consolidated) return statusBadge;
|
||||
|
||||
return (
|
||||
<Group gap={4} wrap="nowrap">
|
||||
{statusBadge}
|
||||
<Badge
|
||||
color="indigo"
|
||||
variant="light"
|
||||
size="sm"
|
||||
radius="md"
|
||||
tt="uppercase"
|
||||
fw={600}
|
||||
leftSection={<Link2 size={12} />}
|
||||
title={
|
||||
partnerReference
|
||||
? `Consolidated with ${partnerReference}`
|
||||
: "Part of a consolidation"
|
||||
}
|
||||
style={{
|
||||
fontSize: "0.7rem",
|
||||
letterSpacing: "0.05em",
|
||||
display: "inline-flex",
|
||||
whiteSpace: "nowrap",
|
||||
}}
|
||||
>
|
||||
Consolidated
|
||||
</Badge>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,11 @@ export function BookingDetailHeader({
|
||||
<Title order={2} fw={700} style={{ letterSpacing: "-0.4px" }}>
|
||||
{booking.reference}
|
||||
</Title>
|
||||
<BookingStatusBadge status={booking.status} />
|
||||
<BookingStatusBadge
|
||||
status={booking.status}
|
||||
consolidated={Boolean(booking.consolidationPartnerId)}
|
||||
partnerReference={booking.consolidationPartner?.reference}
|
||||
/>
|
||||
</Group>
|
||||
<Group gap="xs">
|
||||
<Building2 size={14} color="var(--mantine-color-gray-5)" />
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Alert, List, Text } from "@mantine/core";
|
||||
import { Link2 } from "lucide-react";
|
||||
|
||||
import { bookingsService } from "@/services/bookings.service";
|
||||
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
|
||||
|
||||
/**
|
||||
* Shown on a booking parked in PENDING_CONSOLIDATION. Explains that the booking
|
||||
* cannot be approved until a complementary booking fills the wagon, and lists
|
||||
* the partial-wagon container lines that are waiting for a partner.
|
||||
*/
|
||||
export function ConsolidationWaitingBanner({ bookingId }: { bookingId: string }) {
|
||||
const { data } = useQuery({
|
||||
queryKey: [...QUERY_KEYS.BOOKINGS.byId(bookingId), "consolidation"],
|
||||
queryFn: () => bookingsService.getConsolidationDetails(bookingId),
|
||||
enabled: Boolean(bookingId),
|
||||
});
|
||||
|
||||
return (
|
||||
<Alert
|
||||
color="yellow"
|
||||
variant="light"
|
||||
icon={<Link2 size={18} />}
|
||||
title="Waiting for a consolidation partner"
|
||||
>
|
||||
<Text size="sm">
|
||||
This booking cannot be approved until a matching booking fills the
|
||||
wagon. It will return to the approval queue automatically once a partner
|
||||
is found.
|
||||
</Text>
|
||||
{data?.wagonSlots?.length ? (
|
||||
<List size="sm" mt="xs" spacing={2}>
|
||||
{data.wagonSlots.map((slot) => (
|
||||
<List.Item key={slot.containerTypeCode}>
|
||||
{slot.slotsNeeded} more × {slot.containerTypeCode} (
|
||||
{slot.containersPerWagon} per wagon; you have {slot.quantity})
|
||||
</List.Item>
|
||||
))}
|
||||
</List>
|
||||
) : null}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user