mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 07:38:10 +00:00
148 lines
5.0 KiB
TypeScript
148 lines
5.0 KiB
TypeScript
import { useState } from 'react';
|
|
import { Badge, Button, Card, Divider, Group, Stack, Text } from '@mantine/core';
|
|
import { PackagePlus, Train as TrainIcon, Warehouse as WarehouseIcon } from 'lucide-react';
|
|
|
|
import { useQuery } from '@tanstack/react-query';
|
|
|
|
import { api } from '@/services/api';
|
|
import { InventoryStatusBadge } from './badges';
|
|
import { FreightVisual } from './FreightVisual';
|
|
import { formatDate } from './options';
|
|
import { ReceiveInventoryModal } from './ReceiveInventoryModal';
|
|
|
|
interface WarehouseInfoCardProps {
|
|
bookingId: string;
|
|
bookingReference?: string;
|
|
}
|
|
|
|
function Row({ label, value }: { label: string; value: React.ReactNode }) {
|
|
return (
|
|
<Group justify="space-between" wrap="nowrap">
|
|
<Text size="sm" c="dimmed">
|
|
{label}
|
|
</Text>
|
|
<Text size="sm" fw={500} ta="right">
|
|
{value}
|
|
</Text>
|
|
</Group>
|
|
);
|
|
}
|
|
|
|
export function WarehouseInfoCard({ bookingId, bookingReference }: WarehouseInfoCardProps) {
|
|
const [modalOpen, setModalOpen] = useState(false);
|
|
const { data, isLoading } = useQuery(
|
|
api.warehouses.listInventory.queryOptions({ input: { filter: { bookingId } } }),
|
|
);
|
|
const { data: scheduleView } = useQuery(
|
|
api.warehouses.bookingSchedule.queryOptions({
|
|
input: { bookingId },
|
|
enabled: Boolean(bookingId),
|
|
}),
|
|
);
|
|
|
|
const items = data ?? [];
|
|
const latest = items[0];
|
|
const schedule = scheduleView?.schedule;
|
|
const wagon = scheduleView?.wagon;
|
|
const isLoadedOrDispatched =
|
|
latest?.status === 'LOADED' || latest?.status === 'DISPATCHED';
|
|
|
|
return (
|
|
<Card withBorder radius="md" padding="lg">
|
|
<Stack gap="md">
|
|
<Group justify="space-between">
|
|
<Group gap="xs">
|
|
<WarehouseIcon size={18} />
|
|
<Text fw={700}>Warehouse Information</Text>
|
|
</Group>
|
|
{items.length > 0 && (
|
|
<Badge variant="light" color="gray">
|
|
{items.length} item{items.length > 1 ? 's' : ''}
|
|
</Badge>
|
|
)}
|
|
</Group>
|
|
|
|
<Divider />
|
|
|
|
{isLoading ? (
|
|
<Text size="sm" c="dimmed">
|
|
Loading…
|
|
</Text>
|
|
) : !latest ? (
|
|
<Text size="sm" c="dimmed">
|
|
This booking has not been received at any warehouse yet.
|
|
</Text>
|
|
) : (
|
|
<Stack gap="xs">
|
|
<Row label="Warehouse" value={latest.warehouse ? `${latest.warehouse.name} (${latest.warehouse.code})` : '—'} />
|
|
<Row label="Yard" value={latest.yard ? `${latest.yard.name} (${latest.yard.code})` : '—'} />
|
|
<Row label="Zone" value={latest.zone ? `${latest.zone.name} (${latest.zone.code})` : '—'} />
|
|
<Row label="Inventory Status" value={<InventoryStatusBadge status={latest.status} />} />
|
|
<Row label="Arrived At" value={formatDate(latest.arrivedAt)} />
|
|
<Row label="Ready For Loading At" value={formatDate(latest.readyForLoadingAt)} />
|
|
{isLoadedOrDispatched && (
|
|
<>
|
|
<Row
|
|
label="Wagon"
|
|
value={wagon?.wagonNumber ?? '—'}
|
|
/>
|
|
<Row label="Loaded At" value={formatDate(latest.loadedAt)} />
|
|
<Row label="Dispatched At" value={formatDate(latest.dispatchedAt)} />
|
|
</>
|
|
)}
|
|
</Stack>
|
|
)}
|
|
|
|
{schedule && (
|
|
<>
|
|
<Divider
|
|
label={
|
|
<Group gap={6}>
|
|
<TrainIcon size={14} />
|
|
<Text size="xs" c="dimmed">
|
|
Train schedule (read-only)
|
|
</Text>
|
|
</Group>
|
|
}
|
|
labelPosition="left"
|
|
/>
|
|
<Group gap="sm" wrap="nowrap" align="flex-start">
|
|
<FreightVisual variant="train" size={40} />
|
|
<Stack gap="xs" style={{ flex: 1 }}>
|
|
<Row
|
|
label="Departure Status"
|
|
value={
|
|
<Badge variant="light" color="blue" size="sm">
|
|
{schedule.status}
|
|
</Badge>
|
|
}
|
|
/>
|
|
<Row label="Scheduled Departure" value={formatDate(schedule.scheduledDepartureDate)} />
|
|
<Row label="Scheduled Arrival" value={formatDate(schedule.scheduledArrivalDate)} />
|
|
{wagon?.wagonNumber && <Row label="Assigned Wagon" value={wagon.wagonNumber} />}
|
|
{wagon?.sequenceNo != null && <Row label="Wagon Position" value={`#${wagon.sequenceNo}`} />}
|
|
</Stack>
|
|
</Group>
|
|
</>
|
|
)}
|
|
|
|
<Button
|
|
variant="light"
|
|
leftSection={<PackagePlus size={16} />}
|
|
onClick={() => setModalOpen(true)}
|
|
fullWidth
|
|
>
|
|
Receive At Warehouse
|
|
</Button>
|
|
</Stack>
|
|
|
|
<ReceiveInventoryModal
|
|
opened={modalOpen}
|
|
onClose={() => setModalOpen(false)}
|
|
bookingId={bookingId}
|
|
bookingLabel={bookingReference}
|
|
/>
|
|
</Card>
|
|
);
|
|
}
|