diff --git a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/DraftBookingView.tsx b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/DraftBookingView.tsx index 38238680a..f20679ab9 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/DraftBookingView.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/DraftBookingView.tsx @@ -77,7 +77,9 @@ export function DraftBookingView({ enabled: booking.status === "DRAFT" && !booking.pricingBreakdown, }), ); - const pricing = booking.pricingBreakdown ?? generatedPricing ?? null; + const pricing = (booking.pricingBreakdown ?? + generatedPricing ?? + null) as Freight.PricingBreakdown | null; const uploadMutation = useMutation({ mutationFn: (files: Record) => diff --git a/apps/edr-freight-web/portal/src/pages/bookings/EditBookingPage.tsx b/apps/edr-freight-web/portal/src/pages/bookings/EditBookingPage.tsx index fa1900734..edd83df15 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/EditBookingPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/EditBookingPage.tsx @@ -45,7 +45,6 @@ import { initialBookingFormValues, type BookingDocuments, type BookingFormValues, - type RouteDirection, } from "./new-booking-form/schema"; import { SelectField } from "./new-booking-form/shared"; import { Step5CargoDetails } from "./new-booking-form/steps"; @@ -90,13 +89,13 @@ function mapBookingToFormValues( booking: Freight.IBooking, referenceData: Freight.BookingReferenceData, ): BookingFormInputValues { - const vals: BookingFormInputValues = { + const vals = { ...initialBookingFormValues, contractType: (booking.contractType?.toLowerCase() as "new" | "renewal") ?? "new", previousContractRef: booking.previousContractId ?? "", - serviceType: - booking.serviceType === "RAIL_AND_FORWARDING" ? "rail_forwarding" : "rail", + serviceTypeId: + referenceData.service.find((s) => s.code === booking.serviceType)?.id ?? "", firstMile: { enabled: booking.firstMileEnabled ?? false, pickUpAddress: booking.firstMilePickupAddress ?? "", @@ -120,18 +119,15 @@ function mapBookingToFormValues( notes: "", // Terms were accepted at creation; editing shouldn't re-gate on them. termsAccepted: true, - freightType: "", - bulkCommoditytype: "", containers: [], - }; + } as BookingFormInputValues; const bookingCargoTypeId = (booking as any).cargoTypeId as string | undefined; if (booking.freightType === "BULK" && bookingCargoTypeId) { for (const group of referenceData.cargo_type) { const child = group.children?.find((c) => c.id === bookingCargoTypeId); if (child) { - vals.freightType = group.code.toLowerCase(); - vals.bulkCommoditytype = child.name; + vals.cargoTypePath = [group.id, child.id]; break; } } @@ -299,16 +295,24 @@ export default function EditBookingPage() { const originYard = form.watch("originYard"); const destinationYard = form.watch("destinationYard"); - const serviceType = form.watch("serviceType"); + const serviceTypeId = form.watch("serviceTypeId"); const firstMileEnabled = form.watch("firstMile.enabled"); const lastMileEnabled = form.watch("lastMile.enabled"); const documents = (form.watch("documents") ?? {}) as BookingDocuments; - const direction: RouteDirection = useMemo( - () => getRouteDirection(originYard, destinationYard), - [originYard, destinationYard], + const selectedService = useMemo( + () => referenceData?.service.find((s) => s.id === serviceTypeId), + [serviceTypeId, referenceData], ); + const direction = useMemo(() => { + const origin = referenceData?.yard.find((y) => y.name === originYard); + const destination = referenceData?.yard.find( + (y) => y.name === destinationYard, + ); + return getRouteDirection(origin, destination); + }, [originYard, destinationYard, referenceData]); + const yardOptions = useMemo(() => { if (!referenceData?.yard) return []; return referenceData.yard.map((y) => ({ @@ -339,29 +343,17 @@ export default function EditBookingPage() { const yards = referenceData?.yard ?? []; const services = referenceData?.service ?? []; const shippingLines = referenceData?.shipping_line ?? []; - const cargoTree = referenceData?.cargo_type ?? []; const containerGroups = referenceData?.containers ?? []; const findYardId = (name: string): string => yards.find((y) => y.name === name)?.id ?? ""; - const findServiceTypeId = (): string => { - const code = data.serviceType === "rail" ? "RAIL" : "RAIL_AND_FORWARDING"; - return services.find((s) => s.code === code)?.id ?? services[0]?.id ?? ""; - }; - const findShippingLineId = (name: string): string | undefined => shippingLines.find((l) => l.name === name)?.id; - const selectedChild = - data.cargoType !== "container" && data.bulkCommoditytype - ? cargoTree - .find((g) => g.code.toLowerCase() === data.freightType) - ?.children?.find((c) => c.name === data.bulkCommoditytype) - : undefined; - + const cargoTypePath = data.cargoTypePath ?? []; const cargoTypeId = - data.cargoType === "container" ? undefined : (selectedChild?.id ?? ""); + data.cargoType === "container" ? undefined : (cargoTypePath[1] ?? ""); const findContainerTypeId = (name: string): string => { for (const group of containerGroups) { @@ -379,11 +371,13 @@ export default function EditBookingPage() { ) : Number(data.cargoWeight || 0); + const selectedSvc = services.find((s) => s.id === data.serviceTypeId); + const apiPayload: Partial = { scheduledDate: new Date().toISOString().slice(0, 10), contractType: data.contractType.toUpperCase() as CreateBookingPayload["contractType"], - serviceTypeId: findServiceTypeId(), + serviceTypeId: data.serviceTypeId, equipmentReturn: data.equipmentReturn === "with_return" ? "WITH_RETURN" @@ -391,9 +385,9 @@ export default function EditBookingPage() { originYardId: findYardId(data.originYard), destinationYardId: findYardId(data.destinationYard), tradeDirection: - direction === "export" + direction === "EXPORT" ? "EXPORT" - : direction === "domestic" + : direction === "DOMESTIC" ? "DOMESTIC" : "IMPORT", cargoTypeId: data.cargoType === "container" ? undefined : cargoTypeId, @@ -420,10 +414,10 @@ export default function EditBookingPage() { ...(data.contractType === "renewal" && data.previousContractRef ? { pnrCode: data.previousContractRef } : {}), - ...(data.serviceType === "rail_forwarding" && data.firstMile.enabled + ...(selectedSvc?.includesFirstMile && data.firstMile.enabled ? { firstMilePickupAddress: data.firstMile.pickUpAddress } : {}), - ...(data.serviceType === "rail_forwarding" && data.lastMile.enabled + ...(selectedSvc?.includesLastMile && data.lastMile.enabled ? { lastMileDeliveryAddress: data.lastMile.deliveryAddress } : {}), ...(data.shippingLine @@ -523,7 +517,7 @@ export default function EditBookingPage() { ( s.canBeBookedAlone) + .map((s) => ({ value: s.id, label: s.serviceName }))} /> )} /> @@ -560,7 +550,9 @@ export default function EditBookingPage() { /> - {serviceType === "rail_forwarding" && ( + {(selectedService?.includesFirstMile || + selectedService?.includesLastMile || + selectedService?.includesCustoms) && ( } title="First Mile - Pick-up" description="Truck pick-up from your premises to the origin rail yard." - checked={field.value} + checked={field.value ?? false} onChange={(value) => { field.onChange(value); if (!value) { @@ -610,7 +602,7 @@ export default function EditBookingPage() { icon={} title="Last Mile - Delivery" description="Truck delivery from the destination rail yard to the final address." - checked={field.value} + checked={field.value ?? false} onChange={(value) => { field.onChange(value); if (!value) { @@ -650,7 +642,7 @@ export default function EditBookingPage() { icon={} title="Customs Clearing Service" description="EDR handles customs documentation and clearance on your behalf." - checked={field.value} + checked={field.value ?? false} onChange={field.onChange} /> )} @@ -710,7 +702,7 @@ export default function EditBookingPage() { )} - {direction && direction !== "domestic" && ( + {direction && direction !== "DOMESTIC" && ( diff --git a/apps/edr-freight-web/portal/src/pages/bookings/MyBookings.tsx b/apps/edr-freight-web/portal/src/pages/bookings/MyBookings.tsx index e689fa230..0ee19f95e 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/MyBookings.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/MyBookings.tsx @@ -179,11 +179,7 @@ export default function MyBookings() { cell: ({ row }) => { const b = row.original; const cargoLabel = - b.freightType === "BULK" - ? "Bulk Cargo" - : b.freightType === "BREAK_BULK" - ? "Break Bulk" - : "Cargo"; + b.freightType === "BULK" ? "Bulk Cargo" : "Cargo"; return ( ; export const initialBookingFormValues: DeepPartial = { previousContractRef: "", + serviceTypeId: "", firstMile: { enabled: false, pickUpAddress: "", diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step8-review.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step8-review.tsx index d3a24d55d..7d14dd28e 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step8-review.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step8-review.tsx @@ -85,14 +85,15 @@ export function Step8Review({ }).length; const docsTotal = BOOKING_DOCS_SETTING.fields.length; - const cargoValue = - values.cargoType === "container" - ? containerSummary - : values.freightType === "bulk" - ? `Bulk — ${values.bulkCommoditytype}` - : values.freightType === "break_bulk" - ? `Break-Bulk` - : ""; + const cargoValue = (() => { + if (values.cargoType === "container") return containerSummary; + if (!referenceData) return ""; + const path = values.cargoTypePath ?? []; + const group = referenceData.cargo_type.find((g) => g.id === path[0]); + if (!group) return ""; + const child = group.children?.find((c) => c.id === path[1]); + return child ? `${group.name} — ${child.name}` : group.name; + })(); function ReviewCard({ title,