mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat(portal): show warehouse location for arrived cargo
Display cargo warehouse location (warehouse, yard, zone, arrival time) on the portal booking detail page once the cargo has been received and assigned to a warehouse location. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,7 @@ import { HeaderButton, PageHeader } from "./components/PageHeader";
|
||||
import { PaymentMethodModal } from "./components/PaymentMethodModal";
|
||||
import { ScheduleCard } from "./components/ScheduleCard";
|
||||
import { WarehousePaymentsSection } from "./components/WarehousePaymentsSection";
|
||||
import { WarehouseLocationCard } from "./components/WarehouseLocationCard";
|
||||
import { ShipmentDetailsCard } from "./components/ShipmentDetailsCard";
|
||||
import { ShipmentTrackingCard } from "./components/ShipmentTrackingCard";
|
||||
import { StatusHero } from "./components/StatusHero";
|
||||
@@ -273,6 +274,8 @@ export function ReadonlyBookingView({
|
||||
|
||||
<ContainersCard booking={booking} />
|
||||
|
||||
<WarehouseLocationCard bookingId={booking.id} />
|
||||
|
||||
<ContractInfoCard booking={booking} />
|
||||
|
||||
<ShipmentTrackingCard bookingId={booking.id} />
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { Group, Paper, Stack, Text, Divider } from "@mantine/core";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Warehouse as WarehouseIcon } from "lucide-react";
|
||||
|
||||
import { warehouseService } from "@/services/warehouse.service";
|
||||
|
||||
interface WarehouseLocationCardProps {
|
||||
bookingId: 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 WarehouseLocationCard({ bookingId }: WarehouseLocationCardProps) {
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ["warehouse-inventory", bookingId],
|
||||
queryFn: () => warehouseService.listInventory({ bookingId }),
|
||||
});
|
||||
|
||||
const items = data ?? [];
|
||||
const latest = items[0];
|
||||
|
||||
return (
|
||||
<Paper withBorder radius="md" padding="lg">
|
||||
<Stack gap="md">
|
||||
<Group gap="xs">
|
||||
<WarehouseIcon size={18} />
|
||||
<Text fw={700}>Warehouse Location</Text>
|
||||
</Group>
|
||||
|
||||
<Divider />
|
||||
|
||||
{isLoading ? (
|
||||
<Text size="sm" c="dimmed">
|
||||
Loading…
|
||||
</Text>
|
||||
) : !latest ? (
|
||||
<Text size="sm" c="dimmed">
|
||||
Your cargo will appear here once it arrives at the warehouse.
|
||||
</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="Arrived At" value={latest.arrivedAt ? new Date(latest.arrivedAt).toLocaleString() : "—"} />
|
||||
</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import { client } from "@/utils/api";
|
||||
|
||||
export interface InventoryFilter {
|
||||
bookingId?: string;
|
||||
}
|
||||
|
||||
export interface WarehouseInventoryItem {
|
||||
id: string;
|
||||
bookingId: string | null;
|
||||
warehouseId: string;
|
||||
yardId: string;
|
||||
zoneId: string;
|
||||
status: string;
|
||||
arrivedAt: string | null;
|
||||
warehouse?: {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
} | null;
|
||||
yard?: {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
} | null;
|
||||
zone?: {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export interface BookingScheduleView {
|
||||
schedule: {
|
||||
status: string;
|
||||
scheduledDepartureDate: string | null;
|
||||
scheduledArrivalDate: string | null;
|
||||
} | null;
|
||||
wagon?: {
|
||||
wagonNumber: string | null;
|
||||
sequenceNo: number | null;
|
||||
} | null;
|
||||
}
|
||||
|
||||
export const warehouseService = {
|
||||
listInventory: async (filter?: InventoryFilter): Promise<WarehouseInventoryItem[]> => {
|
||||
const { data } = await client.get("/warehouse-inventory", {
|
||||
params: filter,
|
||||
});
|
||||
return data?.data ?? data ?? [];
|
||||
},
|
||||
|
||||
bookingSchedule: async (bookingId: string): Promise<BookingScheduleView> => {
|
||||
const { data } = await client.get(`/warehouse-inventory/booking-schedule/${bookingId}`);
|
||||
return data?.data ?? data ?? { schedule: null, wagon: null };
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user