From ed503f1e6b19fe34fc4aac7ac4c9c82b2f84323f Mon Sep 17 00:00:00 2001 From: Hagernesh Date: Tue, 21 Jul 2026 11:38:57 +0000 Subject: [PATCH] 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 --- .../BookingDetailPage/ReadonlyBookingView.tsx | 3 + .../components/WarehouseLocationCard.tsx | 71 +++++++++++++++++++ .../portal/src/services/warehouse.service.ts | 56 +++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/components/WarehouseLocationCard.tsx create mode 100644 apps/edr-freight-web/portal/src/services/warehouse.service.ts diff --git a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/ReadonlyBookingView.tsx b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/ReadonlyBookingView.tsx index fc701b924..ce218f84b 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/ReadonlyBookingView.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/ReadonlyBookingView.tsx @@ -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({ + + diff --git a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/components/WarehouseLocationCard.tsx b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/components/WarehouseLocationCard.tsx new file mode 100644 index 000000000..64320a968 --- /dev/null +++ b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/components/WarehouseLocationCard.tsx @@ -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 ( + + + {label} + + + {value} + + + ); +} + +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 ( + + + + + Warehouse Location + + + + + {isLoading ? ( + + Loading… + + ) : !latest ? ( + + Your cargo will appear here once it arrives at the warehouse. + + ) : ( + + + + + + + )} + + + ); +} diff --git a/apps/edr-freight-web/portal/src/services/warehouse.service.ts b/apps/edr-freight-web/portal/src/services/warehouse.service.ts new file mode 100644 index 000000000..dfb6042cc --- /dev/null +++ b/apps/edr-freight-web/portal/src/services/warehouse.service.ts @@ -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 => { + const { data } = await client.get("/warehouse-inventory", { + params: filter, + }); + return data?.data ?? data ?? []; + }, + + bookingSchedule: async (bookingId: string): Promise => { + const { data } = await client.get(`/warehouse-inventory/booking-schedule/${bookingId}`); + return data?.data ?? data ?? { schedule: null, wagon: null }; + }, +};