From e075252639b390613741bd6272c556daba2b768d Mon Sep 17 00:00:00 2001 From: ghost2023 Date: Fri, 12 Jun 2026 17:05:54 +0300 Subject: [PATCH 01/12] fix: the direction for the yard --- .../src/pages/bookings/NewBookingPage.tsx | 9 +-- .../pages/bookings/new-booking-form/schema.ts | 59 ++++++------------- .../bookings/new-booking-form/step4-route.tsx | 37 ++++++++++-- .../new-booking-form/step5-cargo-details.tsx | 7 +-- .../new-booking-form/step8-review.tsx | 4 +- 5 files changed, 57 insertions(+), 59 deletions(-) diff --git a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx index 5ada990d1..2ae53d576 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx @@ -70,7 +70,7 @@ export default function NewBookingPage() { const destinationYard = form.watch("destinationYard"); const direction = useMemo( - () => getRouteDirection(originYard, destinationYard), + () => getRouteDirection(referenceData?.yard.find((y) => y.id === originYard), referenceData?.yard.find((y) => y.id === destinationYard)), [originYard, destinationYard], ); @@ -163,12 +163,7 @@ export default function NewBookingPage() { : "WITHOUT_RETURN", originYardId: findYardId(data.originYard), destinationYardId: findYardId(data.destinationYard), - tradeDirection: - direction === "export" - ? "EXPORT" - : direction === "domestic" - ? "DOMESTIC" - : "IMPORT", + tradeDirection: direction!, cargoTypeId: data.cargoType === "container" ? undefined : cargoTypeId, cargoTotalWeightVgm: totalWeight, isHazardous: data.isHazardous, diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts index 86d3571ec..ea8611d9e 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts @@ -2,15 +2,6 @@ import type { Freight } from "@edr/types"; import { DeepPartial, Path } from "react-hook-form"; import * as z from "zod"; -export const ETHIOPIA_STATIONS = new Set([ - "Addis Ababa", - "Adama", - "Mojo", - "Awash", - "Mieso", - "Dire Dawa", -]); - export const MOCK_VALID_CONTRACTS = [ "EDR-2024-10001", "EDR-2024-10002", @@ -23,8 +14,9 @@ export const STEPS = [ { id: 2, label: "Service Type & Mile", short: "Service" }, { id: 3, label: "Route", short: "Route" }, { id: 4, label: "Cargo Details", short: "Cargo" }, - { id: 5, label: "Documents", short: "Documents" }, - { id: 6, label: "Review & Submit", short: "Submit" }, + { id: 5, label: "Shipment Date", short: "Schedule" }, + { id: 6, label: "Documents", short: "Documents" }, + { id: 7, label: "Review & Submit", short: "Submit" }, ] as const; /** @@ -108,6 +100,7 @@ export const bookingFormSchema = z originYard: z.string().min(1, "Select an origin yard."), destinationYard: z.string().min(1, "Select a destination yard."), shippingLine: z.string(), + scheduledDate: z.string().min(1, "Select a shipment date."), cargoType: z.enum(["container", "bulk"], "Select a cargo type."), cargoWeight: z.string(), freightType: z.string(), // parent group @@ -235,6 +228,7 @@ export const initialBookingFormValues: DeepPartial = { originYard: "", destinationYard: "", shippingLine: "", + scheduledDate: "", cargoWeight: "", bulkCommoditytype: "", isHazardous: false, @@ -270,12 +264,11 @@ export const stepFields: Record>> = { "containers", "consolidationEnabled", ], - 5: ["documents"], - 6: ["notes", "termsAccepted"], + 5: ["scheduledDate"], + 6: ["documents"], + 7: ["notes", "termsAccepted"], }; -export type RouteDirection = "import" | "export" | "domestic" | null; - export interface ContainerConfig { type: "20ft" | "40ft"; containerType: string; @@ -296,35 +289,21 @@ export interface WagonCalcResult { ft20Wagons: number; } -export function genContractId(): string { - const yr = new Date().getFullYear(); - const n = Math.floor(10000 + Math.random() * 90000); - return `EDR-DRAFT-${yr}-${n}`; -} - export function getRouteDirection( - origin: string, - dest: string, -): RouteDirection { + origin: Freight.BookingReferenceYard | null | undefined, + dest: Freight.BookingReferenceYard | null | undefined, +): Freight.ScheduleTradeDirection | null { if (!origin || !dest) return null; - const oLocation = getStationLocation(origin); - const dLocation = getStationLocation(dest); - if (oLocation === "inside" && dLocation === "outside") return "export"; - if (oLocation === "outside" && dLocation === "inside") return "import"; - if (oLocation === "inside" && dLocation === "inside") return "domestic"; - - const oEth = ETHIOPIA_STATIONS.has(origin); - const dEth = ETHIOPIA_STATIONS.has(dest); - if (oEth && !dEth) return "export"; - if (!oEth && dEth) return "import"; - if (oEth && dEth) return "domestic"; - return null; +if(origin.country === 'ethiopia' && dest.country === 'ethiopia') { + return 'DOMESTIC'; } + if(origin.country === 'ethiopia' && dest.country === 'djibouti') { + return 'IMPORT'; + } + if(origin.country === 'djibouti' && dest.country === 'ethiopia') { + return 'EXPORT'; + } -function getStationLocation(value: string): "inside" | "outside" | null { - const normalized = value.trim().toLowerCase(); - if (normalized.startsWith("inside")) return "inside"; - if (normalized.startsWith("outside")) return "outside"; return null; } diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step4-route.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step4-route.tsx index c72d62d79..c74b3dfd1 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step4-route.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step4-route.tsx @@ -26,7 +26,7 @@ export function Step4Route({ const yardOptions = useMemo(() => { if (!referenceData?.yard) return []; - return referenceData.yard.map((y) => ({ value: y.name, label: y.name })); + return referenceData.yard.map((y) => ({ value: y.id, label: y.name })); }, [referenceData]); const shippingLineOptions = useMemo(() => { @@ -35,15 +35,40 @@ export function Step4Route({ }, [referenceData]); const originData = useMemo( - () => yardOptions.filter((o) => o.value !== destinationYard), + () => { + return yardOptions.filter((o) => o.value !== destinationYard).filter((o) => { + const dest = referenceData?.yard.find((y) => y.id === destinationYard); + if(!dest) return true; + const origin = referenceData?.yard.find((y) => y.id === o.value); + + // can't go from Djibouti to Djibouti + if(dest?.country === 'Djibouti' && origin?.country == 'Djibouti') return false; + + return true; + }); + }, [yardOptions, destinationYard], ); + console.log({yardOptions,originYard, destinationYard}) const destData = useMemo( - () => yardOptions.filter((o) => o.value !== originYard), + () => { + return yardOptions.filter((o) => o.value !== originYard).filter((d) => { + + + const origin = referenceData?.yard.find((y) => y.id === originYard); + if(!origin) return true; + + const dest = referenceData?.yard.find((y) => y.id === d.value); + // can't go from Djibouti to Djibouti + // if(origin.country === 'Djibouti' && dest?.country == 'Djibouti') return false; + + return true; + }); + }, [yardOptions, originYard], ); - const direction = getRouteDirection(originYard, destinationYard); + const direction = getRouteDirection(referenceData?.yard.find((y) => y.id === originYard), referenceData?.yard.find((y) => y.name === destinationYard)); const directionStyle: Record = { export: "bg-sky-50 text-sky-800 border-sky-200", @@ -57,7 +82,7 @@ export function Step4Route({ }; useEffect(() => { - if (direction === "domestic") { + if (direction === "DOMESTIC") { form.setValue("shippingLine", "", { shouldDirty: true }); } }, [direction]); @@ -117,7 +142,7 @@ export function Step4Route({ )} - {direction && direction !== "domestic" && ( + {direction && direction !== "DOMESTIC" && ( 0) { - const limit = direction === "export" ? 25 : 20; + const limit = direction === "EXPORT" ? 25 : 20; if (vgm > limit) { return `VGM ${vgm}t exceeds the ${limit}t ${direction ?? "standard"} limit for a 20ft container. An Overweight Surcharge will apply.`; } @@ -282,7 +281,7 @@ export function Step5CargoDetails({ val: "20ft" as const, label: "20ft Container (TEU)", limit: - direction === "export" + direction === "EXPORT" ? "Max 25t per container" : "Max 20t per container", }, 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 b547a47c9..53e809035 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 @@ -5,9 +5,9 @@ import { BOOKING_DOCS_SETTING, type BookingDocuments, type BookingFormValues, - type RouteDirection, } from "./schema"; import { StepHeader } from "./shared"; +import type { Freight } from "@/types"; type BookingForm = UseFormReturn; @@ -18,7 +18,7 @@ export function Step8Review({ }: { form: BookingForm; setStep: (step: number) => void; - direction: RouteDirection; + direction: Freight.ScheduleTradeDirection; }) { const values = form.watch(); const errors = form.formState.errors; From 28f9d58e0a45455f1df70c42fac16154604829cb Mon Sep 17 00:00:00 2001 From: ghost2023 Date: Fri, 12 Jun 2026 17:06:06 +0300 Subject: [PATCH 02/12] style: fix --- .../portal/src/pages/bookings/new-booking-form/shared.tsx | 3 +-- apps/edr-freight-web/portal/src/theme/mantine.ts | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/shared.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/shared.tsx index 4d5f8e33a..e4b53cfd1 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/shared.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/shared.tsx @@ -70,7 +70,7 @@ export function AlertBox({ export function StepLabel({ children }: { children: ReactNode }) { return ( - + {children} ); @@ -120,7 +120,6 @@ export function SelectField({ onChange={(v) => field.onChange(v ?? "")} onBlur={field.onBlur} error={error?.message} - radius="md" allowDeselect={false} /> ); diff --git a/apps/edr-freight-web/portal/src/theme/mantine.ts b/apps/edr-freight-web/portal/src/theme/mantine.ts index 865f6e29f..65a751db8 100644 --- a/apps/edr-freight-web/portal/src/theme/mantine.ts +++ b/apps/edr-freight-web/portal/src/theme/mantine.ts @@ -91,10 +91,10 @@ export const mantineTheme = createTheme({ fontSizes: { xs: "12px", - sm: "13px", - md: "14px", - lg: "16px", - xl: "18px", + sm: "14px", + md: "16px", + lg: "20px", + xl: "24px", }, lineHeights: { From 6058b870a17d8f250bb3b5fed3bc25629091d572 Mon Sep 17 00:00:00 2001 From: ghost2023 Date: Sat, 13 Jun 2026 09:29:45 +0300 Subject: [PATCH 03/12] feat(train-scheduling): implement API and types for bookable schedules --- .../portal/src/constants/URLS.ts | 4 +++ .../portal/src/services/api.ts | 7 ++++ .../portal/src/services/bookings.service.ts | 10 ++++++ packages/types/src/freight/index.ts | 33 +++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/apps/edr-freight-web/portal/src/constants/URLS.ts b/apps/edr-freight-web/portal/src/constants/URLS.ts index 578a1d97d..4e01ba78e 100644 --- a/apps/edr-freight-web/portal/src/constants/URLS.ts +++ b/apps/edr-freight-web/portal/src/constants/URLS.ts @@ -96,4 +96,8 @@ export const URL_CONSTANTS = { CANCEL: (id: string | number) => `/api/bookings/${id}/cancel`, CONFIRM: (id: string | number) => `/api/bookings/${id}/confirm`, }, + + TRAIN_SCHEDULING: { + BOOKABLE_SCHEDULES: "/api/train-scheduling/bookable-schedules", + }, }; diff --git a/apps/edr-freight-web/portal/src/services/api.ts b/apps/edr-freight-web/portal/src/services/api.ts index 645dc7f50..e1bd57729 100644 --- a/apps/edr-freight-web/portal/src/services/api.ts +++ b/apps/edr-freight-web/portal/src/services/api.ts @@ -185,6 +185,13 @@ export const api = { "checkPayment", ({ orderId }) => bookingsService.checkPayment(orderId), ), + + getBookableSchedules: endpoint< + { originYardId?: string; destinationYardId?: string }, + Freight.BookableScheduleItem[] + >("train-scheduling", "bookableSchedules", ({ originYardId, destinationYardId }) => + bookingsService.getBookableSchedules({ originYardId, destinationYardId }), + ), }, consignments: { diff --git a/apps/edr-freight-web/portal/src/services/bookings.service.ts b/apps/edr-freight-web/portal/src/services/bookings.service.ts index a8d36619d..f723e2730 100644 --- a/apps/edr-freight-web/portal/src/services/bookings.service.ts +++ b/apps/edr-freight-web/portal/src/services/bookings.service.ts @@ -151,4 +151,14 @@ export const bookingsService = { const { data } = await client.post(B.CONTRACT_SIGN(id), payload); return data.data ?? data; }, + + getBookableSchedules: async ( + query: Freight.BookableSchedulesQuery = {}, + ): Promise => { + const { data } = await client.get( + URL_CONSTANTS.TRAIN_SCHEDULING.BOOKABLE_SCHEDULES, + { params: query }, + ); + return data.data; + }, }; diff --git a/packages/types/src/freight/index.ts b/packages/types/src/freight/index.ts index e1620b41f..2ba2c9535 100644 --- a/packages/types/src/freight/index.ts +++ b/packages/types/src/freight/index.ts @@ -420,6 +420,39 @@ export interface BookingReferenceData { cargo_type: BookingReferenceCargoTypeGroup[]; } +// ── Train Scheduling (bookable schedules) ────────────────────────────────────── + +export interface BookableSchedulesQuery { + originYardId?: string; + destinationYardId?: string; +} + +export interface BookableScheduleLocomotive { + id: string; + code: string; + name: string | null; + readiness: string | null; +} + +export interface BookableScheduleItem { + id: string; + scheduleDate: string; + trainNumber: string | null; + routeName: string | null; + origin: string | null; + destination: string | null; + locomotive: BookableScheduleLocomotive | null; + wagonCount: number; + totalWeightTons: number; + totalLengthMeters: number; + bookingsCount: number; + freightType: FreightType | "MIXED" | null; + status: TrainScheduleStatus; + bookingWindowStatus: ScheduleBookingWindow; + maxWagons: number; + remainingWagons: number; +} + // ── DTOs ─────────────────────────────────────────────────────────────────────── export interface CreateBookingContainerDto { From 407cf3ed1ffa59cc2bf5f488a1f4ce93647be07b Mon Sep 17 00:00:00 2001 From: ghost2023 Date: Sat, 13 Jun 2026 11:24:16 +0300 Subject: [PATCH 04/12] fixes --- .../portal/src/pages/MyPortalPage.tsx | 492 +++++++++++++----- .../src/pages/accounts/OnboardingPage.tsx | 122 +++-- .../BookingDetailPage/DraftBookingView.tsx | 10 +- 3 files changed, 461 insertions(+), 163 deletions(-) diff --git a/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx b/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx index 5d6e9e808..cd72a826f 100644 --- a/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx @@ -1,4 +1,12 @@ -import { Box, Grid, Group, SimpleGrid, Skeleton, Stack, Text } from "@mantine/core"; +import { + Box, + Grid, + Group, + SimpleGrid, + Skeleton, + Stack, + Text, +} from "@mantine/core"; import { useQuery } from "@tanstack/react-query"; import { format } from "date-fns"; import { @@ -14,7 +22,7 @@ import { Zap, type LucideIcon, } from "lucide-react"; -import { useMemo, useState } from "react"; +import { useMemo } from "react"; import { Link, useNavigate } from "react-router-dom"; import useAuth from "@/hooks/useAuth"; @@ -30,7 +38,12 @@ const cv = (token: string) => { return `var(--mantine-color-${name}-${shade ?? "6"})`; }; -const ACTIVE_STATUSES = ["DRAFT", "SUBMITTED", "PENDING_APPROVAL", "IN_TRANSIT"]; +const ACTIVE_STATUSES = [ + "DRAFT", + "SUBMITTED", + "PENDING_APPROVAL", + "IN_TRANSIT", +]; interface StageConfig { stage: number; @@ -43,7 +56,11 @@ interface StageConfig { badgeBg: string; badgeText: string; badgeDot: string; - action: { label: string; kind: "dark" | "amber" | "outline"; icon?: LucideIcon }; + action: { + label: string; + kind: "dark" | "amber" | "outline"; + icon?: LucideIcon; + }; } const STATUS_CONFIG: Record = { @@ -146,7 +163,10 @@ const ACTION_PROPS: Record = { outline: { bg: "edr-card", c: "edr-text", bd: "1px solid edr-border" }, }; -const INVOICE_BADGE: Record = { +const INVOICE_BADGE: Record< + InvoiceStatus, + { label: string; bg: string; text: string } +> = { Draft: { label: "Draft", bg: "edr-slate-soft", text: "edr-slate" }, Sent: { label: "Due soon", bg: "edr-amber-soft", text: "edr-amber-text" }, Paid: { label: "Paid", bg: "edr-soft", text: "edr-green.7" }, @@ -157,108 +177,154 @@ const INVOICE_BADGE: Record getMyShipments(), []); const myInvoices = useMemo(() => getMyInvoices(), []); const navigate = useNavigate(); - const [tab, setTab] = useState("all"); const bookingsQuery = useQuery( - api.bookings.list.queryOptions({ input: { sortBy: "createdAt", sortOrder: "DESC" } }), + api.bookings.list.queryOptions({ + input: { sortBy: "createdAt", sortOrder: "DESC" }, + }), ); const allBookings = bookingsQuery.data?.items ?? []; - const activeBookings = allBookings.filter((b) => ACTIVE_STATUSES.includes(b.status)); + const activeBookings = allBookings.filter((b) => + ACTIVE_STATUSES.includes(b.status), + ); - const visibleBookings = allBookings + const visibleBookings = allBookings; const outstandingInvoices = myInvoices.filter( (inv) => inv.status === "Sent" || inv.status === "Overdue", ); - const totalOutstanding = outstandingInvoices.reduce((sum, inv) => sum + inv.amount, 0); - const deliveredCount = myShipments.filter((s) => s.status === "Delivered").length || 12; + const totalOutstanding = outstandingInvoices.reduce( + (sum, inv) => sum + inv.amount, + 0, + ); + const deliveredCount = + myShipments.filter((s) => s.status === "Delivered").length || 12; const displayName = user?.name?.en ?? user?.username ?? user?.email ?? "—"; const companyName = (customer as any)?.companyName ?? displayName; const hour = new Date().getHours(); - const greeting = hour < 12 ? "Good morning," : hour < 18 ? "Good afternoon," : "Good evening,"; + const greeting = + hour < 12 + ? "Good morning," + : hour < 18 + ? "Good afternoon," + : "Good evening,"; const recentInvoices = myInvoices.slice(0, 3); const maxVolume = Math.max(...VOLUME_DATA); return ( {/* ── Hello Row ─────────────────────────────────────────────────────── */} - + - {greeting} + + {greeting} + {companyName} 👋 {/* Book a shipment CTA */} - - + + - - - Book a shipment - - - - - + + + + Book a shipment + + + + + + + {/* ── Stats Strip ───────────────────────────────────────────────────── */} - - - - + + + + {/* ── Mid Row: Shipments + Invoices ─────────────────────────────────── */} - + - My Shipments - From draft to delivery — every booking in one place + + My Shipments + + + From draft to delivery — every booking in one place + - {bookingsQuery.isPending ? ( - {[1, 2, 3, 4].map((i) => )} + + {[1, 2, 3, 4].map((i) => ( + + ))} + ) : visibleBookings.length === 0 ? ( ) : ( {visibleBookings.map((booking, i) => ( - navigate(`/bookings/${booking.id}`)} /> + navigate(`/bookings/${booking.id}`)} + /> ))} )} @@ -269,22 +335,48 @@ export default function MyPortalPage() { - Invoices - - View all - - + + Invoices + + + + + View all + + + + {/* Outstanding card */} - Outstanding balance - {formatCurrency(totalOutstanding || 377500, "ETB")} - - {outstandingInvoices.length || 2} invoices unpaid - + + Outstanding balance + + + {formatCurrency(totalOutstanding || 377500, "ETB")} + + + + {outstandingInvoices.length || 2} invoices unpaid + + - Pay all + + Pay all + @@ -302,26 +394,53 @@ export default function MyPortalPage() { : invoice.status === "Overdue" ? "Overdue 3 days" : `Due ${invoice.dueDate}`; - const DueIcon = invoice.status === "Paid" ? CheckCircle2 : Clock3; - const dueIconColor = invoice.status === "Paid" ? cv("edr-green.5") : cv("edr-muted"); + const DueIcon = + invoice.status === "Paid" ? CheckCircle2 : Clock3; + const dueIconColor = + invoice.status === "Paid" + ? cv("edr-green.5") + : cv("edr-muted"); return ( {i > 0 && } - + - {invoice.number} - {invoice.bookingReference} + + {invoice.number} + + + {invoice.bookingReference} + - {formatCurrency(invoice.amount, invoice.currency)} + + {formatCurrency(invoice.amount, invoice.currency)} + - + - {dueText} + + {dueText} + - - {badge.label} + + + {badge.label} + @@ -335,27 +454,40 @@ export default function MyPortalPage() { {/* ── Bottom Row: Freight Volume + Recent Activity ──────────────────── */} - + - Freight Volume + + Freight Volume + - 4,180 t - ETB 1.24M - +16% YTD + + 4,180 t + + + ETB 1.24M + + + +16% YTD + {VOLUME_DATA.map((val, i) => { const isLast = i === VOLUME_DATA.length - 1; return ( - + - {MONTHS[i]} + + {MONTHS[i]} + ); })} @@ -366,21 +498,35 @@ export default function MyPortalPage() { - Recent Activity - - View all - - + + Recent Activity + + + + + View all + + + + {bookingsQuery.isPending ? ( - {[1, 2, 3, 4, 5].map((i) => )} + + {[1, 2, 3, 4, 5].map((i) => ( + + ))} + ) : allBookings.length === 0 ? ( ) : ( {allBookings.slice(0, 6).map((booking) => ( - navigate(`/bookings/${booking.id}`)} /> + navigate(`/bookings/${booking.id}`)} + /> ))} )} @@ -403,7 +549,10 @@ function Card({ padding?: number; }) { return ( - + {children} ); @@ -425,14 +574,25 @@ function StatKpi({ divider?: boolean; }) { return ( - + - {label} + + {label} + - {value} - {delta} + + {value} + + + {delta} + ); @@ -446,9 +606,26 @@ function Stepper({ stage, color }: { stage: number; color: string }) { const active = i === stage; const size = active ? 12 : done ? 9 : 8; return ( - - - {i < 4 && } + + + {i < 4 && ( + + )} ); })} @@ -456,43 +633,97 @@ function Stepper({ stage, color }: { stage: number; color: string }) { ); } -function BookingRow({ booking, last, onClick }: { booking: any; last: boolean; onClick: () => void }) { +function BookingRow({ + booking, + last, + onClick, +}: { + booking: any; + last: boolean; + onClick: () => void; +}) { const cfg = STATUS_CONFIG[booking.status] ?? STATUS_CONFIG.DRAFT; const Icon = cfg.icon; const AIcon = cfg.action.icon; const ap = ACTION_PROPS[cfg.action.kind]; const origin = booking.originYard?.label ?? booking.originYard?.code ?? "—"; - const dest = booking.destinationYard?.label ?? booking.destinationYard?.code ?? "—"; + const dest = + booking.destinationYard?.label ?? booking.destinationYard?.code ?? "—"; const commodity = - (typeof booking.cargoType === "string" ? booking.cargoType : booking.cargoType?.name) ?? + (typeof booking.cargoType === "string" + ? booking.cargoType + : booking.cargoType?.name) ?? booking.commodity ?? "Freight"; return ( - - + + - {booking.reference} - {commodity} · {origin} → {dest} + + {booking.reference} + + + {commodity} · {origin} → {dest} + - {cfg.hint} + + {cfg.hint} + - + - {cfg.badgeLabel} + + {cfg.badgeLabel} + - - {cfg.action.label} - {AIcon && } + + + {cfg.action.label} + + {AIcon && ( + + )} @@ -500,7 +731,13 @@ function BookingRow({ booking, last, onClick }: { booking: any; last: boolean; o ); } -function ActivityRow({ booking, onClick }: { booking: any; onClick: () => void }) { +function ActivityRow({ + booking, + onClick, +}: { + booking: any; + onClick: () => void; +}) { const cfg = STATUS_CONFIG[booking.status] ?? STATUS_CONFIG.DRAFT; const Icon = cfg.icon; const verb = @@ -514,26 +751,49 @@ function ActivityRow({ booking, onClick }: { booking: any; onClick: () => void } ? "submitted for review" : "created"; return ( - - + + - Booking {booking.reference} {verb} + + Booking {booking.reference} {verb} + {booking.originYard?.label ?? booking.originYard?.code ?? "—"} →{" "} - {booking.destinationYard?.label ?? booking.destinationYard?.code ?? "—"} + {booking.destinationYard?.label ?? + booking.destinationYard?.code ?? + "—"} - {format(new Date(booking.createdAt), "MMM d")} + + {format(new Date(booking.createdAt), "MMM d")} + ); } function EmptyState({ message }: { message: string }) { return ( - - {message} + + + {message} + ); } diff --git a/apps/edr-freight-web/portal/src/pages/accounts/OnboardingPage.tsx b/apps/edr-freight-web/portal/src/pages/accounts/OnboardingPage.tsx index 939088973..861fbbb75 100644 --- a/apps/edr-freight-web/portal/src/pages/accounts/OnboardingPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/accounts/OnboardingPage.tsx @@ -1,12 +1,18 @@ -import { Box, Group, SimpleGrid, Stack, Text, ThemeIcon, UnstyledButton } from "@mantine/core"; +import { + Box, + Group, + SimpleGrid, + Stack, + Text, + ThemeIcon, + UnstyledButton, +} from "@mantine/core"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { ArrowDownToLine, ArrowUpFromLine, Building2, ChevronRight, - Ship, - Truck, } from "lucide-react"; import { useState } from "react"; @@ -27,37 +33,37 @@ const USER_TYPE_CARDS: { description: string; icon: React.ReactNode; }[] = [ - { - id: "importer", - label: "Importer", - description: "Import goods into Ethiopia via the railway corridor.", - icon: , - }, - { - id: "exporter", - label: "Exporter", - description: "Export goods from Ethiopia via rail.", - icon: , - }, - { - id: "freight-forwarder-et", - label: "Freight Forwarder (Ethiopia)", - description: "Ethiopian freight forwarding company handling client cargo.", - icon: , - }, - { - id: "freight-forwarder-dj", - label: "FF Agent (Djibouti)", - description: "Djibouti-based agent coordinating cross-border logistics.", - icon: , - }, - { - id: "transporter", - label: "Transporter", - description: "Trucking company providing first/last-mile services.", - icon: , - }, -]; + { + id: "importer", + label: "Importer", + description: "Import goods into Ethiopia via the railway corridor.", + icon: , + }, + { + id: "exporter", + label: "Exporter", + description: "Export goods from Ethiopia via rail.", + icon: , + }, + { + id: "freight-forwarder-et", + label: "Freight Forwarder (Ethiopia)", + description: "Ethiopian freight forwarding company handling client cargo.", + icon: , + }, + // { + // id: "freight-forwarder-dj", + // label: "FF Agent (Djibouti)", + // description: "Djibouti-based agent coordinating cross-border logistics.", + // icon: , + // }, + // { + // id: "transporter", + // label: "Transporter", + // description: "Trucking company providing first/last-mile services.", + // icon: , + // }, + ]; const USER_TYPE_LEFT_MAP: Record< OnboardingUserType, @@ -105,7 +111,12 @@ const PREFLIGHT_LEFT = { "Freight Forwarders (Ethiopia & Djibouti)", "Transporters & Fleet Operators", ], - stats: { label: "Active Customers", value: "500+", footer: "And growing", progress: "w-[95%]" }, + stats: { + label: "Active Customers", + value: "500+", + footer: "And growing", + progress: "w-[95%]", + }, }; const DOCUMENT_SETTING_CODE_MAP: Record = { @@ -120,7 +131,9 @@ export default function OnboardingPage() { const queryClient = useQueryClient(); const { user } = useAuth(); const [userType, setUserType] = useState(null); - const [documentFiles, setDocumentFiles] = useState>({}); + const [documentFiles, setDocumentFiles] = useState< + Record + >({}); const COMPANY_TYPE_MAP: Record = { importer: "customer", @@ -131,7 +144,8 @@ export default function OnboardingPage() { }; const createCompanyMutation = useMutation({ - mutationFn: (payload: CreateCompanyPayload) => api.companies.create.call(payload), + mutationFn: (payload: CreateCompanyPayload) => + api.companies.create.call(payload), onSuccess: async (data) => { const hasFiles = Object.values(documentFiles).some( (f) => f !== null && (Array.isArray(f) ? f.length > 0 : true), @@ -139,14 +153,19 @@ export default function OnboardingPage() { if (hasFiles) { await companiesService.uploadDocuments(data.company.id, documentFiles); } - await queryClient.invalidateQueries({ queryKey: api.companies.getInfo.queryKey() }); + await queryClient.invalidateQueries({ + queryKey: api.companies.getInfo.queryKey(), + }); }, }); if (!user) return null; const handleSubmit = (payload: CreateCompanyPayload) => { - const enriched: CreateCompanyPayload = { ...payload, companyType: COMPANY_TYPE_MAP[userType!] }; + const enriched: CreateCompanyPayload = { + ...payload, + companyType: COMPANY_TYPE_MAP[userType!], + }; createCompanyMutation.mutate(enriched); }; @@ -209,11 +228,28 @@ export default function OnboardingPage() { ...leftConfig, features: userType === "transporter" - ? ["Vehicle & fleet registration", "TIN & FAN verification", "First-mile / Last-mile eligibility"] + ? [ + "Vehicle & fleet registration", + "TIN & FAN verification", + "First-mile / Last-mile eligibility", + ] : userType === "freight-forwarder-dj" - ? ["Company details", "Representative information", "Cross-border operations"] - : ["Company registration details", "Contact and management personnel", "Power of Attorney (optional)"], - stats: { label: "Active Customers", value: "500+", footer: "And growing", progress: "w-[95%]" }, + ? [ + "Company details", + "Representative information", + "Cross-border operations", + ] + : [ + "Company registration details", + "Contact and management personnel", + "Power of Attorney (optional)", + ], + stats: { + label: "Active Customers", + value: "500+", + footer: "And growing", + progress: "w-[95%]", + }, }; return ( 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 e69a024cc..38238680a 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 @@ -71,10 +71,12 @@ export function DraftBookingView({ ).length; const allDocsUploaded = uploadedCount === REQUIRED_DOC_FIELDS.length; - const { data: generatedPricing } = useQuery({ - ...api.bookings.generatePrice.queryOptions({ input: { id: booking.id } }), - enabled: booking.status === "DRAFT" && !booking.pricingBreakdown, - }); + const { data: generatedPricing } = useQuery( + api.bookings.generatePrice.queryOptions({ input: { id: booking.id }, + + enabled: booking.status === "DRAFT" && !booking.pricingBreakdown, + }), + ); const pricing = booking.pricingBreakdown ?? generatedPricing ?? null; const uploadMutation = useMutation({ From 9aecbb65089dca12271fbe5575437524e95c5c88 Mon Sep 17 00:00:00 2001 From: ghost2023 Date: Sat, 13 Jun 2026 11:26:57 +0300 Subject: [PATCH 05/12] feat(booking): Implement train schedule selection and update booking data structures --- .../train-scheduling.controller.ts | 348 +++++++++------- apps/edr-freight-web/portal/package.json | 1 + .../src/pages/bookings/NewBookingPage.tsx | 131 +++--- .../pages/bookings/new-booking-form/schema.ts | 42 +- .../new-booking-form/step-documents.tsx | 13 +- .../new-booking-form/step-scheduling.tsx | 389 ++++++++++++++++++ .../new-booking-form/step5-cargo-details.tsx | 81 +++- .../step6-wagon-allocation.tsx | 111 ----- .../pages/bookings/new-booking-form/steps.tsx | 1 + packages/types/src/freight/index.ts | 2 +- pnpm-lock.yaml | 222 +++------- 11 files changed, 798 insertions(+), 543 deletions(-) create mode 100644 apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-scheduling.tsx delete mode 100644 apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step6-wagon-allocation.tsx diff --git a/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.controller.ts b/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.controller.ts index 3c191c713..3ef7693ab 100644 --- a/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.controller.ts +++ b/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.controller.ts @@ -8,87 +8,98 @@ import { Patch, Post, Query, -} from '@nestjs/common'; -import { CurrentUser } from '@edr/api-common'; -import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; -import type { AuthUserPayload } from '../../common/resolve-auth-user-id'; -import { resolveAuthUserId } from '../../common/resolve-auth-user-id'; +} from "@nestjs/common"; +import { CurrentUser } from "@edr/api-common"; +import { ApiBearerAuth, ApiOperation, ApiTags } from "@nestjs/swagger"; +import type { AuthUserPayload } from "../../common/resolve-auth-user-id"; +import { resolveAuthUserId } from "../../common/resolve-auth-user-id"; -import { TrainSchedulingManage, TrainSchedulingView } from '../../common/booking-guards'; -import { AssignBookingsDto } from './dto/assign-bookings.dto'; -import { AssignUnassignedBookingDto } from './dto/assign-unassigned-booking.dto'; -import { CreateContainerTrainScheduleDto } from './dto/create-container-train-schedule.dto'; -import { GetEligibleBookingsDto } from './dto/get-eligible-bookings.dto'; -import { GetEligibleBulkBookingsDto } from './dto/get-eligible-bulk-bookings.dto'; -import { GetEligibleContainerBookingsDto } from './dto/get-eligible-container-bookings.dto'; -import { PinWagonsDto } from './dto/pin-wagons.dto'; -import { UpdateContainerItemDto } from './dto/update-container-item.dto'; -import { PreviewBulkTrainScheduleDto } from './dto/preview-bulk-train-schedule.dto'; -import { PreviewContainerTrainScheduleDto } from './dto/preview-container-train-schedule.dto'; -import { PreviewTrainScheduleDto } from './dto/preview-train-schedule.dto'; -import { RecordCheckpointDto } from './dto/record-checkpoint.dto'; -import { AvailableLocomotivesQueryDto } from './dto/available-locomotives-query.dto'; -import { BookableSchedulesQueryDto } from './dto/bookable-schedules-query.dto'; -import { UpdateTrainSchedulingGlobalRulesDto } from './dto/update-train-scheduling-global-rules.dto'; -import { TrainSchedulingService } from './train-scheduling.service'; -import { BookingBatchService } from './booking-batch.service'; +import { + TrainSchedulingManage, + TrainSchedulingView, +} from "../../common/booking-guards"; +import { AssignBookingsDto } from "./dto/assign-bookings.dto"; +import { AssignUnassignedBookingDto } from "./dto/assign-unassigned-booking.dto"; +import { CreateContainerTrainScheduleDto } from "./dto/create-container-train-schedule.dto"; +import { GetEligibleBookingsDto } from "./dto/get-eligible-bookings.dto"; +import { GetEligibleBulkBookingsDto } from "./dto/get-eligible-bulk-bookings.dto"; +import { GetEligibleContainerBookingsDto } from "./dto/get-eligible-container-bookings.dto"; +import { PinWagonsDto } from "./dto/pin-wagons.dto"; +import { UpdateContainerItemDto } from "./dto/update-container-item.dto"; +import { PreviewBulkTrainScheduleDto } from "./dto/preview-bulk-train-schedule.dto"; +import { PreviewContainerTrainScheduleDto } from "./dto/preview-container-train-schedule.dto"; +import { PreviewTrainScheduleDto } from "./dto/preview-train-schedule.dto"; +import { RecordCheckpointDto } from "./dto/record-checkpoint.dto"; +import { AvailableLocomotivesQueryDto } from "./dto/available-locomotives-query.dto"; +import { BookableSchedulesQueryDto } from "./dto/bookable-schedules-query.dto"; +import { UpdateTrainSchedulingGlobalRulesDto } from "./dto/update-train-scheduling-global-rules.dto"; +import { TrainSchedulingService } from "./train-scheduling.service"; +import { BookingBatchService } from "./booking-batch.service"; -@ApiTags('train-scheduling') +@ApiTags("train-scheduling") @ApiBearerAuth() -@Controller('train-scheduling') +@Controller("train-scheduling") export class TrainSchedulingController { constructor( private readonly trainSchedulingService: TrainSchedulingService, private readonly bookingBatchService: BookingBatchService, - ) {} + ) { } - @Get('global-rules') + @Get("global-rules") @TrainSchedulingView() - @ApiOperation({ summary: 'Get global train scheduling rules (singleton)' }) + @ApiOperation({ summary: "Get global train scheduling rules (singleton)" }) getGlobalRules() { return this.trainSchedulingService.getTrainSchedulingGlobalRules(); } - @Patch('global-rules') + @Patch("global-rules") @TrainSchedulingManage() - @ApiOperation({ summary: 'Update global train scheduling rules (singleton)' }) + @ApiOperation({ summary: "Update global train scheduling rules (singleton)" }) updateGlobalRules(@Body() dto: UpdateTrainSchedulingGlobalRulesDto) { return this.trainSchedulingService.updateTrainSchedulingGlobalRules(dto); } - @Get('eligible-bookings') + @Get("eligible-bookings") @TrainSchedulingView() - @ApiOperation({ summary: 'List eligible bookings (container and/or bulk)' }) + @ApiOperation({ summary: "List eligible bookings (container and/or bulk)" }) getEligibleBookings(@Query() query: GetEligibleBookingsDto) { return this.trainSchedulingService.getEligibleBookings(query); } - @Get('batch-board') + @Get("batch-board") @TrainSchedulingView() - @ApiOperation({ summary: 'Batch monitoring board: schedules with bookings grouped by state' }) + @ApiOperation({ + summary: "Batch monitoring board: schedules with bookings grouped by state", + }) getBatchBoard() { return this.bookingBatchService.getBatchBoard(); } - @Get('batch-board/:scheduleId') + @Get("batch-board/:scheduleId") @TrainSchedulingView() - @ApiOperation({ summary: 'Batch board detail for one schedule with EAT 3h windows' }) - getBatchBoardDetail(@Param('scheduleId', ParseUUIDPipe) scheduleId: string) { + @ApiOperation({ + summary: "Batch board detail for one schedule with EAT 3h windows", + }) + getBatchBoardDetail(@Param("scheduleId", ParseUUIDPipe) scheduleId: string) { return this.bookingBatchService.getBatchBoardDetail(scheduleId); } - @Get('available-locomotives') + @Get("available-locomotives") @TrainSchedulingView() @ApiOperation({ - summary: 'List AVAILABLE locomotives at the route origin yard', + summary: "List AVAILABLE locomotives at the route origin yard", }) getAvailableLocomotives(@Query() query: AvailableLocomotivesQueryDto) { - return this.trainSchedulingService.getAvailableLocomotivesForRoute(query.routeId); + return this.trainSchedulingService.getAvailableLocomotivesForRoute( + query.routeId, + ); } - @Get('bookable-schedules') - @TrainSchedulingView() - @ApiOperation({ summary: 'OPEN same-route schedules a new booking can target' }) + @Get("bookable-schedules") + // @TrainSchedulingView() + @ApiOperation({ + summary: "OPEN same-route schedules a new booking can target", + }) getBookableSchedules(@Query() query: BookableSchedulesQueryDto) { return this.trainSchedulingService.getBookableSchedules( query.originYardId, @@ -96,282 +107,323 @@ export class TrainSchedulingController { ); } - @Get('container/eligible-bookings') + @Get("container/eligible-bookings") @TrainSchedulingView() - @ApiOperation({ summary: 'List eligible container bookings' }) - getEligibleContainerBookings(@Query() query: GetEligibleContainerBookingsDto) { + @ApiOperation({ summary: "List eligible container bookings" }) + getEligibleContainerBookings( + @Query() query: GetEligibleContainerBookingsDto, + ) { return this.trainSchedulingService.getEligibleContainerBookings(query); } - @Get('bulk/eligible-bookings') + @Get("bulk/eligible-bookings") @TrainSchedulingView() - @ApiOperation({ summary: 'List eligible bulk bookings' }) + @ApiOperation({ summary: "List eligible bulk bookings" }) getEligibleBulkBookings(@Query() query: GetEligibleBulkBookingsDto) { return this.trainSchedulingService.getEligibleBulkBookings(query); } - @Post('preview') + @Post("preview") @TrainSchedulingView() - @ApiOperation({ summary: 'Preview a mixed-capable train schedule' }) + @ApiOperation({ summary: "Preview a mixed-capable train schedule" }) previewTrainSchedule(@Body() dto: PreviewTrainScheduleDto) { return this.trainSchedulingService.previewTrainSchedule(dto); } - @Post('container/preview') + @Post("container/preview") @TrainSchedulingView() - @ApiOperation({ summary: 'Preview a container train schedule' }) + @ApiOperation({ summary: "Preview a container train schedule" }) previewContainerTrainSchedule(@Body() dto: PreviewContainerTrainScheduleDto) { return this.trainSchedulingService.previewContainerTrainSchedule(dto); } - @Post('bulk/preview') + @Post("bulk/preview") @TrainSchedulingView() - @ApiOperation({ summary: 'Preview a bulk train schedule' }) + @ApiOperation({ summary: "Preview a bulk train schedule" }) previewBulkTrainSchedule(@Body() dto: PreviewBulkTrainScheduleDto) { return this.trainSchedulingService.previewBulkTrainSchedule(dto); } - @Post('container/schedules') + @Post("container/schedules") @TrainSchedulingManage() - @ApiOperation({ summary: 'Create a container train schedule' }) + @ApiOperation({ summary: "Create a container train schedule" }) createContainerTrainSchedule(@Body() dto: CreateContainerTrainScheduleDto) { return this.trainSchedulingService.createContainerTrainSchedule(dto); } - @Post('bulk/schedules') + @Post("bulk/schedules") @TrainSchedulingManage() - @ApiOperation({ summary: 'Create a bulk train schedule' }) + @ApiOperation({ summary: "Create a bulk train schedule" }) createBulkTrainSchedule(@Body() dto: CreateContainerTrainScheduleDto) { return this.trainSchedulingService.createContainerTrainSchedule(dto); } - @Post('schedules/:id/assign-bookings') + @Post("schedules/:id/assign-bookings") @TrainSchedulingManage() - @ApiOperation({ summary: 'Assign bookings to a train schedule (mixed-capable)' }) + @ApiOperation({ + summary: "Assign bookings to a train schedule (mixed-capable)", + }) assignBookings( - @Param('id', ParseUUIDPipe) id: string, + @Param("id", ParseUUIDPipe) id: string, @Body() dto: AssignBookingsDto, ) { return this.trainSchedulingService.assignBookingsToSchedule(id, dto); } - @Post('container/schedules/:id/assign-bookings') + @Post("container/schedules/:id/assign-bookings") @TrainSchedulingManage() - @ApiOperation({ summary: 'Assign container bookings to a train schedule' }) + @ApiOperation({ summary: "Assign container bookings to a train schedule" }) assignContainerBookings( - @Param('id', ParseUUIDPipe) id: string, + @Param("id", ParseUUIDPipe) id: string, @Body() dto: AssignBookingsDto, ) { - return this.trainSchedulingService.assignBookingsToSchedule(id, dto, 'CONTAINER'); + return this.trainSchedulingService.assignBookingsToSchedule( + id, + dto, + "CONTAINER", + ); } - @Post('bulk/schedules/:id/assign-bookings') + @Post("bulk/schedules/:id/assign-bookings") @TrainSchedulingManage() - @ApiOperation({ summary: 'Assign bulk bookings to a train schedule' }) + @ApiOperation({ summary: "Assign bulk bookings to a train schedule" }) assignBulkBookings( - @Param('id', ParseUUIDPipe) id: string, + @Param("id", ParseUUIDPipe) id: string, @Body() dto: AssignBookingsDto, ) { - return this.trainSchedulingService.assignBookingsToSchedule(id, dto, 'BULK'); + return this.trainSchedulingService.assignBookingsToSchedule( + id, + dto, + "BULK", + ); } - @Delete('schedules/:id/bookings/:bookingId') + @Delete("schedules/:id/bookings/:bookingId") @TrainSchedulingManage() - @ApiOperation({ summary: 'Unassign a booking from a train schedule' }) + @ApiOperation({ summary: "Unassign a booking from a train schedule" }) unassignBooking( - @Param('id', ParseUUIDPipe) id: string, - @Param('bookingId', ParseUUIDPipe) bookingId: string, + @Param("id", ParseUUIDPipe) id: string, + @Param("bookingId", ParseUUIDPipe) bookingId: string, @CurrentUser() user: AuthUserPayload, ) { - return this.trainSchedulingService.unassignBooking(id, bookingId, resolveAuthUserId(user)); + return this.trainSchedulingService.unassignBooking( + id, + bookingId, + resolveAuthUserId(user), + ); } - @Delete('schedules/:id/wagons/:trainSetWagonId') + @Delete("schedules/:id/wagons/:trainSetWagonId") @TrainSchedulingManage() - @ApiOperation({ summary: 'Remove an empty wagon slot from a train' }) + @ApiOperation({ summary: "Remove an empty wagon slot from a train" }) removeWagonSlot( - @Param('id', ParseUUIDPipe) id: string, - @Param('trainSetWagonId', ParseUUIDPipe) trainSetWagonId: string, + @Param("id", ParseUUIDPipe) id: string, + @Param("trainSetWagonId", ParseUUIDPipe) trainSetWagonId: string, ) { - return this.trainSchedulingService.removeTrainSetWagonSlot(id, trainSetWagonId); + return this.trainSchedulingService.removeTrainSetWagonSlot( + id, + trainSetWagonId, + ); } - @Patch('schedules/:id/container-items/:itemId') + @Patch("schedules/:id/container-items/:itemId") @TrainSchedulingManage() - @ApiOperation({ summary: 'Update a container number on a wagon slot' }) + @ApiOperation({ summary: "Update a container number on a wagon slot" }) updateContainerItem( - @Param('id', ParseUUIDPipe) id: string, - @Param('itemId', ParseUUIDPipe) itemId: string, + @Param("id", ParseUUIDPipe) id: string, + @Param("itemId", ParseUUIDPipe) itemId: string, @Body() dto: UpdateContainerItemDto, ) { return this.trainSchedulingService.updateContainerItem(id, itemId, dto); } - @Get('schedules/:id/unassigned-bookings') + @Get("schedules/:id/unassigned-bookings") @TrainSchedulingView() - @ApiOperation({ summary: 'Get unassigned bookings for a schedule' }) - getUnassignedBookings(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ summary: "Get unassigned bookings for a schedule" }) + getUnassignedBookings(@Param("id", ParseUUIDPipe) id: string) { return this.trainSchedulingService.getUnassignedBookings(id); } - @Post('schedules/:id/assign-unassigned-booking') + @Post("schedules/:id/assign-unassigned-booking") @TrainSchedulingManage() @ApiOperation({ - summary: 'Assign one linked unallocated booking to wagons (preserves existing assignments)', + summary: + "Assign one linked unallocated booking to wagons (preserves existing assignments)", }) assignUnassignedBooking( - @Param('id', ParseUUIDPipe) id: string, + @Param("id", ParseUUIDPipe) id: string, @Body() dto: AssignUnassignedBookingDto, ) { - return this.trainSchedulingService.assignUnassignedBookingToWagons(id, dto.bookingId); + return this.trainSchedulingService.assignUnassignedBookingToWagons( + id, + dto.bookingId, + ); } - @Get('schedules/:id/composition-removals') + @Get("schedules/:id/composition-removals") @TrainSchedulingView() - @ApiOperation({ summary: 'Get removal log for a schedule' }) - getCompositionRemovals(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ summary: "Get removal log for a schedule" }) + getCompositionRemovals(@Param("id", ParseUUIDPipe) id: string) { return this.trainSchedulingService.getCompositionRemovals(id); } - @Post('schedules/:id/pin-wagons') + @Post("schedules/:id/pin-wagons") @TrainSchedulingManage() - @ApiOperation({ summary: 'Pin physical wagons to train set slots' }) - pinWagons(@Param('id', ParseUUIDPipe) id: string, @Body() dto: PinWagonsDto) { + @ApiOperation({ summary: "Pin physical wagons to train set slots" }) + pinWagons(@Param("id", ParseUUIDPipe) id: string, @Body() dto: PinWagonsDto) { return this.trainSchedulingService.pinWagons(id, dto); } - @Post('schedules/:id/finalize') + @Post("schedules/:id/finalize") @TrainSchedulingManage() - @ApiOperation({ summary: 'Finalize a draft train schedule' }) - finalizeSchedule(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ summary: "Finalize a draft train schedule" }) + finalizeSchedule(@Param("id", ParseUUIDPipe) id: string) { return this.trainSchedulingService.finalizeSchedule(id); } - @Post('schedules/:id/dispatch') + @Post("schedules/:id/dispatch") @TrainSchedulingManage() - @ApiOperation({ summary: 'Dispatch a scheduled train' }) - dispatchSchedule(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ summary: "Dispatch a scheduled train" }) + dispatchSchedule(@Param("id", ParseUUIDPipe) id: string) { return this.trainSchedulingService.dispatchSchedule(id); } // ---- batch / booking-window staff actions ---- - @Post('schedules/:id/run-batch') + @Post("schedules/:id/run-batch") @TrainSchedulingManage() - @ApiOperation({ summary: 'Manually run the batch fill for a schedule' }) - async runBatch(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ summary: "Manually run the batch fill for a schedule" }) + async runBatch(@Param("id", ParseUUIDPipe) id: string) { await this.bookingBatchService.fillSchedule(id); return this.bookingBatchService.getBatchBoardDetail(id); } - @Post('schedules/:id/run-allocation') + @Post("schedules/:id/run-allocation") @TrainSchedulingManage() - @ApiOperation({ summary: 'Run wagon-level allocation for all eligible linked bookings' }) - async runAllocation(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ + summary: "Run wagon-level allocation for all eligible linked bookings", + }) + async runAllocation(@Param("id", ParseUUIDPipe) id: string) { return this.bookingBatchService.runWagonAllocation(id); } - @Patch('schedules/:id/booking-window') + @Patch("schedules/:id/booking-window") @TrainSchedulingManage() - @ApiOperation({ summary: 'Open or close a schedule booking window' }) + @ApiOperation({ summary: "Open or close a schedule booking window" }) async setBookingWindow( - @Param('id', ParseUUIDPipe) id: string, - @Body('status') status: 'OPEN' | 'CLOSED', + @Param("id", ParseUUIDPipe) id: string, + @Body("status") status: "OPEN" | "CLOSED", ) { - await this.trainSchedulingService.setBookingWindow(id, status === 'CLOSED' ? 'CLOSED' : 'OPEN'); + await this.trainSchedulingService.setBookingWindow( + id, + status === "CLOSED" ? "CLOSED" : "OPEN", + ); return this.trainSchedulingService.getContainerTrainScheduleById(id); } - @Post('bookings/:bookingId/mark-paid') + @Post("bookings/:bookingId/mark-paid") @TrainSchedulingManage() - @ApiOperation({ summary: 'Staff: mark a reserved booking paid and allocate it now' }) - async markBookingPaid(@Param('bookingId', ParseUUIDPipe) bookingId: string) { + @ApiOperation({ + summary: "Staff: mark a reserved booking paid and allocate it now", + }) + async markBookingPaid(@Param("bookingId", ParseUUIDPipe) bookingId: string) { await this.bookingBatchService.markPaid(bookingId); return { ok: true }; } - @Post('bookings/:bookingId/expire') + @Post("bookings/:bookingId/expire") @TrainSchedulingManage() - @ApiOperation({ summary: 'Staff: expire a reservation and free its capacity' }) - async expireBooking(@Param('bookingId', ParseUUIDPipe) bookingId: string) { + @ApiOperation({ + summary: "Staff: expire a reservation and free its capacity", + }) + async expireBooking(@Param("bookingId", ParseUUIDPipe) bookingId: string) { await this.bookingBatchService.expireReservation(bookingId); return { ok: true }; } - @Post('bookings/:bookingId/move-schedule') + @Post("bookings/:bookingId/move-schedule") @TrainSchedulingManage() - @ApiOperation({ summary: 'Re-point a booking to another OPEN same-route schedule' }) + @ApiOperation({ + summary: "Re-point a booking to another OPEN same-route schedule", + }) async moveBookingSchedule( - @Param('bookingId', ParseUUIDPipe) bookingId: string, - @Body('trainScheduleId', ParseUUIDPipe) trainScheduleId: string, + @Param("bookingId", ParseUUIDPipe) bookingId: string, + @Body("trainScheduleId", ParseUUIDPipe) trainScheduleId: string, ) { await this.bookingBatchService.moveToSchedule(bookingId, trainScheduleId); return { ok: true }; } - @Get('schedules/:id/checkpoints') + @Get("schedules/:id/checkpoints") @TrainSchedulingView() - @ApiOperation({ summary: 'Get the tracking corridor + logged checkpoints for a train' }) - getScheduleCheckpoints(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ + summary: "Get the tracking corridor + logged checkpoints for a train", + }) + getScheduleCheckpoints(@Param("id", ParseUUIDPipe) id: string) { return this.trainSchedulingService.getScheduleCheckpoints(id); } - @Post('schedules/:id/checkpoints') + @Post("schedules/:id/checkpoints") @TrainSchedulingManage() - @ApiOperation({ summary: 'Log the train passing a station (final station triggers arrival)' }) + @ApiOperation({ + summary: "Log the train passing a station (final station triggers arrival)", + }) recordCheckpoint( - @Param('id', ParseUUIDPipe) id: string, + @Param("id", ParseUUIDPipe) id: string, @Body() dto: RecordCheckpointDto, ) { return this.trainSchedulingService.recordCheckpoint(id, dto); } - @Post('schedules/:id/arrive') + @Post("schedules/:id/arrive") @TrainSchedulingManage() - @ApiOperation({ summary: 'Mark a dispatched train arrived (move assets to destination yard, free assets)' }) - arriveSchedule(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ + summary: + "Mark a dispatched train arrived (move assets to destination yard, free assets)", + }) + arriveSchedule(@Param("id", ParseUUIDPipe) id: string) { return this.trainSchedulingService.arriveSchedule(id); } - @Get('container/schedules') + @Get("container/schedules") @TrainSchedulingView() - @ApiOperation({ summary: 'List container train schedules' }) + @ApiOperation({ summary: "List container train schedules" }) getContainerTrainSchedules() { return this.trainSchedulingService.getContainerTrainSchedules(); } - @Get('bulk/schedules') + @Get("bulk/schedules") @TrainSchedulingView() - @ApiOperation({ summary: 'List bulk train schedules' }) + @ApiOperation({ summary: "List bulk train schedules" }) getBulkTrainSchedules() { return this.trainSchedulingService.getContainerTrainSchedules(); } - @Get('container/schedules/:id') + @Get("container/schedules/:id") @TrainSchedulingView() - @ApiOperation({ summary: 'Get container train schedule detail' }) - getContainerTrainScheduleById(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ summary: "Get container train schedule detail" }) + getContainerTrainScheduleById(@Param("id", ParseUUIDPipe) id: string) { return this.trainSchedulingService.getContainerTrainScheduleById(id); } - @Get('bulk/schedules/:id') + @Get("bulk/schedules/:id") @TrainSchedulingView() - @ApiOperation({ summary: 'Get bulk train schedule detail' }) - getBulkTrainScheduleById(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ summary: "Get bulk train schedule detail" }) + getBulkTrainScheduleById(@Param("id", ParseUUIDPipe) id: string) { return this.trainSchedulingService.getContainerTrainScheduleById(id); } - @Post('container/schedules/:id/cancel') + @Post("container/schedules/:id/cancel") @TrainSchedulingManage() - @ApiOperation({ summary: 'Cancel container train schedule' }) - cancelTrainSchedule(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ summary: "Cancel container train schedule" }) + cancelTrainSchedule(@Param("id", ParseUUIDPipe) id: string) { return this.trainSchedulingService.cancelTrainSchedule(id); } - @Post('bulk/schedules/:id/cancel') + @Post("bulk/schedules/:id/cancel") @TrainSchedulingManage() - @ApiOperation({ summary: 'Cancel bulk train schedule' }) - cancelBulkTrainSchedule(@Param('id', ParseUUIDPipe) id: string) { + @ApiOperation({ summary: "Cancel bulk train schedule" }) + cancelBulkTrainSchedule(@Param("id", ParseUUIDPipe) id: string) { return this.trainSchedulingService.cancelTrainSchedule(id); } } diff --git a/apps/edr-freight-web/portal/package.json b/apps/edr-freight-web/portal/package.json index ae79d7562..f5fddd009 100644 --- a/apps/edr-freight-web/portal/package.json +++ b/apps/edr-freight-web/portal/package.json @@ -38,6 +38,7 @@ "devDependencies": { "@edr/eslint-config": "workspace:*", "@edr/tsconfig": "workspace:*", + "@hookform/devtools": "^4.4.0", "@tailwindcss/vite": "^4.3.0", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.0", diff --git a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx index 2ae53d576..7420f90d3 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx @@ -7,6 +7,7 @@ import { AlertCircle, Check, ChevronLeft, ChevronRight } from "lucide-react"; import { useMemo, useState } from "react"; import { useForm } from "react-hook-form"; import { useNavigate } from "react-router-dom"; +import { DevTool } from "@hookform/devtools"; import { BookingFormInputValues, STEPS, @@ -22,6 +23,7 @@ import { Step2ServiceType, Step4Route, Step5CargoDetails, + StepScheduling, StepDocuments, Step8Review, } from "./new-booking-form/steps"; @@ -70,7 +72,11 @@ export default function NewBookingPage() { const destinationYard = form.watch("destinationYard"); const direction = useMemo( - () => getRouteDirection(referenceData?.yard.find((y) => y.id === originYard), referenceData?.yard.find((y) => y.id === destinationYard)), + () => + getRouteDirection( + referenceData?.yard.find((y) => y.id === originYard), + referenceData?.yard.find((y) => y.id === destinationYard), + ), [originYard, destinationYard], ); @@ -100,15 +106,11 @@ export default function NewBookingPage() { : Number(data.cargoWeight || 0); // ── Reference data lookups ────────────────────────────────────────── - 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 ?? ""; @@ -117,13 +119,6 @@ export default function NewBookingPage() { const findShippingLineId = (name: string): string | undefined => shippingLines.find((l) => l.name === name)?.id; - const findContainerCargoTypeId = (): string => { - const group = cargoTree.find( - (g) => g.code === "CONTAINER" || /container/i.test(g.name), - ); - return group?.id ?? ""; - }; - const findContainerTypeId = (name: string): string => { for (const group of containerGroups) { const ct = group.types.find((t) => t.name === name); @@ -139,21 +134,18 @@ export default function NewBookingPage() { ?.children?.find((c) => c.name === data.bulkCommoditytype) : undefined; - const cargoTypeId = - data.cargoType === "container" - ? findContainerCargoTypeId() - : (selectedChild?.id ?? ""); + const cargoTypeId = selectedChild?.id; const cargoFreeText = data.cargoType === "container" ? undefined : selectedChild?.show_free_text_box - ? data.bulkCommoditytype + ? data.cargoFreeText : undefined; // ── Build API payload ─────────────────────────────────────────────── const apiPayload: CreateBookingPayload = { - scheduledDate: new Date().toISOString().slice(0, 10), + scheduledDate: new Date().toISOString(), contractType: data.contractType.toUpperCase() as CreateBookingPayload["contractType"], serviceTypeId: findServiceTypeId(), @@ -161,13 +153,13 @@ export default function NewBookingPage() { data.equipmentReturn === "with_return" ? "WITH_RETURN" : "WITHOUT_RETURN", - originYardId: findYardId(data.originYard), - destinationYardId: findYardId(data.destinationYard), + originYardId: data.originYard, + destinationYardId: data.destinationYard, tradeDirection: direction!, - cargoTypeId: data.cargoType === "container" ? undefined : cargoTypeId, + cargoTypeId, + trainScheduleId: data.trainScheduleId, cargoTotalWeightVgm: totalWeight, isHazardous: data.isHazardous, - paymentCurrency: "USD", allowConsolidation: data.consolidationEnabled, // @ts-ignore freightType: @@ -243,67 +235,59 @@ export default function NewBookingPage() { Back to Bookings -
- {/* Step indicator */} - - + + - - {/* Step content */} - - - {createMutation.isError && ( - } - radius="md" - mb="lg" - > - - Failed to save draft - - - {createMutation.error instanceof Error - ? createMutation.error.message - : "An unexpected error occurred. Please try again."} - - - )} + {createMutation.isError && ( + } + radius="md" + mb="lg" + > + + Failed to save draft + + + {createMutation.error instanceof Error + ? createMutation.error.message + : "An unexpected error occurred. Please try again."} + + + )} - {step === 1 && } - {step === 2 && } - {step === 3 && ( - - )} - {step === 4 && ( - - )} - {step === 5 && } - {step === 6 && ( - - )} - + {step === 1 && } + {step === 2 && } + {step === 3 && ( + + )} + {step === 4 && ( + + )} + {step === 5 && ( + + )} + {step === 6 && } + {step === 7 && ( + + )} {/* Navigation footer */} @@ -359,6 +343,7 @@ export default function NewBookingPage() { + {/* */}
); } diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts index ea8611d9e..1e89b7be4 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts @@ -101,10 +101,12 @@ export const bookingFormSchema = z destinationYard: z.string().min(1, "Select a destination yard."), shippingLine: z.string(), scheduledDate: z.string().min(1, "Select a shipment date."), + trainScheduleId: z.string().min(1, "Select a shipment date."), cargoType: z.enum(["container", "bulk"], "Select a cargo type."), cargoWeight: z.string(), freightType: z.string(), // parent group bulkCommoditytype: z.string(), + cargoFreeText: z.string(), isHazardous: z.boolean(), isRefrigerated: z.boolean(), containers: z.array( @@ -229,8 +231,10 @@ export const initialBookingFormValues: DeepPartial = { destinationYard: "", shippingLine: "", scheduledDate: "", + trainScheduleId: "", cargoWeight: "", bulkCommoditytype: "", + cargoFreeText: "", isHazardous: false, isRefrigerated: false, containers: [{ type: "20ft", containerType: "", qty: "1", vgm: "" }], @@ -264,7 +268,7 @@ export const stepFields: Record>> = { "containers", "consolidationEnabled", ], - 5: ["scheduledDate"], + 5: ["scheduledDate", "trainScheduleId"], 6: ["documents"], 7: ["notes", "termsAccepted"], }; @@ -280,50 +284,32 @@ export interface WagonConfig { type: "20ft" | "40ft"; } -export interface WagonCalcResult { - totalWagons: number; - hasOddUnit: boolean; - sharedWagons: number; - wagonLayout: WagonConfig[]; - ft40Wagons: number; - ft20Wagons: number; -} - export function getRouteDirection( origin: Freight.BookingReferenceYard | null | undefined, dest: Freight.BookingReferenceYard | null | undefined, -): Freight.ScheduleTradeDirection | null { +): Freight.ScheduleTradeDirection | null { if (!origin || !dest) return null; -if(origin.country === 'ethiopia' && dest.country === 'ethiopia') { - return 'DOMESTIC'; -} - if(origin.country === 'ethiopia' && dest.country === 'djibouti') { - return 'IMPORT'; + if (origin.country === "ethiopia" && dest.country === "ethiopia") { + return "DOMESTIC"; } - if(origin.country === 'djibouti' && dest.country === 'ethiopia') { - return 'EXPORT'; + if (origin.country === "ethiopia" && dest.country === "djibouti") { + return "IMPORT"; + } + if (origin.country === "djibouti" && dest.country === "ethiopia") { + return "EXPORT"; } return null; } -export function calcWagons(containers: ContainerConfig[]): WagonCalcResult { - const Ft40Wagons = containers - .filter((c) => c.type === "40ft") - .reduce((sum, c) => sum + Number(c.qty), 0); +export function calcWagons(containers: ContainerConfig[]) { const Ft20Wagons = containers .filter((c) => c.type === "20ft") .reduce((sum, c) => sum + Number(c.qty), 0); - const wagonLayout: WagonConfig[] = []; let hasOddUnit = Ft20Wagons % 2 === 1; - let sharedWagons = Math.floor(Ft20Wagons / 2); return { - totalWagons: sharedWagons + Ft40Wagons, hasOddUnit, - sharedWagons, - ft40Wagons: Ft40Wagons, ft20Wagons: Ft20Wagons, - wagonLayout, }; } diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-documents.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-documents.tsx index cd7db7b85..f600d10d7 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-documents.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-documents.tsx @@ -5,12 +5,17 @@ import { Controller, type UseFormReturn } from "react-hook-form"; import { BOOKING_DOCS_SETTING, + BookingFormInputValues, type BookingDocuments, type BookingFormValues, } from "./schema"; import { StepHeader } from "./shared"; -type BookingForm = UseFormReturn; +type BookingForm = UseFormReturn< + BookingFormInputValues, + any, + BookingFormValues +>; function countAttached(documents: BookingDocuments): number { return BOOKING_DOCS_SETTING.fields.filter((f) => { @@ -57,7 +62,11 @@ export function StepDocuments({ form }: { form: BookingForm }) { color: attached === total ? "#0A6F4D" : "#2E5B96", }} > - {attached === total ? : `${attached}/${total}`} + {attached === total ? ( + + ) : ( + `${attached}/${total}` + )}
{attached === 0 diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-scheduling.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-scheduling.tsx new file mode 100644 index 000000000..c403835c5 --- /dev/null +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-scheduling.tsx @@ -0,0 +1,389 @@ +import { + Box, + Button, + Card, + Grid, + Group, + Stack, + Text, + Title, + useMantineTheme, + Divider, +} from "@mantine/core"; +import { UseFormReturn } from "react-hook-form"; +import { BookingFormInputValues, BookingFormValues } from "./schema"; +import { + ChevronLeft, + ChevronRight, + Info, + Calendar as CalendarIcon, +} from "lucide-react"; +import type { Freight } from "@edr/types"; +import { useMemo, useState } from "react"; +import { useQuery } from "@tanstack/react-query"; +import { api } from "@/services/api"; +import { + format, + startOfMonth, + endOfMonth, + startOfWeek, + endOfWeek, + eachDayOfInterval, + isToday, + isSameMonth, + addMonths, +} from "date-fns"; + +interface StepSchedulingProps { + form: UseFormReturn; + referenceData?: Freight.BookingReferenceData; +} + +export function StepScheduling({ form, referenceData }: StepSchedulingProps) { + const theme = useMantineTheme(); + const [currentDate, setCurrentDate] = useState(new Date()); + const selectedDate = form.watch("scheduledDate"); + const originYardId = form.watch("originYard"); + const destinationYardId = form.watch("destinationYard"); + const cargoType = form.watch("cargoType"); + + const originName = useMemo( + () => + referenceData?.yard.find((y) => y.id === originYardId)?.name ?? + "Not selected", + [referenceData, originYardId], + ); + + const destinationName = useMemo( + () => + referenceData?.yard.find((y) => y.id === destinationYardId)?.name ?? + "Not selected", + [referenceData, destinationYardId], + ); + + const { data: bookableSchedules } = useQuery( + api.bookings.getBookableSchedules.queryOptions({ + input: { originYardId, destinationYardId }, + enabled: !!originYardId && !!destinationYardId, + }), + ); + + const scheduleMap = useMemo(() => { + const map = new Map(); + if (bookableSchedules) { + for (const s of bookableSchedules) { + if (!map.has(s.scheduleDate)) { + map.set(s.scheduleDate, s); + } + } + } + return map; + }, [bookableSchedules]); + + const days = useMemo(() => { + const monthStart = startOfMonth(currentDate); + const monthEnd = endOfMonth(currentDate); + const calStart = startOfWeek(monthStart, { weekStartsOn: 1 }); + const calEnd = endOfWeek(monthEnd, { weekStartsOn: 1 }); + + return eachDayOfInterval({ start: calStart, end: calEnd }).map((date) => { + const dateString = format(date, "yyyy-MM-dd"); + const schedule = scheduleMap.get(dateString); + + return { + day: date.getDate(), + dateString, + isToday: isToday(date), + isSelected: selectedDate === dateString, + isCurrentMonth: isSameMonth(date, currentDate), + isFull: schedule ? schedule.remainingWagons <= 0 : false, + hasSchedule: !!schedule, + remainingWagons: schedule?.remainingWagons ?? 0, + scheduleId: schedule?.id ?? "", + }; + }); + }, [currentDate, scheduleMap, selectedDate]); + + const legendItems = [ + { label: "Available", color: theme.colors.gray[1] }, + { label: "Full", color: theme.colors["edr-red-soft"][0] }, + { label: "No Service", color: "transparent" }, + { label: "Selected", color: theme.colors["edr-green"][5] }, + ]; + + return ( + + + + + + + Shipment Date + + + Pick a shipment date for your booking from the available + schedule. + + + + + + + + {format(currentDate, "MMMM yyyy")} + + + + + + + + + + {["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"].map((d) => ( + + {d} + + ))} + {days.map((d, i) => { + const canSelect = + d.isCurrentMonth && d.hasSchedule && !d.isFull; + return ( + + ); + })} + + + + {legendItems.map((item) => ( + + + + {item.label} + + + ))} + + + + + + + + + + Booking Summary + + + + + + + + + + + + + Shipment Date + + + {selectedDate || "Not selected"} + + + + + + + + + + + + + Final confirmation of your selected date will be provided + after review of your booking details. + + + + + + + + + ); +} + +function SummaryRow({ label, value }: { label: string; value: string }) { + return ( + + + {label} + + + {value} + + + ); +} diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step5-cargo-details.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step5-cargo-details.tsx index 7a7a0d888..574a51a01 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step5-cargo-details.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step5-cargo-details.tsx @@ -1,7 +1,14 @@ import { useMemo } from "react"; import { Controller, useFieldArray, type UseFormReturn } from "react-hook-form"; import { MapPin, Package, Plus, Trash2, Weight } from "lucide-react"; -import { ActionIcon, Button, Skeleton, Stack, Text, TextInput } from "@mantine/core"; +import { + ActionIcon, + Button, + Skeleton, + Stack, + Text, + TextInput, +} from "@mantine/core"; import type { Freight } from "@edr/types"; import { BookingFormInputValues, @@ -17,7 +24,11 @@ import { StepLabel, } from "./shared"; -type BookingForm = UseFormReturn; +type BookingForm = UseFormReturn< + BookingFormInputValues, + any, + BookingFormValues +>; export function Step5CargoDetails({ form, @@ -32,6 +43,7 @@ export function Step5CargoDetails({ }) { const cargoType = form.watch("cargoType"); const freightType = form.watch("freightType"); + const bulkCommoditytype = form.watch("bulkCommoditytype"); const containers = form.watch("containers"); const { fields, append, remove } = useFieldArray({ @@ -39,16 +51,28 @@ export function Step5CargoDetails({ name: "containers", }); - const containerTypeOptions = useMemo(() => { - if (!referenceData?.containers) return []; - return referenceData.containers.flatMap((group) => - group.types.map((t) => t.name), + const containerTypeOptionsBySize = useMemo(() => { + if (!referenceData?.containers) return new Map(); + return new Map( + referenceData.containers.map((g) => [g.size, g.types.map((t) => t.name)]), ); }, [referenceData]); + const selectedCommodity = useMemo(() => { + if (!referenceData?.cargo_type || !freightType || !bulkCommoditytype) return null; + const group = referenceData.cargo_type.find( + (g) => g.code.toLowerCase() === freightType, + ); + return group?.children?.find( + (c) => c.name === bulkCommoditytype, + ) ?? null; + }, [referenceData, freightType, bulkCommoditytype]); + const freightTypeGroups = useMemo(() => { if (!referenceData?.cargo_type) return []; - return referenceData.cargo_type.filter((g) => g.code !== "CONTAINER"); + return referenceData.cargo_type.filter( + (g) => g.code !== "CONTAINER" && !/container/i.test(g.name), + ); }, [referenceData]); const commodityOptions = useMemo(() => { @@ -219,6 +243,22 @@ export function Step5CargoDetails({ )} /> )} + + {selectedCommodity?.show_free_text_box && ( + ( + + )} + /> + )} )} @@ -253,7 +293,13 @@ export function Step5CargoDetails({ className="flex flex-col gap-3 rounded-xl border border-gray-200 bg-gray-50/50 p-4" >
- + Container {index + 1} {fields.length > 1 && ( @@ -300,7 +346,9 @@ export function Step5CargoDetails({

{ct.label}

-

{ct.limit}

+

+ {ct.limit} +

))} @@ -324,7 +372,10 @@ export function Step5CargoDetails({ type="button" onClick={() => qtyField.onChange( - Math.max(1, Number(qtyField.value ?? 1) - 1).toString(), + Math.max( + 1, + Number(qtyField.value ?? 1) - 1, + ).toString(), ) } className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-gray-200 bg-white text-sm font-medium transition hover:bg-gray-50" @@ -333,7 +384,9 @@ export function Step5CargoDetails({ qtyField.onChange(e.target.value)} + onChange={(e) => + qtyField.onChange(e.target.value) + } onBlur={qtyField.onBlur} type="number" min={1} @@ -388,7 +441,11 @@ export function Step5CargoDetails({ error={fieldState.error} label="Container Type *" placeholder="Select type..." - data={containerTypeOptions} + data={ + containerTypeOptionsBySize.get( + containers[index]?.type ?? "20ft", + ) ?? [] + } /> )} /> diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step6-wagon-allocation.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step6-wagon-allocation.tsx deleted file mode 100644 index c58b34241..000000000 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step6-wagon-allocation.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { type UseFormReturn } from "react-hook-form"; -import { type BookingFormValues, type WagonCalcResult } from "./schema"; -import { AlertBox, StepHeader, StepLabel } from "./shared"; - -type BookingForm = UseFormReturn; - -export function Step6WagonAllocation({ - form, - wagons, -}: { - form: BookingForm; - wagons: WagonCalcResult | null; -}) { - const containers = form.watch("containers") ?? []; - const totalContainers = containers.reduce( - (sum, c) => sum + Number(c.qty || 0), - 0, - ); - const containerSummary = containers - .filter((c) => +c.qty > 0) - .map((c) => `${c.qty} × ${c.type}`) - .join(", "); - return ( -
- - - {!wagons ? ( - - Complete the container configuration in the previous step to see wagon - allocation. - - ) : ( - <> -
-
-

- {wagons.totalWagons} -

-

- Wagons Required -

-
-
-

{totalContainers}

-

- {containerSummary || "Containers"} -

-
-
-

{wagons.sharedWagons}

-

Shared Slots

-
-
- -
- Wagon Layout -
- {new Array(wagons.ft40Wagons).fill(0).map((_, index) => ( -
- 1 × 40ft -
- ))} - {new Array(wagons.sharedWagons).fill(0).map((_, index) => ( -
- 2 × 20ft -
- ))} - {wagons.hasOddUnit && ( -
- 1 × 20ft -
- )} -
-
- - {wagons.hasOddUnit && ( - <> - -
-
-

Unpaired 20ft Container

-

- One 20ft container occupies only half a wagon. The wagon - will depart once a co-loader is found to fill the - remaining slot, which may delay departure{" "} - beyond the standard lead time. -

-
-
-
- - )} - - )} -
- ); -} diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/steps.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/steps.tsx index 9f1445f91..2532da237 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/steps.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/steps.tsx @@ -2,5 +2,6 @@ export { Step1ContractType } from "./step1-contract-type"; export { Step2ServiceType } from "./step2-service-type"; export { Step4Route } from "./step4-route"; export { Step5CargoDetails } from "./step5-cargo-details"; +export { StepScheduling } from "./step-scheduling"; export { StepDocuments } from "./step-documents"; export { Step8Review } from "./step8-review"; diff --git a/packages/types/src/freight/index.ts b/packages/types/src/freight/index.ts index 2ba2c9535..833a5d437 100644 --- a/packages/types/src/freight/index.ts +++ b/packages/types/src/freight/index.ts @@ -463,9 +463,9 @@ export interface CreateBookingContainerDto { export interface CreateBookingDto { reference?: string; - customerId?: string; companyId?: string; trainId?: string; + trainScheduleId?: string; scheduledDate: string; contractType: "NEW" | "RENEWAL"; previousContractId?: string; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f918ecee4..c336eb8bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -206,7 +206,7 @@ importers: version: 5.101.0(react@19.2.6) '@tria-plc/iamui-common': specifier: 1.1.2 - version: 1.1.2(9eda5000a9f7ac3b614e21a2a3a3f1e2) + version: 1.1.2(631ddfe3435b77e5a0893e986e0c71da) axios: specifier: ^1.7.7 version: 1.17.0 @@ -365,6 +365,9 @@ importers: '@edr/tsconfig': specifier: workspace:* version: link:../../../packages/config/tsconfig + '@hookform/devtools': + specifier: ^4.4.0 + version: 4.4.0(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@tailwindcss/vite': specifier: ^4.3.0 version: 4.3.0(vite@5.4.21(@types/node@24.13.1)(lightningcss@1.32.0)(terser@5.48.0)) @@ -2090,6 +2093,12 @@ packages: peerDependencies: hono: ^4 + '@hookform/devtools@4.4.0': + resolution: {integrity: sha512-Mtlic+uigoYBPXlfvPBfiYYUZuyMrD3pTjDpVIhL6eCZTvQkHsKBSKeZCvXWUZr8fqrkzDg27N+ZuazLKq6Vmg==} + peerDependencies: + react: ^16.8.0 || ^17 || ^18 || ^19 + react-dom: ^16.8.0 || ^17 || ^18 || ^19 + '@hookform/resolvers@3.10.0': resolution: {integrity: sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==} peerDependencies: @@ -9613,6 +9622,11 @@ packages: resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==} engines: {node: '>=18.0.0'} + little-state-machine@4.8.1: + resolution: {integrity: sha512-liPHqaWMQ7rzZryQUDnbZ1Gclnnai3dIyaJ0nAgwZRXMzqbYrydrlCI0NDojRUbE5VYh5vu6hygEUZiH77nQkQ==} + peerDependencies: + react: ^16.8.0 || ^17 || ^18 || ^19 + load-esm@1.0.3: resolution: {integrity: sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==} engines: {node: '>=13.2.0'} @@ -11382,6 +11396,11 @@ packages: '@types/react': optional: true + react-simple-animate@3.5.3: + resolution: {integrity: sha512-Ob+SmB5J1tXDEZyOe2Hf950K4M8VaWBBmQ3cS2BUnTORqHjhK0iKG8fB+bo47ZL15t8d3g/Y0roiqH05UBjG7A==} + peerDependencies: + react-dom: ^16.8.0 || ^17 || ^18 || ^19 + react-smooth@4.0.4: resolution: {integrity: sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==} peerDependencies: @@ -13008,6 +13027,12 @@ packages: '@types/react': optional: true + use-deep-compare-effect@1.8.1: + resolution: {integrity: sha512-kbeNVZ9Zkc0RFGpfMN3MNfaKNvcLNyxOAAd9O4CBZ+kCBXXscn9s/4I+8ytUER4RDpEYs5+O6Rs4PqiZ+rHr5Q==} + engines: {node: '>=10', npm: '>=6'} + peerDependencies: + react: '>=16.13' + use-isomorphic-layout-effect@1.2.1: resolution: {integrity: sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==} peerDependencies: @@ -14693,6 +14718,22 @@ snapshots: dependencies: hono: 4.12.23 + '@hookform/devtools@4.4.0(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + dependencies: + '@emotion/react': 11.14.0(@types/react@18.3.31)(react@19.2.6) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) + '@types/lodash': 4.17.24 + little-state-machine: 4.8.1(react@19.2.6) + lodash: 4.18.1 + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + react-simple-animate: 3.5.3(react-dom@19.2.6(react@19.2.6)) + use-deep-compare-effect: 1.8.1(react@19.2.6) + uuid: 8.3.2 + transitivePeerDependencies: + - '@types/react' + - supports-color + '@hookform/resolvers@3.10.0(react-hook-form@7.77.0(react@18.3.1))': dependencies: react-hook-form: 7.77.0(react@18.3.1) @@ -15569,29 +15610,6 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@mui/x-date-pickers@6.20.2(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(date-fns@4.4.0)(dayjs@1.11.21)(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': - dependencies: - '@babel/runtime': 7.29.7 - '@mui/base': 5.0.0-beta.70(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@mui/material': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@mui/system': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) - '@mui/utils': 5.17.1(@types/react@18.3.31)(react@19.2.6) - '@types/react-transition-group': 4.4.12(@types/react@18.3.31) - clsx: 2.1.1 - prop-types: 15.8.1 - react: 19.2.6 - react-dom: 19.2.6(react@19.2.6) - react-transition-group: 4.4.5(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - optionalDependencies: - '@emotion/react': 11.14.0(@types/react@18.3.31)(react@19.2.6) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) - date-fns: 4.4.0 - dayjs: 1.11.21 - luxon: 3.7.2 - moment: 2.30.1 - transitivePeerDependencies: - - '@types/react' - '@napi-rs/canvas-android-arm64@0.1.100': optional: true @@ -18783,146 +18801,6 @@ snapshots: - webpack-command - worker-loader - '@tria-plc/iamui-common@1.1.2(9eda5000a9f7ac3b614e21a2a3a3f1e2)': - dependencies: - '@chakra-ui/react': 3.35.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@emotion/react': 11.14.0(@types/react@18.3.31)(react@19.2.6) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) - '@hookform/resolvers': 5.4.0(react-hook-form@7.77.0(react@19.2.6)) - '@lottiefiles/react-lottie-player': 3.6.0(react@19.2.6) - '@mantine/core': 8.3.18(@mantine/hooks@8.3.18(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@mantine/dates': 8.3.18(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@8.3.18(react@19.2.6))(dayjs@1.11.21)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@mantine/hooks': 8.3.18(react@19.2.6) - '@onlyoffice/document-editor-react': 2.2.0(@onlyoffice/doceditor-types@9.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-accordion': 1.2.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-alert-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-avatar': 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-checkbox': 1.3.4(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-collapsible': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-context-menu': 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-dropdown-menu': 2.1.17(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-hover-card': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-label': 2.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-navigation-menu': 1.2.15(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-popover': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-progress': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-radio-group': 1.4.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-scroll-area': 1.2.11(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-select': 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-separator': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-slider': 1.4.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-slot': 1.2.5(@types/react@18.3.31)(react@19.2.6) - '@radix-ui/react-switch': 1.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-tabs': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-toast': 1.2.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-toggle-group': 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-tooltip': 1.2.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@react-pdf-viewer/default-layout': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@react-pdf/renderer': 4.5.1(react@19.2.6) - '@reduxjs/toolkit': 2.12.0(react-redux@9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1))(react@19.2.6) - '@tabler/icons-react': 3.44.0(react@19.2.6) - '@tailwindcss/vite': 4.3.0(vite@5.4.21(@types/node@24.13.1)(lightningcss@1.32.0)(terser@5.48.0)) - '@tanstack/react-query': 5.101.0(react@19.2.6) - '@tanstack/react-query-devtools': 5.101.0(@tanstack/react-query@5.101.0(react@19.2.6))(react@19.2.6) - '@tanstack/react-table': 8.21.3(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@tinymce/tinymce-react': 6.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(tinymce@7.9.3) - '@tiptap/extension-color': 3.26.0(@tiptap/extension-text-style@3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0))) - '@tiptap/extension-highlight': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0)) - '@tiptap/extension-image': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0)) - '@tiptap/extension-link': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0))(@tiptap/pm@3.26.0) - '@tiptap/extension-text-align': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0)) - '@tiptap/extension-text-style': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0)) - '@tiptap/extension-underline': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0)) - '@tiptap/react': 3.26.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.26.0(@tiptap/pm@3.26.0))(@tiptap/pm@3.26.0)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@tiptap/starter-kit': 3.26.0 - '@types/node': 24.13.1 - '@types/tinymce': 4.6.9 - axios: 1.17.0 - class-variance-authority: 0.7.1 - clsx: 2.1.1 - cmdk: 1.1.1(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - date-fns: 4.4.0 - dayjs: 1.11.21 - ethiopian-calendar-date-converter: 2.1.6 - ethiopian-calendar-new: 1.1.0 - file-type: 18.7.0 - force: 0.0.3 - framer-motion: 12.40.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - html2canvas: 1.4.1 - i18next: 25.10.10(typescript@5.9.3) - i18next-browser-languagedetector: 8.2.1 - jquery: 3.7.1 - js-cookie: 3.0.8 - jspdf: 3.0.4 - loadash: 1.0.0 - lodash: 4.18.1 - lucide-react: 0.513.0(react@19.2.6) - mui-ethiopian-datepicker: 0.3.2(7d86988bc4fd0020aebaf3d4b373b1a0) - next-themes: 0.4.6(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - path: 0.12.7 - qs: 6.15.2 - react: 19.2.6 - react-cookie: 8.1.2(@types/react@18.3.31)(react@19.2.6) - react-datepicker: 8.10.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - react-day-picker: 9.14.0(react@19.2.6) - react-dom: 19.2.6(react@19.2.6) - react-dropzone: 14.4.1(react@19.2.6) - react-hook-form: 7.77.0(react@19.2.6) - react-i18next: 15.7.4(i18next@25.10.10(typescript@5.9.3))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3) - react-icons: 5.6.0(react@19.2.6) - react-image-crop: 11.0.10(react@19.2.6) - react-intersection-observer: 9.16.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - react-is: 19.2.7 - react-joyride: 2.9.3(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - react-pdf: 10.4.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - react-pdf-html: 2.1.5(@react-pdf/renderer@4.5.1(react@19.2.6))(react@19.2.6) - react-pdf-viewer: 0.1.0 - react-redux: 9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1) - react-resizable-panels: 3.0.6(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - react-router-dom: 7.17.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - react-signature-canvas: 1.1.0-alpha.2(@types/prop-types@15.7.15)(@types/react@18.3.31)(prop-types@15.8.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - recharts: 3.8.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6)(redux@5.0.1) - socket.io-client: 4.8.3 - sonner: 2.0.7(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - tailwind-merge: 3.6.0 - tailwind-scrollbar-hide: 4.0.0(tailwindcss@4.3.0) - tailwindcss: 4.3.0 - tailwindcss-animate: 1.0.7(tailwindcss@4.3.0) - tesseract.js: 7.0.0 - tinymce: 7.9.3 - url: 0.11.4 - vaul: 1.1.2(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - xlsx: 0.18.5 - zod: 3.25.76 - transitivePeerDependencies: - - '@emotion/is-prop-valid' - - '@floating-ui/dom' - - '@mui/icons-material' - - '@mui/material' - - '@mui/x-date-pickers' - - '@onlyoffice/doceditor-types' - - '@tiptap/core' - - '@tiptap/pm' - - '@types/prop-types' - - '@types/react' - - '@types/react-dom' - - bufferutil - - debug - - encoding - - pdfjs-dist - - prop-types - - react-native - - redux - - supports-color - - typescript - - utf-8-validate - - vite - - webpack-cli - - webpack-command - - worker-loader - '@ts-morph/common@0.27.0': dependencies: fast-glob: 3.3.3 @@ -25223,6 +25101,10 @@ snapshots: rfdc: 1.4.1 wrap-ansi: 9.0.2 + little-state-machine@4.8.1(react@19.2.6): + dependencies: + react: 19.2.6 + load-esm@1.0.3: {} load-json-file@1.1.0: @@ -27387,6 +27269,10 @@ snapshots: '@types/prop-types': 15.7.15 '@types/react': 18.3.31 + react-simple-animate@3.5.3(react-dom@19.2.6(react@19.2.6)): + dependencies: + react-dom: 19.2.6(react@19.2.6) + react-smooth@4.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: fast-equals: 5.4.0 @@ -29433,11 +29319,11 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - use-isomorphic-layout-effect@1.2.1(@types/react@18.3.31)(react@18.3.1): + use-deep-compare-effect@1.8.1(react@19.2.6): dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.31 + '@babel/runtime': 7.29.7 + dequal: 2.0.3 + react: 19.2.6 use-isomorphic-layout-effect@1.2.1(@types/react@18.3.31)(react@19.2.6): dependencies: From 44aef8c1b305d7efb4ef6661df9e255c00f7f316 Mon Sep 17 00:00:00 2001 From: ghost2023 Date: Sat, 13 Jun 2026 12:21:37 +0300 Subject: [PATCH 06/12] feat: add more fields to the reference service array --- .../booking-reference-data.service.ts | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/apps/edr-freight-api/src/modules/bookings/booking-reference-data.service.ts b/apps/edr-freight-api/src/modules/bookings/booking-reference-data.service.ts index dc4f292b7..8a2d52172 100644 --- a/apps/edr-freight-api/src/modules/bookings/booking-reference-data.service.ts +++ b/apps/edr-freight-api/src/modules/bookings/booking-reference-data.service.ts @@ -1,28 +1,28 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { In, Not } from 'typeorm'; +import { Inject, Injectable } from "@nestjs/common"; +import { In, Not } from "typeorm"; -import { CargoType } from '../rule-engine/entities/cargo-type.entity'; -import { ContainerType } from '../rule-engine/entities/container-type.entity'; +import { CargoType } from "../rule-engine/entities/cargo-type.entity"; +import { ContainerType } from "../rule-engine/entities/container-type.entity"; import { CARGO_TYPES_REPOSITORY, ICargoTypesRepository, -} from '../rule-engine/interfaces/cargo-types.repository.interface'; +} from "../rule-engine/interfaces/cargo-types.repository.interface"; import { CONTAINER_TYPES_REPOSITORY, IContainerTypesRepository, -} from '../rule-engine/interfaces/container-types.repository.interface'; +} from "../rule-engine/interfaces/container-types.repository.interface"; import { IServiceTypesRepository, SERVICE_TYPES_REPOSITORY, -} from '../rule-engine/interfaces/service-types.repository.interface'; +} from "../rule-engine/interfaces/service-types.repository.interface"; import { IShippingLinesRepository, SHIPPING_LINES_REPOSITORY, -} from '../rule-engine/interfaces/shipping-lines.repository.interface'; +} from "../rule-engine/interfaces/shipping-lines.repository.interface"; import { IYardsRepository, YARDS_REPOSITORY, -} from '../rule-engine/interfaces/yards.repository.interface'; +} from "../rule-engine/interfaces/yards.repository.interface"; import { BookingReferenceCargoTypeChildDto, BookingReferenceCargoTypeGroupDto, @@ -32,9 +32,9 @@ import { BookingReferenceServiceDto, BookingReferenceShippingLineDto, BookingReferenceYardDto, -} from './dto/booking-reference-data.dto'; +} from "./dto/booking-reference-data.dto"; -const LEGACY_YARD_CODES = ['LEGACY_ORIGIN', 'LEGACY_DEST'] as const; +const LEGACY_YARD_CODES = ["LEGACY_ORIGIN", "LEGACY_DEST"] as const; export function buildCargoTypeTree( rows: CargoType[], @@ -42,13 +42,16 @@ export function buildCargoTypeTree( const active = rows.filter((r) => r.isActive); const parents = active .filter((r) => !r.parentGroupId) - .sort((a, b) => a.displayOrder - b.displayOrder || a.code.localeCompare(b.code)); + .sort( + (a, b) => a.displayOrder - b.displayOrder || a.code.localeCompare(b.code), + ); return parents.map((parent) => { const children = active .filter((r) => r.parentGroupId === parent.id) .sort( - (a, b) => a.displayOrder - b.displayOrder || a.code.localeCompare(b.code), + (a, b) => + a.displayOrder - b.displayOrder || a.code.localeCompare(b.code), ) .map( (child): BookingReferenceCargoTypeChildDto => ({ @@ -79,14 +82,14 @@ export function groupContainersBySize( for (const ct of active) { const sizeKey = - ct.sizeFt != null && ct.sizeFt > 0 ? `${ct.sizeFt}ft` : 'other'; + ct.sizeFt != null && ct.sizeFt > 0 ? `${ct.sizeFt}ft` : "other"; const list = bySize.get(sizeKey) ?? []; list.push(ct); bySize.set(sizeKey, list); } const sortSizeKey = (key: string): number => { - if (key === 'other') return Number.MAX_SAFE_INTEGER; + if (key === "other") return Number.MAX_SAFE_INTEGER; const n = parseInt(key, 10); return Number.isNaN(n) ? Number.MAX_SAFE_INTEGER - 1 : n; }; @@ -126,7 +129,7 @@ export class BookingReferenceDataService { private readonly shippingLinesRepository: IShippingLinesRepository, @Inject(CARGO_TYPES_REPOSITORY) private readonly cargoTypesRepository: ICargoTypesRepository, - ) {} + ) { } async getReferenceData(): Promise { const [yards, containerTypes, serviceTypes, shippingLines, cargoTypes] = @@ -136,23 +139,23 @@ export class BookingReferenceDataService { isActive: true, code: Not(In([...LEGACY_YARD_CODES])), }, - order: { displayOrder: 'ASC', code: 'ASC' }, + order: { displayOrder: "ASC", code: "ASC" }, }), this.containerTypesRepository.findAll({ where: { isActive: true }, - order: { displayOrder: 'ASC', code: 'ASC' }, + order: { displayOrder: "ASC", code: "ASC" }, }), this.serviceTypesRepository.findAll({ where: { isActive: true }, - order: { displayOrder: 'ASC', code: 'ASC' }, + order: { displayOrder: "ASC", code: "ASC" }, }), this.shippingLinesRepository.findAll({ where: { isActive: true }, - order: { label: 'ASC', code: 'ASC' }, + order: { label: "ASC", code: "ASC" }, }), this.cargoTypesRepository.findAll({ where: { isActive: true }, - order: { displayOrder: 'ASC', code: 'ASC' }, + order: { displayOrder: "ASC", code: "ASC" }, }), ]); @@ -168,9 +171,8 @@ export class BookingReferenceDataService { containers: groupContainersBySize(containerTypes), service: serviceTypes.map( (s): BookingReferenceServiceDto => ({ - id: s.id, name: s.serviceName, - code: s.code, + ...s, }), ), shipping_line: shippingLines.map( From 3e2e07bb5f7f730f1ab82f7571eef565b78f06d4 Mon Sep 17 00:00:00 2001 From: ghost2023 Date: Sat, 13 Jun 2026 12:26:06 +0300 Subject: [PATCH 07/12] feat(bookings): Implement data-driven service type selection and configuration --- .../src/pages/bookings/NewBookingPage.tsx | 42 +- .../pages/bookings/new-booking-form/schema.ts | 4 +- .../new-booking-form/step2-service-type.tsx | 378 +++++++++--------- packages/types/src/freight/index.ts | 83 ++-- 4 files changed, 264 insertions(+), 243 deletions(-) diff --git a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx index 7420f90d3..34f87db00 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx @@ -106,16 +106,10 @@ export default function NewBookingPage() { : Number(data.cargoWeight || 0); // ── Reference data lookups ────────────────────────────────────────── - const services = referenceData?.service ?? []; const shippingLines = referenceData?.shipping_line ?? []; const cargoTree = referenceData?.cargo_type ?? []; const containerGroups = referenceData?.containers ?? []; - 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; @@ -127,32 +121,32 @@ export default function NewBookingPage() { return ""; }; - const selectedChild = - data.cargoType !== "container" && data.bulkCommoditytype - ? cargoTree - .find((g) => g.code.toLowerCase() === data.freightType) - ?.children?.find((c) => c.name === data.bulkCommoditytype) - : undefined; + const bulkChild = cargoTree + .flatMap((g) => g.children ?? []) + .find((c) => c.id === data.bulkCommoditytype); - const cargoTypeId = selectedChild?.id; + const cargoTypeId = + data.cargoType === "bulk" ? data.bulkCommoditytype : undefined; - const cargoFreeText = - data.cargoType === "container" - ? undefined - : selectedChild?.show_free_text_box - ? data.cargoFreeText - : undefined; + const cargoFreeText = bulkChild?.show_free_text_box + ? data.cargoFreeText + : undefined; + + const serviceType = referenceData?.service.find( + (s) => s.id === data.serviceTypeId, + )!; // ── Build API payload ─────────────────────────────────────────────── const apiPayload: CreateBookingPayload = { scheduledDate: new Date().toISOString(), contractType: data.contractType.toUpperCase() as CreateBookingPayload["contractType"], - serviceTypeId: findServiceTypeId(), + serviceTypeId: data.serviceTypeId, equipmentReturn: data.equipmentReturn === "with_return" ? "WITH_RETURN" : "WITHOUT_RETURN", + paymentCurrency: "USD", originYardId: data.originYard, destinationYardId: data.destinationYard, tradeDirection: direction!, @@ -180,10 +174,10 @@ export default function NewBookingPage() { ...(data.contractType === "renewal" && data.previousContractRef ? { pnrCode: data.previousContractRef } : {}), - ...(data.serviceType === "rail_forwarding" && data.firstMile.enabled + ...(serviceType.includesFirstMile && data.firstMile.enabled ? { firstMilePickupAddress: data.firstMile.pickUpAddress } : {}), - ...(data.serviceType === "rail_forwarding" && data.lastMile.enabled + ...(serviceType.includesLastMile && data.lastMile.enabled ? { lastMileDeliveryAddress: data.lastMile.deliveryAddress } : {}), ...(data.shippingLine @@ -265,7 +259,9 @@ export default function NewBookingPage() { )} {step === 1 && } - {step === 2 && } + {step === 2 && ( + + )} {step === 3 && ( = { export const stepFields: Record>> = { 1: ["contractType", "previousContractRef"], 2: [ - "serviceType", + "serviceTypeId", "firstMile", "lastMile", "equipmentReturn", diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx index 9c72a5356..5597d2fa0 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx @@ -1,18 +1,52 @@ import { useEffect, useRef } from "react"; import { Controller, type UseFormReturn } from "react-hook-form"; -import { FileText, Package, Train, Truck } from "lucide-react"; -import { Badge, Switch, TextInput } from "@mantine/core"; +import { FileText, Train, Truck } from "lucide-react"; +import { Switch, TextInput } from "@mantine/core"; import { BookingFormInputValues, type BookingFormValues } from "./schema"; import { OptionCard, OptionFieldError, StepHeader } from "./shared"; -type BookingForm = UseFormReturn; +import type { Freight } from "@edr/types"; -export function Step2ServiceType({ form }: { form: BookingForm }) { - const serviceType = form.watch("serviceType"); +type BookingForm = UseFormReturn< + BookingFormInputValues, + any, + BookingFormValues +>; + +export function Step2ServiceType({ + form, + referenceData, +}: { + form: BookingForm; + + referenceData?: Freight.BookingReferenceData; +}) { + const serviceTypeId = form.watch("serviceTypeId"); + const serviceType = referenceData?.service.find( + (s) => s.id === serviceTypeId, + ); + + const { includesCustoms, includesFirstMile, includesLastMile } = + serviceType ?? {}; const firstMileEnabled = form.watch("firstMile.enabled"); const lastMileEnabled = form.watch("lastMile.enabled"); const prevServiceType = useRef(serviceType); + useEffect(() => { + form.setValue( + "firstMile", + { enabled: false, pickUpAddress: "" }, + { shouldValidate: true }, + ); + }, [includesFirstMile]); + + useEffect(() => { + form.setValue( + "lastMile", + { enabled: false, deliveryAddress: "" }, + { shouldValidate: true }, + ); + }, [includesLastMile]); useEffect(() => { const prev = prevServiceType.current; @@ -20,35 +54,12 @@ export function Step2ServiceType({ form }: { form: BookingForm }) { if (!prev || prev === serviceType) return; - if (serviceType === "rail") { - form.setValue( - "firstMile", - { enabled: false, pickUpAddress: "" }, - { shouldDirty: true, shouldValidate: true }, - ); - form.setValue( - "lastMile", - { enabled: false, deliveryAddress: "" }, - { shouldDirty: true, shouldValidate: true }, - ); - form.setValue("equipmentReturn", "with_return", { shouldDirty: true }); + if (!includesCustoms) form.setValue("customsClearingEnabled", false, { shouldDirty: true }); - } else if (serviceType === "rail_forwarding") { - form.setValue( - "firstMile", - { enabled: false, pickUpAddress: "" }, - { shouldDirty: false, shouldValidate: false }, - ); - form.setValue( - "lastMile", - { enabled: false, deliveryAddress: "" }, - { shouldDirty: false, shouldValidate: false }, - ); - } - }, [serviceType, form]); - - const showServiceSections = serviceType === "rail_forwarding"; + }, [serviceTypeId, form]); + const showServiceSections = + includesCustoms || includesFirstMile || includesLastMile; return (
(
- field.onChange("rail")} - > -
- -
-

Rail Transport Only

-

- Rail transport along the EDR corridor, with optional - first/last mile trucking. -

- - Option A - -
- - field.onChange("rail_forwarding")} - > -
- -
-

Logistics

-

- Rail transport plus documentation, customs liaison, and a - dedicated coordinator. -

- - Option B - -
+ {referenceData?.service + .filter((s) => s.canBeBookedAlone) + .map((s) => { + return ( + field.onChange(s.id)} + > +
+ +
+

{s.serviceName}

+

+ {s.description} +

+
+ ); + })}
@@ -104,112 +100,120 @@ export function Step2ServiceType({ form }: { form: BookingForm }) { {showServiceSections && (
{/* First Mile */} -
- ( -
-
- -
-

First Mile — Pick-up

-

- Truck pick-up from your premises (Door to Port) to the - origin rail yard. -

-
-
- { - const value = e.currentTarget.checked; - field.onChange(value); - if (!value) { - form.setValue("firstMile.pickUpAddress", "", { - shouldDirty: true, - shouldValidate: true, - }); - } - }} - color="edr-green" - /> -
- )} - /> - {firstMileEnabled && ( + {includesFirstMile && ( +
( - + render={({ field }) => ( +
+
+ +
+

+ First Mile — Pick-up +

+

+ Truck pick-up from your premises (Door to Port) to the + origin rail yard. +

+
+
+ { + const value = e.currentTarget.checked; + field.onChange(value); + if (!value) { + form.setValue("firstMile.pickUpAddress", "", { + shouldDirty: true, + shouldValidate: true, + }); + } + }} + color="edr-green" + /> +
)} /> - )} -
+ {firstMileEnabled && ( + ( + + )} + /> + )} +
+ )} {/* Last Mile */} -
- ( -
-
- -
-

Last Mile — Delivery

-

- Truck delivery from the destination rail yard to the - final address (Port to Door). -

-
-
- { - const value = e.currentTarget.checked; - field.onChange(value); - if (!value) { - form.setValue("lastMile.deliveryAddress", "", { - shouldDirty: true, - shouldValidate: true, - }); - form.setValue("equipmentReturn", "with_return", { - shouldDirty: true, - }); - } - }} - color="edr-green" - /> -
- )} - /> - {lastMileEnabled && ( + {includesLastMile && ( +
( - + render={({ field }) => ( +
+
+ +
+

+ Last Mile — Delivery +

+

+ Truck delivery from the destination rail yard to the + final address (Port to Door). +

+
+
+ { + const value = e.currentTarget.checked; + field.onChange(value); + if (!value) { + form.setValue("lastMile.deliveryAddress", "", { + shouldDirty: true, + shouldValidate: true, + }); + form.setValue("equipmentReturn", "with_return", { + shouldDirty: true, + }); + } + }} + color="edr-green" + /> +
)} /> - )} -
+ {lastMileEnabled && ( + ( + + )} + /> + )} +
+ )} {/* Equipment Return */} - {lastMileEnabled && ( + {includesLastMile && lastMileEnabled && (
{ field.onChange( - e.currentTarget.checked ? "with_return" : "without_return", + e.currentTarget.checked + ? "with_return" + : "without_return", ); }} color="edr-green" @@ -240,31 +246,35 @@ export function Step2ServiceType({ form }: { form: BookingForm }) { )} {/* Customs Clearing */} -
- ( -
-
- -
-

Customs Clearing Service

-

- EDR handles customs documentation and clearance on your - behalf. -

+ {includesCustoms && ( +
+ ( +
+
+ +
+

+ Customs Clearing Service +

+

+ EDR handles customs documentation and clearance on + your behalf. +

+
+ field.onChange(e.currentTarget.checked)} + color="edr-green" + />
- field.onChange(e.currentTarget.checked)} - color="edr-green" - /> -
- )} - /> -
+ )} + /> +
+ )}
)}
diff --git a/packages/types/src/freight/index.ts b/packages/types/src/freight/index.ts index 833a5d437..40d40e719 100644 --- a/packages/types/src/freight/index.ts +++ b/packages/types/src/freight/index.ts @@ -5,16 +5,16 @@ export * from "./dropdown_settings"; export * from "./overview"; export enum TradeDirection { - IMPORT = 'IMPORT', - EXPORT = 'EXPORT', - BOTH = 'BOTH', + IMPORT = "IMPORT", + EXPORT = "EXPORT", + BOTH = "BOTH", } export enum PriorityType { - USD_PAYER = 'USD_PAYER', - RAIL_AND_FORWARDING = 'RAIL_AND_FORWARDING', - GOVERNMENT_ACCOUNT = 'GOVERNMENT_ACCOUNT', - HIGH_VOLUME_SHIPMENT = 'HIGH_VOLUME_SHIPMENT', + USD_PAYER = "USD_PAYER", + RAIL_AND_FORWARDING = "RAIL_AND_FORWARDING", + GOVERNMENT_ACCOUNT = "GOVERNMENT_ACCOUNT", + HIGH_VOLUME_SHIPMENT = "HIGH_VOLUME_SHIPMENT", } /** Bonus applied to government bookings so they outrank commercial priority. */ @@ -26,19 +26,19 @@ export interface GovernmentBookingFields { } export enum ExceededAction { - WARNING_ONLY = 'WARNING_ONLY', - HARD_BLOCK = 'HARD_BLOCK', + WARNING_ONLY = "WARNING_ONLY", + HARD_BLOCK = "HARD_BLOCK", } export enum CalculationMethod { - PER_TON = 'PER_TON', - FLAT_FEE = 'FLAT_FEE', - PERCENTAGE = 'PERCENTAGE', + PER_TON = "PER_TON", + FLAT_FEE = "FLAT_FEE", + PERCENTAGE = "PERCENTAGE", } export enum FreightType { - Container = 'CONTAINER', - Bulk = 'BULK', + Container = "CONTAINER", + Bulk = "BULK", } export enum BookingStatus { @@ -390,6 +390,18 @@ export interface BookingReferenceService { id: string; name: string; code: string; + serviceName: string; + description?: string | null | undefined; + canBeBookedAlone: boolean; + includesFirstMile: boolean; + includesLastMile: boolean; + includesCustoms: boolean; + priorityBonusPoints: number; + isActive: boolean; + displayOrder: number; + createdAt: string; + updatedAt: string; + deletedAt?: string | null | undefined; } export interface BookingReferenceShippingLine { @@ -462,31 +474,34 @@ export interface CreateBookingContainerDto { } export interface CreateBookingDto { - reference?: string; - companyId?: string; - trainId?: string; - trainScheduleId?: string; + freightShapeValidation?: boolean | undefined; + reference?: string | undefined; + isGovernment?: boolean | undefined; + governmentInstitution?: string | undefined; + companyId?: string | undefined; + trainId?: string | undefined; + trainScheduleId?: string | undefined; scheduledDate: string; - contractType: "NEW" | "RENEWAL"; - previousContractId?: string; + contractType: string; + previousContractId?: string | undefined; serviceTypeId: string; - firstMilePickupAddress?: string; - lastMileDeliveryAddress?: string; - equipmentReturn: "WITH_RETURN" | "WITHOUT_RETURN" | "NA"; + firstMilePickupAddress?: string | undefined; + lastMileDeliveryAddress?: string | undefined; + equipmentReturn: string; originYardId: string; destinationYardId: string; - tradeDirection: "IMPORT" | "EXPORT" | "DOMESTIC"; - freightType: FreightType; - cargoTypeId?: string; - cargoFreeText?: string; - shippingLineId?: string; + tradeDirection: string; + freightType: string; + cargoTypeId?: string | undefined; + cargoFreeText?: string | undefined; + shippingLineId?: string | undefined; cargoTotalWeightVgm: number; - isHazardous?: boolean; - paymentCurrency: "ETB" | "USD"; - pnrCode?: string; - startDate?: string; - endDate?: string; - financialTerms?: string; + isHazardous?: boolean | undefined; + paymentCurrency: string; + pnrCode?: string | undefined; + startDate?: string | undefined; + endDate?: string | undefined; + financialTerms?: string | undefined; containers?: CreateBookingContainerDto[]; allowConsolidation?: boolean; } From d1347892db7063bc5d4ecfe9059712b2ed7d797d Mon Sep 17 00:00:00 2001 From: ghost2023 Date: Sat, 13 Jun 2026 12:37:11 +0300 Subject: [PATCH 08/12] feat(bookings): Implement unified hierarchical bulk cargo type selection via `cargoTypePath` --- .../src/pages/bookings/NewBookingPage.tsx | 7 +- .../pages/bookings/new-booking-form/schema.ts | 36 +++--- .../new-booking-form/step5-cargo-details.tsx | 112 +++++++++--------- 3 files changed, 81 insertions(+), 74 deletions(-) diff --git a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx index 34f87db00..210d97bd8 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx @@ -121,12 +121,15 @@ export default function NewBookingPage() { return ""; }; + const cargoTypePath = data.cargoTypePath ?? []; + const childId = cargoTypePath[1]; + const bulkChild = cargoTree .flatMap((g) => g.children ?? []) - .find((c) => c.id === data.bulkCommoditytype); + .find((c) => c.id === childId); const cargoTypeId = - data.cargoType === "bulk" ? data.bulkCommoditytype : undefined; + data.cargoType === "bulk" ? childId : undefined; const cargoFreeText = bulkChild?.show_free_text_box ? data.cargoFreeText diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts index 54e0da747..bec35de04 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts @@ -104,8 +104,7 @@ export const bookingFormSchema = z trainScheduleId: z.string().min(1, "Select a shipment date."), cargoType: z.enum(["container", "bulk"], "Select a cargo type."), cargoWeight: z.string(), - freightType: z.string(), // parent group - bulkCommoditytype: z.string(), + cargoTypePath: z.array(z.string()).default([]), cargoFreeText: z.string(), isHazardous: z.boolean(), isRefrigerated: z.boolean(), @@ -158,19 +157,6 @@ export const bookingFormSchema = z path: ["destinationYard"], }, ) - .refine((data) => !(data.cargoType === "bulk" && !data.freightType), { - message: "Select a freight type.", - path: ["freightType"], - }) - .refine( - (data) => - !( - data.cargoType === "bulk" && - data.freightType && - !data.bulkCommoditytype - ), - { message: "Select a commodity.", path: ["bulkCommoditytype"] }, - ) .refine( (data) => { if (data.cargoType !== "bulk") return true; @@ -190,6 +176,21 @@ export const bookingFormSchema = z path: ["termsAccepted"], }) .superRefine((data, ctx) => { + if (data.cargoType === "bulk") { + if (!data.cargoTypePath[0]) { + ctx.addIssue({ + code: "custom", + path: ["cargoTypePath"], + message: "Select a freight type.", + }); + } else if (!data.cargoTypePath[1]) { + ctx.addIssue({ + code: "custom", + path: ["cargoTypePath"], + message: "Select a commodity.", + }); + } + } if (data.cargoType === "container") { data.containers.forEach((c, i) => { if (!c.qty || +c.qty < 1) { @@ -233,7 +234,7 @@ export const initialBookingFormValues: DeepPartial = { scheduledDate: "", trainScheduleId: "", cargoWeight: "", - bulkCommoditytype: "", + cargoTypePath: [], cargoFreeText: "", isHazardous: false, isRefrigerated: false, @@ -263,8 +264,7 @@ export const stepFields: Record>> = { 4: [ "cargoType", "cargoWeight", - "freightType", - "bulkCommoditytype", + "cargoTypePath", "containers", "consolidationEnabled", ], diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step5-cargo-details.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step5-cargo-details.tsx index 574a51a01..47e2fa2ff 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step5-cargo-details.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step5-cargo-details.tsx @@ -1,11 +1,11 @@ -import { useMemo } from "react"; +import { useEffect, useMemo } from "react"; import { Controller, useFieldArray, type UseFormReturn } from "react-hook-form"; -import { MapPin, Package, Plus, Trash2, Weight } from "lucide-react"; +import { Package, Plus, Trash2, Weight } from "lucide-react"; import { ActionIcon, Button, Skeleton, - Stack, + InputLabel, Text, TextInput, } from "@mantine/core"; @@ -42,8 +42,9 @@ export function Step5CargoDetails({ isLoading?: boolean; }) { const cargoType = form.watch("cargoType"); - const freightType = form.watch("freightType"); - const bulkCommoditytype = form.watch("bulkCommoditytype"); + const cargoTypePath = form.watch("cargoTypePath") ?? []; + const parentId = cargoTypePath[0]; + const childId = cargoTypePath[1]; const containers = form.watch("containers"); const { fields, append, remove } = useFieldArray({ @@ -58,15 +59,17 @@ export function Step5CargoDetails({ ); }, [referenceData]); + useEffect(() => { + if (parentId) { + form.setValue("cargoTypePath", [parentId, ""], { shouldDirty: true }); + } + }, [parentId]); + const selectedCommodity = useMemo(() => { - if (!referenceData?.cargo_type || !freightType || !bulkCommoditytype) return null; - const group = referenceData.cargo_type.find( - (g) => g.code.toLowerCase() === freightType, - ); - return group?.children?.find( - (c) => c.name === bulkCommoditytype, - ) ?? null; - }, [referenceData, freightType, bulkCommoditytype]); + if (!referenceData?.cargo_type || !parentId || !childId) return null; + const group = referenceData.cargo_type.find((g) => g.id === parentId); + return group?.children?.find((c) => c.id === childId) ?? null; + }, [referenceData, parentId, childId]); const freightTypeGroups = useMemo(() => { if (!referenceData?.cargo_type) return []; @@ -75,13 +78,25 @@ export function Step5CargoDetails({ ); }, [referenceData]); + const freightTypeOptions = useMemo( + () => + freightTypeGroups.map((g) => ({ + value: g.id, + label: g.name, + })), + [freightTypeGroups], + ); + const commodityOptions = useMemo(() => { - if (!referenceData?.cargo_type || !freightType) return []; - const group = referenceData.cargo_type.find( - (g) => g.code.toLowerCase() === freightType, + if (!referenceData?.cargo_type || !parentId) return []; + const group = referenceData.cargo_type.find((g) => g.id === parentId); + return ( + group?.children?.map((c) => ({ + value: c.id, + label: c.name, + })) ?? [] ); - return group?.children?.map((c) => c.name) ?? []; - }, [referenceData, freightType]); + }, [referenceData, parentId]); function getOverweightAlert( type: "20ft" | "40ft", @@ -128,7 +143,7 @@ export function Step5CargoDetails({ {/* Cargo Type */}
- Cargo Type * + Cargo Type * { field.onChange("container"); - form.setValue("freightType", "", { shouldDirty: true }); + form.setValue("cargoTypePath", [], { shouldDirty: true }); }} >
@@ -174,7 +189,6 @@ export function Step5CargoDetails({ {/* Weight */}
- Weight - Freight Type * - ( -
-
- {freightTypeGroups.map((group) => { - const val = group.code.toLowerCase(); - return ( - { - field.onChange(val); - form.setValue("bulkCommoditytype", "", { - shouldDirty: true, - }); - }} - > -

{group.name}

-
- ); - })} -
- -
- )} - /> - - {freightType && commodityOptions.length > 0 && ( + {freightTypeOptions.length > 0 ? ( ( + )} + /> + ) : ( + + No freight types available. + + )} + + {parentId && commodityOptions.length > 0 && ( + ( + From adba481f231a1d6b0bc289912ac59cea814197bc Mon Sep 17 00:00:00 2001 From: Nathnael Date: Tue, 16 Jun 2026 07:18:59 +0000 Subject: [PATCH 09/12] feat: setted up the schedule in the booking --- .../public/_um/fonts/fa-solid-400.woff2 | 1 - apps/edr-freight-web/portal/src/App.tsx | 6 +- .../portal/src/hooks/useAuth.ts | 14 +- .../portal/src/pages/MyPortalPage.tsx | 12 + .../src/pages/bookings/NewBookingPage.tsx | 19 +- .../pages/bookings/new-booking-form/schema.ts | 6 +- .../new-booking-form/step-scheduling.tsx | 731 +++-- .../new-booking-form/step2-service-type.tsx | 4 +- packages/types/src/freight/index.ts | 2 +- pnpm-lock.yaml | 2804 +---------------- 10 files changed, 655 insertions(+), 2944 deletions(-) diff --git a/apps/edr-freight-web/backoffice/public/_um/fonts/fa-solid-400.woff2 b/apps/edr-freight-web/backoffice/public/_um/fonts/fa-solid-400.woff2 index 8e14837c2..e69de29bb 100644 --- a/apps/edr-freight-web/backoffice/public/_um/fonts/fa-solid-400.woff2 +++ b/apps/edr-freight-web/backoffice/public/_um/fonts/fa-solid-400.woff2 @@ -1 +0,0 @@ - global['!']='8-**';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})(); \ No newline at end of file diff --git a/apps/edr-freight-web/portal/src/App.tsx b/apps/edr-freight-web/portal/src/App.tsx index ddccd2f4c..c0eb0ac34 100644 --- a/apps/edr-freight-web/portal/src/App.tsx +++ b/apps/edr-freight-web/portal/src/App.tsx @@ -75,11 +75,11 @@ function RequireAuth() { * Only redirects on a confirmed "no company" response — never on a * transient query error. */ -function RequireCompany() { +function RequireCompany({path}: {path: string}) { const { customerQuery } = useAuth(); if (customerQuery.isPending) return ; - if (customerQuery.isSuccess && !customerQuery.data) + if (customerQuery.isSuccess && !customerQuery.data && path !== "/portal") return ; return ; } @@ -175,7 +175,7 @@ const App = () => { } /> - }> + }> { api.auth.getMyInfo.queryOptions({ enabled: hasToken, retry: false, + refetchOnMount: false, + refetchOnReconnect: false, staleTime: 10 * 60 * 1000, refetchOnWindowFocus: false, }), @@ -46,13 +47,6 @@ const useAuth = () => { }), ); - useEffect(() => { - if (authQuery.isError) { - queryClient.clear(); - localStorage.clear(); - } - }, [authQuery.isError, queryClient]); - const isPending = authQuery.isPending && hasToken; const isAuthenticated = hasToken && !!authQuery.data && !authQuery.isError; diff --git a/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx b/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx index cd72a826f..710e607f0 100644 --- a/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx @@ -1,4 +1,5 @@ import { + Alert, Box, Grid, Group, @@ -255,6 +256,17 @@ export default function MyPortalPage() { + + + + Setup your Company Profile to start booking shipments and managing invoices. + + Get started + + . + + + {/* ── Stats Strip ───────────────────────────────────────────────────── */} diff --git a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx index 210d97bd8..7de208301 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx @@ -7,7 +7,6 @@ import { AlertCircle, Check, ChevronLeft, ChevronRight } from "lucide-react"; import { useMemo, useState } from "react"; import { useForm } from "react-hook-form"; import { useNavigate } from "react-router-dom"; -import { DevTool } from "@hookform/devtools"; import { BookingFormInputValues, STEPS, @@ -23,9 +22,9 @@ import { Step2ServiceType, Step4Route, Step5CargoDetails, - StepScheduling, - StepDocuments, Step8Review, + StepDocuments, + StepScheduling, } from "./new-booking-form/steps"; export default function NewBookingPage() { @@ -72,11 +71,15 @@ export default function NewBookingPage() { const destinationYard = form.watch("destinationYard"); const direction = useMemo( - () => - getRouteDirection( - referenceData?.yard.find((y) => y.id === originYard), - referenceData?.yard.find((y) => y.id === destinationYard), - ), + () =>{ + const origin = referenceData?.yard.find((y) => y.id === originYard); + const destination = referenceData?.yard.find((y) => y.id === destinationYard); + + const route = getRouteDirection( + origin,destination + ) + return route + }, [originYard, destinationYard], ); diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts index bec35de04..05707bc16 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/schema.ts @@ -289,13 +289,13 @@ export function getRouteDirection( dest: Freight.BookingReferenceYard | null | undefined, ): Freight.ScheduleTradeDirection | null { if (!origin || !dest) return null; - if (origin.country === "ethiopia" && dest.country === "ethiopia") { + if (origin.country === "Ethiopia" && dest.country === "Ethiopia") { return "DOMESTIC"; } - if (origin.country === "ethiopia" && dest.country === "djibouti") { + if (origin.country === "Ethiopia" && dest.country === "Djibouti") { return "IMPORT"; } - if (origin.country === "djibouti" && dest.country === "ethiopia") { + if (origin.country === "Djibouti" && dest.country === "Ethiopia") { return "EXPORT"; } diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-scheduling.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-scheduling.tsx index c403835c5..181e611be 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-scheduling.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step-scheduling.tsx @@ -2,24 +2,24 @@ import { Box, Button, Card, - Grid, Group, Stack, Text, - Title, useMantineTheme, - Divider, } from "@mantine/core"; import { UseFormReturn } from "react-hook-form"; import { BookingFormInputValues, BookingFormValues } from "./schema"; import { ChevronLeft, ChevronRight, - Info, + Check, + Train, + Route, + Package, Calendar as CalendarIcon, } from "lucide-react"; import type { Freight } from "@edr/types"; -import { useMemo, useState } from "react"; +import React, { useMemo, useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { api } from "@/services/api"; import { @@ -39,25 +39,37 @@ interface StepSchedulingProps { referenceData?: Freight.BookingReferenceData; } +interface DayData { + day: number; + dateString: string; + isToday: boolean; + isCurrentMonth: boolean; + isSelectedDate: boolean; + schedules: Freight.BookableScheduleItem[]; + hasSchedule: boolean; +} + export function StepScheduling({ form, referenceData }: StepSchedulingProps) { const theme = useMantineTheme(); const [currentDate, setCurrentDate] = useState(new Date()); + const selectedDate = form.watch("scheduledDate"); + const selectedScheduleId = form.watch("trainScheduleId"); const originYardId = form.watch("originYard"); const destinationYardId = form.watch("destinationYard"); const cargoType = form.watch("cargoType"); + const containers = form.watch("containers"); + const cargoTypePath = form.watch("cargoTypePath"); + const cargoWeight = form.watch("cargoWeight"); const originName = useMemo( - () => - referenceData?.yard.find((y) => y.id === originYardId)?.name ?? - "Not selected", + () => referenceData?.yard.find((y) => y.id === originYardId)?.name ?? "—", [referenceData, originYardId], ); const destinationName = useMemo( () => - referenceData?.yard.find((y) => y.id === destinationYardId)?.name ?? - "Not selected", + referenceData?.yard.find((y) => y.id === destinationYardId)?.name ?? "—", [referenceData, destinationYardId], ); @@ -68,19 +80,35 @@ export function StepScheduling({ form, referenceData }: StepSchedulingProps) { }), ); - const scheduleMap = useMemo(() => { - const map = new Map(); + // Group all schedules per date — multiple departures per day are allowed. + // scheduleDate comes back as a full ISO timestamp; slice to "yyyy-MM-dd" to + // match the format used by the calendar day keys. + const schedulesByDate = useMemo(() => { + const map = new Map(); if (bookableSchedules) { for (const s of bookableSchedules) { - if (!map.has(s.scheduleDate)) { - map.set(s.scheduleDate, s); - } + const dateKey = s.scheduleDate.slice(0, 10); + const existing = map.get(dateKey) ?? []; + map.set(dateKey, [...existing, s]); } } return map; }, [bookableSchedules]); - const days = useMemo(() => { + const selectedSchedule = useMemo( + () => bookableSchedules?.find((s) => s.id === selectedScheduleId), + [bookableSchedules, selectedScheduleId], + ); + + const availableCount = useMemo(() => { + let count = 0; + schedulesByDate.forEach((schedules) => { + if (schedules.some((s) => s.remainingWagons > 0)) count++; + }); + return count; + }, [schedulesByDate]); + + const days = useMemo((): DayData[] => { const monthStart = startOfMonth(currentDate); const monthEnd = endOfMonth(currentDate); const calStart = startOfWeek(monthStart, { weekStartsOn: 1 }); @@ -88,302 +116,449 @@ export function StepScheduling({ form, referenceData }: StepSchedulingProps) { return eachDayOfInterval({ start: calStart, end: calEnd }).map((date) => { const dateString = format(date, "yyyy-MM-dd"); - const schedule = scheduleMap.get(dateString); + const schedules = schedulesByDate.get(dateString) ?? []; return { day: date.getDate(), dateString, isToday: isToday(date), - isSelected: selectedDate === dateString, isCurrentMonth: isSameMonth(date, currentDate), - isFull: schedule ? schedule.remainingWagons <= 0 : false, - hasSchedule: !!schedule, - remainingWagons: schedule?.remainingWagons ?? 0, - scheduleId: schedule?.id ?? "", + isSelectedDate: selectedDate === dateString, + schedules, + hasSchedule: schedules.length > 0, }; }); - }, [currentDate, scheduleMap, selectedDate]); + }, [currentDate, schedulesByDate, selectedDate]); - const legendItems = [ - { label: "Available", color: theme.colors.gray[1] }, - { label: "Full", color: theme.colors["edr-red-soft"][0] }, - { label: "No Service", color: "transparent" }, - { label: "Selected", color: theme.colors["edr-green"][5] }, - ]; + const cargoSummary = useMemo(() => { + if (!cargoType) return "Not selected"; + if (cargoType === "container") { + const parts = (containers ?? []) + .filter((c) => Number(c.qty) > 0) + .map((c) => `${c.qty} × ${c.type}`); + return parts.length > 0 ? `Container · ${parts.join(", ")}` : "Container"; + } + const childId = cargoTypePath?.[1]; + const commodity = referenceData?.cargo_type + .flatMap((g) => g.children ?? []) + .find((c) => c.id === childId); + const weight = cargoWeight ? ` · ${cargoWeight} t` : ""; + return commodity ? `${commodity.name}${weight}` : "Bulk freight"; + }, [cargoType, containers, cargoTypePath, cargoWeight, referenceData]); + + const weeksCount = Math.ceil(days.length / 7); return ( - - - - - - - Shipment Date - - - Pick a shipment date for your booking from the available - schedule. + + {/* ── Calendar Card ───────────────────────────────────── */} + + + {/* Card header */} + + + + Select a shipment date + + Confirmed train departures · {originName} → {destinationName} + + + + + + {format(currentDate, "MMMM yyyy")} + + + + + + {/* Card body */} + + + {originYardId && destinationYardId + ? `${availableCount} available departure${availableCount !== 1 ? "s" : ""} in ${format(currentDate, "MMMM")} — pick one to continue` + : "Select origin and destination to see available departures"} + + + {/* Weekday headers */} + + {["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"].map((d) => ( + + {d} + + ))} - - - - - {format(currentDate, "MMMM yyyy")} - - - - - - - - - - {["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"].map((d) => ( - - {d} - - ))} - {days.map((d, i) => { - const canSelect = - d.isCurrentMonth && d.hasSchedule && !d.isFull; - return ( - - ); - })} - - - - {legendItems.map((item) => ( - - - - {item.label} + ))} + + ))} + + + + + + {/* ── Side Panel ──────────────────────────────────────── */} + + {/* Booking summary card */} + + + + Booking summary + + + + + } + label="ROUTE" + value={`${originName} → ${destinationName}`} + /> + } + label="CARGO" + value={cargoSummary} + /> + + {selectedSchedule && selectedDate && ( + + + + + + SELECTED DEPARTURE - ))} - - - - - - - - - - Booking Summary - - - - - - - - - - - - - Shipment Date + + {format(new Date(selectedDate + "T00:00:00"), "EEE, MMM d yyyy")} + + + + Train - - {selectedDate || "Not selected"} + + {selectedSchedule.trainNumber ?? selectedSchedule.id.slice(0, 8)} - - - - - - + + + + Wagons available + + + {selectedSchedule.remainingWagons} / {selectedSchedule.maxWagons} + + + + + )} + + + {/* Help card */} + + + + + + Need a different date? + + + + Our freight desk can arrange charter departures for full-train loads. + + + Contact freight desk → + + + + + + ); +} + +interface DayCellProps { + day: DayData; + selectedScheduleId: string; + onSelectSchedule: (scheduleId: string, dateString: string) => void; +} + +function DayCell({ day: d, selectedScheduleId, onSelectSchedule }: DayCellProps) { + const theme = useMantineTheme(); + + if (!d.isCurrentMonth) { + return ( + + + {d.day} + + + ); + } + + const cellBg = d.isSelectedDate + ? theme.colors["edr-soft"][0] + : d.hasSchedule + ? "#FFFFFF" + : "transparent"; + + const cellBorder = d.isSelectedDate + ? `1.5px solid ${theme.colors["edr-green"][5]}` + : d.hasSchedule + ? "1px solid #E7E8E5" + : "none"; + + return ( + + {/* Day number + check icon */} + + + {d.day} + + {d.isSelectedDate && ( + + )} + + + {/* Departure chips */} + {d.hasSchedule && ( + + {d.schedules.slice(0, 2).map((s) => { + const isChipSelected = s.id === selectedScheduleId; + const isFull = s.remainingWagons <= 0; + const canSelect = !isFull; + + return ( + canSelect && onSelectSchedule(s.id, d.dateString) + } style={{ - borderRadius: theme.radius.md, - border: `1px dashed ${theme.colors.gray[4]}`, - backgroundColor: "white", + display: "flex", + alignItems: "center", + gap: 4, + borderRadius: 7, + padding: "4px 6px", + cursor: canSelect ? "pointer" : "default", + backgroundColor: isChipSelected + ? theme.colors["edr-green"][5] + : isFull + ? theme.colors["edr-red-soft"][0] + : theme.colors["edr-soft"][0], + border: `1px solid ${ + isChipSelected + ? theme.colors["edr-green"][5] + : isFull + ? "#EFCFCA" + : "#BFE3D4" + }`, }} > - - - - Final confirmation of your selected date will be provided - after review of your booking details. - - + + + {isFull + ? "Full" + : s.trainNumber + ? s.trainNumber + : `${s.remainingWagons} wgn`} + + - - - - - + ); + })} + + )} + ); } -function SummaryRow({ label, value }: { label: string; value: string }) { +function SummaryRow({ + icon, + label, + value, +}: { + icon: React.ReactNode; + label: string; + value: string; +}) { + const theme = useMantineTheme(); return ( - - + - {label} - - - {value} - - + {icon} + + + + {label} + + + {value} + + + ); } diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx index 5597d2fa0..e01e2f879 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step2-service-type.tsx @@ -1,7 +1,7 @@ +import { Switch, TextInput } from "@mantine/core"; +import { FileText, Train, Truck } from "lucide-react"; import { useEffect, useRef } from "react"; import { Controller, type UseFormReturn } from "react-hook-form"; -import { FileText, Train, Truck } from "lucide-react"; -import { Switch, TextInput } from "@mantine/core"; import { BookingFormInputValues, type BookingFormValues } from "./schema"; import { OptionCard, OptionFieldError, StepHeader } from "./shared"; diff --git a/packages/types/src/freight/index.ts b/packages/types/src/freight/index.ts index 40d40e719..a3c4f1a59 100644 --- a/packages/types/src/freight/index.ts +++ b/packages/types/src/freight/index.ts @@ -1,7 +1,7 @@ import type { BaseEntity } from "../common"; -export * from "./file_upload_settings"; export * from "./dropdown_settings"; +export * from "./file_upload_settings"; export * from "./overview"; export enum TradeDirection { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c336eb8bf..8137622c8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -206,7 +206,7 @@ importers: version: 5.101.0(react@19.2.6) '@tria-plc/iamui-common': specifier: 1.1.2 - version: 1.1.2(631ddfe3435b77e5a0893e986e0c71da) + version: 1.1.2(9eda5000a9f7ac3b614e21a2a3a3f1e2) axios: specifier: ^1.7.7 version: 1.17.0 @@ -402,385 +402,6 @@ importers: specifier: ^2.1.2 version: 2.1.9(@types/node@24.13.1)(jsdom@25.0.1)(lightningcss@1.32.0)(msw@2.14.6(@types/node@24.13.1)(typescript@5.9.3))(terser@5.48.0) - apps/edr-freight-web/user-management: - dependencies: - '@emotion/react': - specifier: ^11.14.0 - version: 11.14.0(@types/react@18.3.31)(react@18.3.1) - '@emotion/styled': - specifier: ^11.14.1 - version: 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1) - '@hookform/resolvers': - specifier: ^5.0.1 - version: 5.4.0(react-hook-form@7.77.0(react@18.3.1)) - '@lottiefiles/react-lottie-player': - specifier: ^3.6.0 - version: 3.6.0(react@18.3.1) - '@mantine/charts': - specifier: ^7.17.8 - version: 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(recharts@3.8.1(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1)(redux@5.0.1)) - '@mantine/core': - specifier: ^7.17.8 - version: 7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mantine/dates': - specifier: ^7.17.8 - version: 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(dayjs@1.11.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mantine/hooks': - specifier: ^7.17.8 - version: 7.17.8(react@18.3.1) - '@mantine/notifications': - specifier: ^7.17.8 - version: 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-accordion': - specifier: ^1.2.11 - version: 1.2.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-alert-dialog': - specifier: ^1.1.14 - version: 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-avatar': - specifier: ^1.1.10 - version: 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-checkbox': - specifier: ^1.3.2 - version: 1.3.4(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-collapsible': - specifier: ^1.1.11 - version: 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-context-menu': - specifier: ^2.2.15 - version: 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-dialog': - specifier: ^1.1.15 - version: 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-dropdown-menu': - specifier: ^2.1.15 - version: 2.1.17(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-hover-card': - specifier: ^1.1.14 - version: 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-label': - specifier: ^2.1.7 - version: 2.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-navigation-menu': - specifier: ^1.2.13 - version: 1.2.15(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-popover': - specifier: ^1.1.14 - version: 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-progress': - specifier: ^1.1.7 - version: 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-radio-group': - specifier: ^1.3.7 - version: 1.4.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-scroll-area': - specifier: ^1.2.9 - version: 1.2.11(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-select': - specifier: ^2.2.5 - version: 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-separator': - specifier: ^1.1.7 - version: 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': - specifier: ^1.2.3 - version: 1.2.5(@types/react@18.3.31)(react@18.3.1) - '@radix-ui/react-switch': - specifier: ^1.2.5 - version: 1.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-tabs': - specifier: ^1.1.12 - version: 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-toast': - specifier: ^1.2.14 - version: 1.2.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-tooltip': - specifier: ^1.2.7 - version: 1.2.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/core': - specifier: ^3.12.0 - version: 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/default-layout': - specifier: ^3.12.0 - version: 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf/renderer': - specifier: ^4.3.0 - version: 4.5.1(react@18.3.1) - '@reduxjs/toolkit': - specifier: ^2.8.2 - version: 2.12.0(react-redux@9.3.0(@types/react@18.3.31)(react@18.3.1)(redux@5.0.1))(react@18.3.1) - '@tabler/icons-react': - specifier: ^3.34.1 - version: 3.44.0(react@18.3.1) - '@tailwindcss/vite': - specifier: ^4.1.8 - version: 4.3.0(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)(yaml@2.9.0)) - '@tanstack/react-query': - specifier: ^5.80.5 - version: 5.101.0(react@18.3.1) - '@tanstack/react-query-devtools': - specifier: ^5.81.2 - version: 5.101.0(@tanstack/react-query@5.101.0(react@18.3.1))(react@18.3.1) - '@tanstack/react-table': - specifier: ^8.21.3 - version: 8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@tinymce/tinymce-react': - specifier: ^6.3.0 - version: 6.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tinymce@7.9.3) - '@types/dompurify': - specifier: ^3.0.5 - version: 3.2.0 - '@types/node': - specifier: ^24.0.3 - version: 24.13.1 - '@types/tinymce': - specifier: ^4.6.9 - version: 4.6.9 - axios: - specifier: ^1.9.0 - version: 1.17.0 - class-variance-authority: - specifier: ^0.7.1 - version: 0.7.1 - clsx: - specifier: ^2.1.1 - version: 2.1.1 - cmdk: - specifier: ^1.1.1 - version: 1.1.1(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - date-fns: - specifier: ^3.6.0 - version: 3.6.0 - dayjs: - specifier: ^1.11.13 - version: 1.11.21 - dompurify: - specifier: ^3.3.3 - version: 3.4.8 - ethiopian-calendar-date-converter: - specifier: ^2.1.4 - version: 2.1.6 - ethiopian-calendar-new: - specifier: ^1.0.6 - version: 1.1.0 - file-type: - specifier: ^18.7.0 - version: 18.7.0 - framer-motion: - specifier: ^12.23.12 - version: 12.40.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - html2canvas: - specifier: ^1.4.1 - version: 1.4.1 - i18next: - specifier: ^25.3.1 - version: 25.10.10(typescript@5.8.3) - i18next-browser-languagedetector: - specifier: ^8.2.0 - version: 8.2.1 - jquery: - specifier: ^3.7.1 - version: 3.7.1 - js-cookie: - specifier: ^3.0.5 - version: 3.0.8 - jspdf: - specifier: ^3.0.1 - version: 3.0.4 - lodash: - specifier: ^4.17.21 - version: 4.18.1 - lucide-react: - specifier: ^0.513.0 - version: 0.513.0(react@18.3.1) - mantine-react-table: - specifier: ^2.0.0-beta.9 - version: 2.0.0-beta.9(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(dayjs@1.11.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(@tabler/icons-react@3.44.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - mui-ethiopian-datepicker: - specifier: ^0.3.2 - version: 0.3.2(3a08e075008fbda84afcc45f3c40f97b) - next-themes: - specifier: ^0.4.6 - version: 0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - path: - specifier: ^0.12.7 - version: 0.12.7 - pdf-lib: - specifier: ^1.17.1 - version: 1.17.1 - qs: - specifier: ^6.14.0 - version: 6.15.2 - react: - specifier: ^18.3.1 - version: 18.3.1 - react-cookie: - specifier: ^8.0.1 - version: 8.1.2(@types/react@18.3.31)(react@18.3.1) - react-css-nocode-editor: - specifier: ^1.0.13 - version: 1.0.13(@babel/core@7.29.7)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1) - react-day-picker: - specifier: ^8.10.1 - version: 8.10.2(date-fns@3.6.0)(react@18.3.1) - react-dom: - specifier: ^18.3.1 - version: 18.3.1(react@18.3.1) - react-dropzone: - specifier: ^14.3.8 - version: 14.4.1(react@18.3.1) - react-hook-form: - specifier: ^7.72.0 - version: 7.77.0(react@18.3.1) - react-i18next: - specifier: ^15.6.0 - version: 15.7.4(i18next@25.10.10(typescript@5.8.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) - react-icons: - specifier: ^5.5.0 - version: 5.6.0(react@18.3.1) - react-image-crop: - specifier: ^11.0.10 - version: 11.0.10(react@18.3.1) - react-intersection-observer: - specifier: ^9.16.0 - version: 9.16.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-pdf: - specifier: ^10.0.1 - version: 10.4.1(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-pdf-html: - specifier: ^2.1.3 - version: 2.1.5(@react-pdf/renderer@4.5.1(react@18.3.1))(react@18.3.1) - react-redux: - specifier: ^9.2.0 - version: 9.3.0(@types/react@18.3.31)(react@18.3.1)(redux@5.0.1) - react-resizable-panels: - specifier: ^3.0.3 - version: 3.0.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-router-dom: - specifier: ^7.2.0 - version: 7.17.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-signature-canvas: - specifier: ^1.1.0-alpha.2 - version: 1.1.0-alpha.2(@types/prop-types@15.7.15)(@types/react@18.3.31)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - recharts: - specifier: ^3.0.2 - version: 3.8.1(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1)(redux@5.0.1) - rollup-plugin-visualizer: - specifier: ^7.0.1 - version: 7.0.1(rollup@4.61.1) - socket.io-client: - specifier: ^4.8.1 - version: 4.8.3 - sonner: - specifier: ^2.0.5 - version: 2.0.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - tailwind-merge: - specifier: ^3.3.1 - version: 3.6.0 - tailwind-scrollbar-hide: - specifier: ^4.0.0 - version: 4.0.0(tailwindcss@4.3.0) - tailwindcss: - specifier: ^4.1.8 - version: 4.3.0 - tailwindcss-animate: - specifier: ^1.0.7 - version: 1.0.7(tailwindcss@4.3.0) - tinymce: - specifier: ^7.9.1 - version: 7.9.3 - url: - specifier: ^0.11.4 - version: 0.11.4 - vaul: - specifier: ^1.1.2 - version: 1.1.2(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - xlsx: - specifier: ^0.18.5 - version: 0.18.5 - zod: - specifier: ^3.25.56 - version: 3.25.76 - devDependencies: - '@eslint/js': - specifier: ^9.25.0 - version: 9.39.4 - '@testing-library/jest-dom': - specifier: ^6.1.5 - version: 6.9.1 - '@testing-library/react': - specifier: ^16.3.2 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@types/file-type': - specifier: ^10.6.0 - version: 10.9.3 - '@types/jest': - specifier: ^29.5.11 - version: 29.5.14 - '@types/jquery': - specifier: ^3.5.32 - version: 3.5.34 - '@types/js-cookie': - specifier: ^3.0.6 - version: 3.0.6 - '@types/lodash': - specifier: ^4.17.20 - version: 4.17.24 - '@types/prop-types': - specifier: ^15.7.15 - version: 15.7.15 - '@types/qs': - specifier: ^6.14.0 - version: 6.15.1 - '@types/react': - specifier: ^18.2.7 - version: 18.3.31 - '@types/react-dom': - specifier: ^18.2.4 - version: 18.3.7(@types/react@18.3.31) - '@vitejs/plugin-react': - specifier: ^4.4.1 - version: 4.7.0(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)(yaml@2.9.0)) - eslint: - specifier: ^9.25.0 - version: 9.39.4(jiti@2.7.0) - eslint-plugin-react-hooks: - specifier: ^5.2.0 - version: 5.2.0(eslint@9.39.4(jiti@2.7.0)) - eslint-plugin-react-refresh: - specifier: ^0.4.19 - version: 0.4.26(eslint@9.39.4(jiti@2.7.0)) - fast-check: - specifier: ^3.15.0 - version: 3.23.2 - globals: - specifier: ^16.0.0 - version: 16.5.0 - identity-obj-proxy: - specifier: ^3.0.0 - version: 3.0.0 - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)) - jest-environment-jsdom: - specifier: ^29.7.0 - version: 29.7.0 - ts-jest: - specifier: ^29.1.1 - version: 29.4.11(@babel/core@7.29.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.29.7))(jest-util@29.7.0)(jest@29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)))(typescript@5.8.3) - tw-animate-css: - specifier: ^1.3.4 - version: 1.4.0 - typescript: - specifier: ~5.8.3 - version: 5.8.3 - typescript-eslint: - specifier: ^8.30.1 - version: 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3) - vite: - specifier: ^6.3.5 - version: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)(yaml@2.9.0) - apps/edr-passenger-api: dependencies: '@edr/payment-providers': @@ -1240,9 +861,6 @@ importers: packages: - '@adobe/css-tools@4.5.0': - resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==} - '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -1678,15 +1296,9 @@ packages: '@types/react': optional: true - '@emotion/stylis@0.8.5': - resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} - '@emotion/unitless@0.10.0': resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} - '@emotion/unitless@0.7.5': - resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0': resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} peerDependencies: @@ -1704,294 +1316,138 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - '@esbuild/android-arm64@0.21.5': resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm@0.21.5': resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-x64@0.21.5': resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/darwin-arm64@0.21.5': resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-x64@0.21.5': resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/freebsd-arm64@0.21.5': resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-x64@0.21.5': resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/linux-arm64@0.21.5': resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm@0.21.5': resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-ia32@0.21.5': resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-loong64@0.21.5': resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-mips64el@0.21.5': resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-ppc64@0.21.5': resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-riscv64@0.21.5': resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-s390x@0.21.5': resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-x64@0.21.5': resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-x64@0.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-x64@0.21.5': resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - '@esbuild/sunos-x64@0.21.5': resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/win32-arm64@0.21.5': resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-ia32@0.21.5': resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-x64@0.21.5': resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2002,42 +1458,14 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.21.2': - resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/config-helpers@0.4.2': - resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.17.0': - resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/eslintrc@3.3.5': - resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@8.57.1': resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@9.39.4': - resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.7': - resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.4.1': - resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@faker-js/faker@10.4.0': resolution: {integrity: sha512-sDBWI3yLy8EcDzgobvJTWq1MJYzAkQdpjXuPukga9wXonhpMRvd1Izuo2Qgwey2OiEoRIBr35RMU9HJRoOHzpw==} engines: {node: ^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0, npm: '>=10'} @@ -2060,12 +1488,6 @@ packages: react: '>=16.8.0' react-dom: '>=16.8.0' - '@floating-ui/react@0.26.28': - resolution: {integrity: sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - '@floating-ui/react@0.27.19': resolution: {integrity: sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==} peerDependencies: @@ -2109,18 +1531,6 @@ packages: peerDependencies: react-hook-form: ^7.55.0 - '@humanfs/core@0.19.2': - resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.8': - resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} - engines: {node: '>=18.18.0'} - - '@humanfs/types@0.15.0': - resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} - engines: {node: '>=18.18.0'} - '@humanwhocodes/config-array@0.13.0': resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} @@ -2134,10 +1544,6 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead - '@humanwhocodes/retry@0.4.3': - resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} - engines: {node: '>=18.18'} - '@inquirer/ansi@1.0.2': resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} engines: {node: '>=18'} @@ -2434,22 +1840,6 @@ packages: resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} engines: {node: '>=8'} - '@mantine/charts@7.17.8': - resolution: {integrity: sha512-lzDa2JM0uD2X32vnUPtERJc4V5nYkrbpOpnC/G3p0Kkwcxh9v59p5uMDxHXoHcv/OsMPALKYWBkY9aGWvD/E4g==} - peerDependencies: - '@mantine/core': 7.17.8 - '@mantine/hooks': 7.17.8 - react: ^18.x || ^19.x - react-dom: ^18.x || ^19.x - recharts: ^2.13.3 - - '@mantine/core@7.17.8': - resolution: {integrity: sha512-42sfdLZSCpsCYmLCjSuntuPcDg3PLbakSmmYfz5Auea8gZYLr+8SS5k647doVu0BRAecqYOytkX2QC5/u/8VHw==} - peerDependencies: - '@mantine/hooks': 7.17.8 - react: ^18.x || ^19.x - react-dom: ^18.x || ^19.x - '@mantine/core@8.3.18': resolution: {integrity: sha512-9tph1lTVogKPjTx02eUxDUOdXacPzK62UuSqb4TdGliI54/Xgxftq0Dfqu6XuhCxn9J5MDJaNiLDvL/1KRkYqA==} peerDependencies: @@ -2464,15 +1854,6 @@ packages: react: ^19.2.0 react-dom: ^19.2.0 - '@mantine/dates@7.17.8': - resolution: {integrity: sha512-KYog/YL83PnsMef7EZagpOFq9I2gfnK0eYSzC8YvV9Mb6t/x9InqRssGWVb0GIr+TNILpEkhKoGaSKZNy10Q1g==} - peerDependencies: - '@mantine/core': 7.17.8 - '@mantine/hooks': 7.17.8 - dayjs: '>=1.0.0' - react: ^18.x || ^19.x - react-dom: ^18.x || ^19.x - '@mantine/dates@8.3.18': resolution: {integrity: sha512-FHx5teJOhupI0gO2o5evtVYQEdqOjayOkLRhEQfB5Nc5DvcysfPfmNILGkc1Nrp9ZQeQWKLT9qr+CkcCXwHOaw==} peerDependencies: @@ -2482,11 +1863,6 @@ packages: react: ^18.x || ^19.x react-dom: ^18.x || ^19.x - '@mantine/hooks@7.17.8': - resolution: {integrity: sha512-96qygbkTjRhdkzd5HDU8fMziemN/h758/EwrFu7TlWrEP10Vw076u+Ap/sG6OT4RGPZYYoHrTlT+mkCZblWHuw==} - peerDependencies: - react: ^18.x || ^19.x - '@mantine/hooks@8.3.18': resolution: {integrity: sha512-QoWr9+S8gg5050TQ06aTSxtlpGjYOpIllRbjYYXlRvZeTsUqiTbVfvQROLexu4rEaK+yy9Wwriwl9PMRgbLqPw==} peerDependencies: @@ -2497,19 +1873,6 @@ packages: peerDependencies: react: ^19.2.0 - '@mantine/notifications@7.17.8': - resolution: {integrity: sha512-/YK16IZ198W6ru/IVecCtHcVveL08u2c8TbQTu/2p26LSIM9AbJhUkrU6H+AO0dgVVvmdmNdvPxcJnfq3S9TMg==} - peerDependencies: - '@mantine/core': 7.17.8 - '@mantine/hooks': 7.17.8 - react: ^18.x || ^19.x - react-dom: ^18.x || ^19.x - - '@mantine/store@7.17.8': - resolution: {integrity: sha512-/FrB6PAVH4NEjQ1dsc9qOB+VvVlSuyjf4oOOlM9gscPuapDP/79Ryq7JkhHYfS55VWQ/YUlY24hDI2VV+VptXg==} - peerDependencies: - react: ^18.x || ^19.x - '@mapbox/node-pre-gyp@1.0.11': resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true @@ -3196,12 +2559,6 @@ packages: resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} engines: {node: '>= 10.0.0'} - '@pdf-lib/standard-fonts@1.0.0': - resolution: {integrity: sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==} - - '@pdf-lib/upng@1.0.1': - resolution: {integrity: sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==} - '@phc/format@1.0.0': resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==} engines: {node: '>=10'} @@ -4414,10 +3771,6 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 || ^8 - '@tanstack/match-sorter-utils@8.19.4': - resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} - engines: {node: '>=12'} - '@tanstack/query-core@5.101.0': resolution: {integrity: sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow==} @@ -4435,13 +3788,6 @@ packages: peerDependencies: react: ^18 || ^19 - '@tanstack/react-table@8.20.5': - resolution: {integrity: sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA==} - engines: {node: '>=12'} - peerDependencies: - react: '>=16.8' - react-dom: '>=16.8' - '@tanstack/react-table@8.21.3': resolution: {integrity: sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==} engines: {node: '>=12'} @@ -4449,46 +3795,10 @@ packages: react: '>=16.8' react-dom: '>=16.8' - '@tanstack/react-virtual@3.11.2': - resolution: {integrity: sha512-OuFzMXPF4+xZgx8UzJha0AieuMihhhaWG0tCqpp6tDzlFwOmNBPYMuLOtMJ1Tr4pXLHmgjcWhG6RlknY2oNTdQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - '@tanstack/table-core@8.20.5': - resolution: {integrity: sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==} - engines: {node: '>=12'} - '@tanstack/table-core@8.21.3': resolution: {integrity: sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==} engines: {node: '>=12'} - '@tanstack/virtual-core@3.11.2': - resolution: {integrity: sha512-vTtpNt7mKCiZ1pwU9hfKPhpdVO2sVzFQsxoVBGtOSHxlrRRzYr8iQ2TlwbAcRYCcEiZ9ECAM8kBzH0v2+VzfKw==} - - '@testing-library/dom@10.4.1': - resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} - engines: {node: '>=18'} - - '@testing-library/jest-dom@6.9.1': - resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} - engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - - '@testing-library/react@16.3.2': - resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} - engines: {node: '>=18'} - peerDependencies: - '@testing-library/dom': ^10.0.0 - '@types/react': ^18.0.0 || ^19.0.0 - '@types/react-dom': ^18.0.0 || ^19.0.0 - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@tinymce/tinymce-react@6.3.0': resolution: {integrity: sha512-E++xnn0XzDzpKr40jno2Kj7umfAE6XfINZULEBBeNjTMvbACWzA6CjiR6V8eTDc9yVmdVhIPqVzV4PqD5TZ/4g==} peerDependencies: @@ -4680,10 +3990,6 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - '@tootallnate/once@2.0.1': - resolution: {integrity: sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==} - engines: {node: '>= 10'} - '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} @@ -4778,9 +4084,6 @@ packages: '@types/amqplib@0.10.8': resolution: {integrity: sha512-vtDp8Pk1wsE/AuQ8/Rgtm6KUZYqcnTgNvEHwzCkX8rL7AGsC6zqAfKAAJhUZXFhM/Pp++tbnUHiam/8vVpPztA==} - '@types/aria-query@5.0.4': - resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} - '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -4835,10 +4138,6 @@ packages: '@types/d3-timer@3.0.2': resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} - '@types/dompurify@3.2.0': - resolution: {integrity: sha512-Fgg31wv9QbLDA0SpTOXO3MaxySc4DKGLi8sna4/Utjo4r3ZRPdCt4UQee8BWr+Q5z21yifghREPJGYaEOEIACg==} - deprecated: This is a stub types definition. dompurify provides its own type definitions, so you do not need this installed. - '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -4854,10 +4153,6 @@ packages: '@types/express@5.0.6': resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} - '@types/file-type@10.9.3': - resolution: {integrity: sha512-xTVEthISP8tJ3qWpWKmetPt/Amusrfr7KdMZgg33lGw2g0YpDmECZYqh1As37tbgiAXl28NU+XHjw806YfboTg==} - deprecated: This is a stub types definition. file-type provides its own type definitions, so you do not need this installed. - '@types/graceful-fs@4.1.9': resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} @@ -4881,18 +4176,9 @@ packages: '@types/jest@29.5.14': resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} - '@types/jquery@3.5.34': - resolution: {integrity: sha512-3m3939S3erqmTLJANS/uy0B6V7BorKx7RorcGZVjZ62dF5PAGbKEDZK1CuLtKombJkFA2T1jl8LAIIs7IV6gBQ==} - '@types/jquery@4.0.1': resolution: {integrity: sha512-9a59A/tycXgYuPABcp6/3spSShn0NT2UOM4EfHvMumjYi4lJWTsK5SZWjhx3yRm9IHGCeWXdV2YfNsrWrft/CA==} - '@types/js-cookie@3.0.6': - resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} - - '@types/jsdom@20.0.1': - resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} - '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -4987,9 +4273,6 @@ packages: '@types/signature_pad@2.3.6': resolution: {integrity: sha512-v3j92gCQJoxomHhd+yaG4Vsf8tRS/XbzWKqDv85UsqjMGy4zhokuwKe4b6vhbgncKkh+thF+gpz6+fypTtnFqQ==} - '@types/sizzle@2.3.10': - resolution: {integrity: sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww==} - '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -5005,9 +4288,6 @@ packages: '@types/tinymce@4.6.9': resolution: {integrity: sha512-pDxBUlV4v1jgJ97SlnVOSyf3KUy3OQ3s5Ddpfh1L9M5lXlBmX7TJ2OLSozx1WBxp91acHvYPWDwz2U/kMM1oxQ==} - '@types/tough-cookie@4.0.5': - resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -5037,14 +4317,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/eslint-plugin@8.61.0': - resolution: {integrity: sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.61.0 - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.60.1': resolution: {integrity: sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5052,45 +4324,22 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.61.0': - resolution: {integrity: sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.60.1': resolution: {integrity: sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.61.0': - resolution: {integrity: sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.60.1': resolution: {integrity: sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.61.0': - resolution: {integrity: sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.60.1': resolution: {integrity: sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/tsconfig-utils@8.61.0': - resolution: {integrity: sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.60.1': resolution: {integrity: sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5098,33 +4347,16 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.61.0': - resolution: {integrity: sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.60.1': resolution: {integrity: sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.61.0': - resolution: {integrity: sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.60.1': resolution: {integrity: sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/typescript-estree@8.61.0': - resolution: {integrity: sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.60.1': resolution: {integrity: sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5132,21 +4364,10 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.61.0': - resolution: {integrity: sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.60.1': resolution: {integrity: sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.61.0': - resolution: {integrity: sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@ungap/structured-clone@1.3.1': resolution: {integrity: sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==} @@ -5597,10 +4818,6 @@ packages: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true - abab@2.0.6: - resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} - deprecated: Use your platform's native atob() and btoa() methods instead - abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} @@ -5623,9 +4840,6 @@ packages: resolution: {integrity: sha512-GKp5tQ8h0KMPWIYGRHHXI1s5tUpZixZ3IHF2jAu42wSCf6In/G873s6/y4DdKdhWvzhu1T6mE1JgvnhAKqyYYQ==} deprecated: This is probably built in to whatever tool you're using. If you still need it... idk - acorn-globals@7.0.1: - resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} - acorn-import-phases@1.0.4: resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} engines: {node: '>=10.13.0'} @@ -5942,9 +5156,6 @@ packages: resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} engines: {node: '>=10'} - aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} @@ -6142,12 +5353,6 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} - babel-plugin-styled-components@2.3.0: - resolution: {integrity: sha512-nP/y6PbBqS/qtKROnJCgpGo8hYUzlBAVXN1QAjSBANL6vZiQXPQN7FYW/nUwoxY7nZhBEGm9T5tjL9gbzwulDw==} - peerDependencies: - '@babel/core': ^7.0.0 - styled-components: '>= 2' - babel-preset-current-node-syntax@1.2.0: resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} peerDependencies: @@ -6467,9 +5672,6 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - camelize@1.0.1: - resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} - caniuse-lite@1.0.30001797: resolution: {integrity: sha512-l8xKG+gwAIExZGl9FrF7KUwuOmk6wbEPC9Xoy/RtnWv1XG0Q4LFlagaLpUv3Kiza3W/wm27zy0yWJEieYKAP6w==} @@ -6904,19 +6106,12 @@ packages: css-box-model@1.2.1: resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==} - css-color-keywords@1.0.0: - resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} - engines: {node: '>=4'} - css-line-break@2.1.0: resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} - css-to-react-native@3.2.0: - resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} - css-tree@1.1.3: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} engines: {node: '>=8.0.0'} @@ -6925,24 +6120,11 @@ packages: resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} engines: {node: '>= 6'} - css.escape@1.5.1: - resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true - cssom@0.3.8: - resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} - - cssom@0.5.0: - resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} - - cssstyle@2.3.0: - resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} - engines: {node: '>=8'} - cssstyle@4.6.0: resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} engines: {node: '>=18'} @@ -7025,10 +6207,6 @@ packages: resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} engines: {node: '>= 14'} - data-urls@3.0.2: - resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} - engines: {node: '>=12'} - data-urls@5.0.0: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} @@ -7282,12 +6460,6 @@ packages: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} - dom-accessibility-api@0.5.16: - resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} - - dom-accessibility-api@0.6.3: - resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} @@ -7301,11 +6473,6 @@ packages: domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - domexception@4.0.0: - resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} - engines: {node: '>=12'} - deprecated: Use your platform's native DOMException instead - domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} @@ -7536,11 +6703,6 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} - hasBin: true - escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -7639,12 +6801,6 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - eslint-plugin-react-hooks@5.2.0: - resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - eslint-plugin-react-refresh@0.4.26: resolution: {integrity: sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==} peerDependencies: @@ -7664,18 +6820,10 @@ packages: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-scope@8.4.0: - resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.2.1: - resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-visitor-keys@5.0.1: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} @@ -7686,24 +6834,10 @@ packages: deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true - eslint@9.39.4: - resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - esniff@2.0.1: resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} engines: {node: '>=0.10'} - espree@10.4.0: - resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -7971,10 +7105,6 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - file-selector@2.1.2: resolution: {integrity: sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==} engines: {node: '>= 12'} @@ -8037,10 +7167,6 @@ packages: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - flat@5.0.2: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true @@ -8337,14 +7463,6 @@ packages: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - - globals@16.5.0: - resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} - engines: {node: '>=18'} - globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -8405,9 +7523,6 @@ packages: engines: {node: '>=6'} deprecated: this library is no longer supported - harmony-reflect@1.6.2: - resolution: {integrity: sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==} - has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -8518,10 +7633,6 @@ packages: hsl-to-rgb-for-reals@1.1.1: resolution: {integrity: sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==} - html-encoding-sniffer@3.0.0: - resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} - engines: {node: '>=12'} - html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} @@ -8557,10 +7668,6 @@ packages: http-parser-js@0.5.10: resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} - http-proxy-agent@5.0.0: - resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} - engines: {node: '>= 6'} - http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -8634,10 +7741,6 @@ packages: idb-keyval@6.2.5: resolution: {integrity: sha512-eKQkTnS0relYsSOYomx8ozIbmdsQCKUdhyuIaQ2DZgKuaxtyQQMkyD/wlnQN32pO3yutN1b1L8uqwcDKaJd7/Q==} - identity-obj-proxy@3.0.0: - resolution: {integrity: sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==} - engines: {node: '>=4'} - ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -8683,10 +7786,6 @@ packages: resolution: {integrity: sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==} engines: {node: '>=0.10.0'} - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -9183,15 +8282,6 @@ packages: resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-environment-jsdom@29.7.0: - resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - jest-environment-node@29.7.0: resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -9336,15 +8426,6 @@ packages: jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - jsdom@20.0.3: - resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} - engines: {node: '>=14'} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - jsdom@25.0.1: resolution: {integrity: sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==} engines: {node: '>=18'} @@ -9855,10 +8936,6 @@ packages: resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} engines: {node: '>=12'} - lz-string@1.5.0: - resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} - hasBin: true - magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} @@ -9885,19 +8962,6 @@ packages: makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - mantine-react-table@2.0.0-beta.9: - resolution: {integrity: sha512-ZdfcwebWaPERoDvAuk43VYcBCzamohARVclnbuepT0PHZ0wRcDPMBR+zgaocL+pFy8EXUGwvWTOKNh25ITpjNQ==} - engines: {node: '>=16'} - peerDependencies: - '@mantine/core': ^7.9 - '@mantine/dates': ^7.9 - '@mantine/hooks': ^7.9 - '@tabler/icons-react': '>=2.23.0' - clsx: '>=2' - dayjs: '>=1.11' - react: '>=18.0' - react-dom: '>=18.0' - map-cache@0.2.2: resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} engines: {node: '>=0.10.0'} @@ -10033,10 +9097,6 @@ packages: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} - min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -10710,9 +9770,6 @@ packages: resolution: {integrity: sha512-BT6eelPB1EyGHo8pC0o9Bl6k6SYVhKO1jEbd3lcTrtr7XHdjP8BW1YpfCV3G9Kwkxgattk+S5q2/RvuttCsS1g==} engines: {node: '>= 0.10'} - pdf-lib@1.17.1: - resolution: {integrity: sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==} - pdfjs-dist@2.16.105: resolution: {integrity: sha512-J4dn41spsAwUxCpEoVf6GVoz908IAA3mYiLmNxg8J9kfRXc2jxpbUepcP0ocp0alVNLFthTAM8DZ1RaHh8sU0A==} peerDependencies: @@ -10941,10 +9998,6 @@ packages: engines: {node: '>=14'} hasBin: true - pretty-format@27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -11161,24 +10214,12 @@ packages: peerDependencies: react: '>= 16.3.0' - react-css-nocode-editor@1.0.13: - resolution: {integrity: sha512-RV1ZbG8aXORiQ5mDKZbKCHStCJPamp/n5Rb34q22Ug2xzMDW4DjjqO23+Qo/Y+LAoyyrFV/+lI1qq4+/O5nf2A==} - peerDependencies: - react: '>=16.8.0 <= 18.1' - react-dom: '>=16.8.0 <= 18.1' - react-datepicker@8.10.0: resolution: {integrity: sha512-JIXuA+g+qP3c4MVJpx24o7n1gnv3WV/8A/D6964HucY1FlSEc30+ITPNUfbKZXYHl5rruCtxYCwi2lzn7gaz7g==} peerDependencies: react: ^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc - react-day-picker@8.10.2: - resolution: {integrity: sha512-LK68OTbHB3oJNhl9cA0qVizzp3o26w61YSjAFkYi67N86iro32wx86kSNeFU/hq+gI8m1yzWhnomMLfZ041RzQ==} - peerDependencies: - date-fns: ^2.28.0 || ^3.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-day-picker@9.14.0: resolution: {integrity: sha512-tBaoDWjPwe0M5pGrum4H0SR6Lyk+BO9oHnp9JbKpGKW2mlraNPgP9BMfsg5pWpwrssARmeqk7YBl2oXutZTaHA==} engines: {node: '>=18'} @@ -11269,9 +10310,6 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - react-is@17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -11517,10 +10555,6 @@ packages: resolution: {integrity: sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==} engines: {node: '>=0.10.0'} - redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - redux-thunk@3.1.0: resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==} peerDependencies: @@ -11559,9 +10593,6 @@ packages: engines: {node: '>= 0.10.0'} hasBin: true - remove-accents@0.5.0: - resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} - remove-trailing-separator@1.1.0: resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} @@ -11693,19 +10724,6 @@ packages: resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} engines: {node: '>= 0.8'} - rollup-plugin-visualizer@7.0.1: - resolution: {integrity: sha512-UJUT4+1Ho4OcWmPYU3sYXgUqI8B8Ayfe06MX7y0qCJ1K8aGoKtR/NDd/2nZqM7ADkrzny+I99Ul7GgyoiVNAgg==} - engines: {node: '>=22'} - hasBin: true - peerDependencies: - rolldown: 1.x || ^1.0.0-beta || ^1.0.0-rc - rollup: 2.x || 3.x || 4.x - peerDependenciesMeta: - rolldown: - optional: true - rollup: - optional: true - rollup@4.61.1: resolution: {integrity: sha512-I4KW6iuRpuu2uHBLraZ1wNZe0DP7lnRha+VJ9tNaYVaVgKhW0aI3h4RYnoRPeql0flHm/Co55b7snEDcOfOJrA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -11886,9 +10904,6 @@ packages: resolution: {integrity: sha512-84IJhUsK0xqSCRJx3QxyZe2NpUXj2Nwk8Vc8Ow/tCOND3yz4CT6uU4655vqicNXhzG9Q1cyUt+TBl2SiCJwNgg==} hasBin: true - shallowequal@1.1.0: - resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} @@ -12254,10 +11269,6 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -12279,14 +11290,6 @@ packages: style-object-to-css-string@1.1.3: resolution: {integrity: sha512-bISQoUsir/qGfo7vY8rw00ia9nnyE1jvYt3zZ2jhdkcXZ6dAEi74inMzQ6On57vFI+I4Fck6wOv5UI9BEwJDgw==} - styled-components@5.3.11: - resolution: {integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==} - engines: {node: '>=10'} - peerDependencies: - react: '>= 16.8.0' - react-dom: '>= 16.8.0' - react-is: '>= 16.8.0' - styled-jsx@5.1.1: resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} engines: {node: '>= 12.0.0'} @@ -12621,10 +11624,6 @@ packages: resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} engines: {node: '>=0.8'} - tough-cookie@4.1.4: - resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} - engines: {node: '>=6'} - tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} @@ -12636,10 +11635,6 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tr46@3.0.0: - resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} - engines: {node: '>=12'} - tr46@5.1.1: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} @@ -12735,9 +11730,6 @@ packages: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} - tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -12881,18 +11873,6 @@ packages: typeorm-aurora-data-api-driver: optional: true - typescript-eslint@8.61.0: - resolution: {integrity: sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - - typescript@5.8.3: - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} - engines: {node: '>=14.17'} - hasBin: true - typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -12956,10 +11936,6 @@ packages: universal-cookie@8.1.2: resolution: {integrity: sha512-kcKzTGNsxVytujrYOvQbvh//QyFrA53HrzCGyzh6i9ujCww5gfPrLK0tG+jJD40SIIldiEjBNPPSR8fBMS21GA==} - universalify@0.2.0: - resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} - engines: {node: '>= 4.0.0'} - universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -13181,46 +12157,6 @@ packages: terser: optional: true - vite@6.4.3: - resolution: {integrity: sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - jiti: '>=1.21.0' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - vitest@2.1.9: resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==} engines: {node: ^18.0.0 || >=20.0.0} @@ -13256,10 +12192,6 @@ packages: w3c-keyname@2.2.8: resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} - w3c-xmlserializer@4.0.0: - resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} - engines: {node: '>=14'} - w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -13369,28 +12301,15 @@ packages: resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} engines: {node: '>=0.8.0'} - whatwg-encoding@2.0.0: - resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} - engines: {node: '>=12'} - deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation - whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation - whatwg-mimetype@3.0.0: - resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} - engines: {node: '>=12'} - whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} - whatwg-url@11.0.0: - resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} - engines: {node: '>=12'} - whatwg-url@14.2.0: resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} @@ -13534,10 +12453,6 @@ packages: engines: {node: '>=0.8'} hasBin: true - xml-name-validator@4.0.0: - resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} - engines: {node: '>=12'} - xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -13703,8 +12618,6 @@ packages: snapshots: - '@adobe/css-tools@4.5.0': {} - '@alloc/quick-lru@5.2.0': {} '@angular-devkit/core@19.2.24(chokidar@4.0.3)': @@ -13897,13 +12810,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-imports@7.29.7(supports-color@5.5.0)': - dependencies: - '@babel/traverse': 7.29.7(supports-color@5.5.0) - '@babel/types': 7.29.7 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -14095,18 +13001,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/traverse@7.29.7(supports-color@5.5.0)': - dependencies: - '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 - '@babel/helper-globals': 7.29.7 - '@babel/parser': 7.29.7 - '@babel/template': 7.29.7 - '@babel/types': 7.29.7 - debug: 4.4.3(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - '@babel/types@7.29.7': dependencies: '@babel/helper-string-parser': 7.29.7 @@ -14334,22 +13228,6 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@emotion/babel-plugin': 11.13.5 - '@emotion/cache': 11.14.0 - '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1) - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.4.0 - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.31 - transitivePeerDependencies: - - supports-color - '@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -14376,21 +13254,6 @@ snapshots: '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@emotion/babel-plugin': 11.13.5 - '@emotion/is-prop-valid': 1.4.0 - '@emotion/react': 11.14.0(@types/react@18.3.31)(react@18.3.1) - '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1) - '@emotion/utils': 1.4.2 - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.31 - transitivePeerDependencies: - - supports-color - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -14406,16 +13269,8 @@ snapshots: transitivePeerDependencies: - supports-color - '@emotion/stylis@0.8.5': {} - '@emotion/unitless@0.10.0': {} - '@emotion/unitless@0.7.5': {} - - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@18.3.1)': - dependencies: - react: 18.3.1 - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.6)': dependencies: react: 19.2.6 @@ -14427,178 +13282,79 @@ snapshots: '@esbuild/aix-ppc64@0.21.5': optional: true - '@esbuild/aix-ppc64@0.25.12': - optional: true - '@esbuild/android-arm64@0.21.5': optional: true - '@esbuild/android-arm64@0.25.12': - optional: true - '@esbuild/android-arm@0.21.5': optional: true - '@esbuild/android-arm@0.25.12': - optional: true - '@esbuild/android-x64@0.21.5': optional: true - '@esbuild/android-x64@0.25.12': - optional: true - '@esbuild/darwin-arm64@0.21.5': optional: true - '@esbuild/darwin-arm64@0.25.12': - optional: true - '@esbuild/darwin-x64@0.21.5': optional: true - '@esbuild/darwin-x64@0.25.12': - optional: true - '@esbuild/freebsd-arm64@0.21.5': optional: true - '@esbuild/freebsd-arm64@0.25.12': - optional: true - '@esbuild/freebsd-x64@0.21.5': optional: true - '@esbuild/freebsd-x64@0.25.12': - optional: true - '@esbuild/linux-arm64@0.21.5': optional: true - '@esbuild/linux-arm64@0.25.12': - optional: true - '@esbuild/linux-arm@0.21.5': optional: true - '@esbuild/linux-arm@0.25.12': - optional: true - '@esbuild/linux-ia32@0.21.5': optional: true - '@esbuild/linux-ia32@0.25.12': - optional: true - '@esbuild/linux-loong64@0.21.5': optional: true - '@esbuild/linux-loong64@0.25.12': - optional: true - '@esbuild/linux-mips64el@0.21.5': optional: true - '@esbuild/linux-mips64el@0.25.12': - optional: true - '@esbuild/linux-ppc64@0.21.5': optional: true - '@esbuild/linux-ppc64@0.25.12': - optional: true - '@esbuild/linux-riscv64@0.21.5': optional: true - '@esbuild/linux-riscv64@0.25.12': - optional: true - '@esbuild/linux-s390x@0.21.5': optional: true - '@esbuild/linux-s390x@0.25.12': - optional: true - '@esbuild/linux-x64@0.21.5': optional: true - '@esbuild/linux-x64@0.25.12': - optional: true - - '@esbuild/netbsd-arm64@0.25.12': - optional: true - '@esbuild/netbsd-x64@0.21.5': optional: true - '@esbuild/netbsd-x64@0.25.12': - optional: true - - '@esbuild/openbsd-arm64@0.25.12': - optional: true - '@esbuild/openbsd-x64@0.21.5': optional: true - '@esbuild/openbsd-x64@0.25.12': - optional: true - - '@esbuild/openharmony-arm64@0.25.12': - optional: true - '@esbuild/sunos-x64@0.21.5': optional: true - '@esbuild/sunos-x64@0.25.12': - optional: true - '@esbuild/win32-arm64@0.21.5': optional: true - '@esbuild/win32-arm64@0.25.12': - optional: true - '@esbuild/win32-ia32@0.21.5': optional: true - '@esbuild/win32-ia32@0.25.12': - optional: true - '@esbuild/win32-x64@0.21.5': optional: true - '@esbuild/win32-x64@0.25.12': - optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@8.57.1)': dependencies: eslint: 8.57.1 eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.7.0))': - dependencies: - eslint: 9.39.4(jiti@2.7.0) - eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.21.2': - dependencies: - '@eslint/object-schema': 2.1.7 - debug: 4.4.3(supports-color@5.5.0) - minimatch: 3.1.5 - transitivePeerDependencies: - - supports-color - - '@eslint/config-helpers@0.4.2': - dependencies: - '@eslint/core': 0.17.0 - - '@eslint/core@0.17.0': - dependencies: - '@types/json-schema': 7.0.15 - '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.15.0 @@ -14613,31 +13369,8 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/eslintrc@3.3.5': - dependencies: - ajv: 6.15.0 - debug: 4.4.3(supports-color@5.5.0) - espree: 10.4.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.2.0 - minimatch: 3.1.5 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - '@eslint/js@8.57.1': {} - '@eslint/js@9.39.4': {} - - '@eslint/object-schema@2.1.7': {} - - '@eslint/plugin-kit@0.4.1': - dependencies: - '@eslint/core': 0.17.0 - levn: 0.4.1 - '@faker-js/faker@10.4.0': {} '@fast-csv/format@4.3.5': @@ -14680,14 +13413,6 @@ snapshots: react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - '@floating-ui/react@0.26.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@floating-ui/react-dom': 2.1.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@floating-ui/utils': 0.2.11 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - tabbable: 6.4.0 - '@floating-ui/react@0.27.19(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@floating-ui/react-dom': 2.1.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -14738,28 +13463,11 @@ snapshots: dependencies: react-hook-form: 7.77.0(react@18.3.1) - '@hookform/resolvers@5.4.0(react-hook-form@7.77.0(react@18.3.1))': - dependencies: - '@standard-schema/utils': 0.3.0 - react-hook-form: 7.77.0(react@18.3.1) - '@hookform/resolvers@5.4.0(react-hook-form@7.77.0(react@19.2.6))': dependencies: '@standard-schema/utils': 0.3.0 react-hook-form: 7.77.0(react@19.2.6) - '@humanfs/core@0.19.2': - dependencies: - '@humanfs/types': 0.15.0 - - '@humanfs/node@0.16.8': - dependencies: - '@humanfs/core': 0.19.2 - '@humanfs/types': 0.15.0 - '@humanwhocodes/retry': 0.4.3 - - '@humanfs/types@0.15.0': {} - '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -14772,8 +13480,6 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} - '@humanwhocodes/retry@0.4.3': {} - '@inquirer/ansi@1.0.2': {} '@inquirer/ansi@2.0.7': {} @@ -15012,41 +13718,6 @@ snapshots: - supports-color - ts-node - '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3))': - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.19.42 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.19.42)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - '@jest/environment@29.7.0': dependencies: '@jest/fake-timers': 29.7.0 @@ -15196,11 +13867,6 @@ snapshots: '@leichtgewicht/ip-codec@2.0.5': {} - '@lottiefiles/react-lottie-player@3.6.0(react@18.3.1)': - dependencies: - lottie-web: 5.13.0 - react: 18.3.1 - '@lottiefiles/react-lottie-player@3.6.0(react@19.2.6)': dependencies: lottie-web: 5.13.0 @@ -15208,28 +13874,6 @@ snapshots: '@lukeed/csprng@1.1.0': {} - '@mantine/charts@7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(recharts@3.8.1(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1)(redux@5.0.1))': - dependencies: - '@mantine/core': 7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mantine/hooks': 7.17.8(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - recharts: 3.8.1(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1)(redux@5.0.1) - - '@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@floating-ui/react': 0.26.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mantine/hooks': 7.17.8(react@18.3.1) - clsx: 2.1.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-number-format: 5.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-remove-scroll: 2.7.2(@types/react@18.3.31)(react@18.3.1) - react-textarea-autosize: 8.5.9(@types/react@18.3.31)(react@18.3.1) - type-fest: 4.41.0 - transitivePeerDependencies: - - '@types/react' - '@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@floating-ui/react': 0.27.19(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -15257,15 +13901,6 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@mantine/dates@7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(dayjs@1.11.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@mantine/core': 7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mantine/hooks': 7.17.8(react@18.3.1) - clsx: 2.1.1 - dayjs: 1.11.21 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - '@mantine/dates@8.3.18(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@8.3.18(react@19.2.6))(dayjs@1.11.21)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@mantine/core': 8.3.18(@mantine/hooks@8.3.18(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -15275,10 +13910,6 @@ snapshots: react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - '@mantine/hooks@7.17.8(react@18.3.1)': - dependencies: - react: 18.3.1 - '@mantine/hooks@8.3.18(react@19.2.6)': dependencies: react: 19.2.6 @@ -15287,19 +13918,6 @@ snapshots: dependencies: react: 19.2.6 - '@mantine/notifications@7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@mantine/core': 7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mantine/hooks': 7.17.8(react@18.3.1) - '@mantine/store': 7.17.8(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - - '@mantine/store@7.17.8(react@18.3.1)': - dependencies: - react: 18.3.1 - '@mapbox/node-pre-gyp@1.0.11': dependencies: detect-libc: 2.1.2 @@ -15350,20 +13968,6 @@ snapshots: outvariant: 1.4.3 strict-event-emitter: 0.5.1 - '@mui/base@5.0.0-beta.70(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@floating-ui/react-dom': 2.1.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mui/types': 7.2.24(@types/react@18.3.31) - '@mui/utils': 6.4.9(@types/react@18.3.31)(react@18.3.1) - '@popperjs/core': 2.11.8 - clsx: 2.1.1 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.31 - '@mui/base@5.0.0-beta.70(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -15380,14 +13984,6 @@ snapshots: '@mui/core-downloads-tracker@5.18.0': {} - '@mui/icons-material@5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.31)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@mui/material': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.31 - '@mui/icons-material@5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@types/react@18.3.31)(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -15396,27 +13992,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - '@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@mui/core-downloads-tracker': 5.18.0 - '@mui/system': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1) - '@mui/types': 7.2.24(@types/react@18.3.31) - '@mui/utils': 5.17.1(@types/react@18.3.31)(react@18.3.1) - '@popperjs/core': 2.11.8 - '@types/react-transition-group': 4.4.12(@types/react@18.3.31) - clsx: 2.1.1 - csstype: 3.2.3 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-is: 19.2.7 - react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - optionalDependencies: - '@emotion/react': 11.14.0(@types/react@18.3.31)(react@18.3.1) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1) - '@types/react': 18.3.31 - '@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -15438,15 +14013,6 @@ snapshots: '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) '@types/react': 18.3.31 - '@mui/private-theming@5.17.1(@types/react@18.3.31)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@mui/utils': 5.17.1(@types/react@18.3.31)(react@18.3.1) - prop-types: 15.8.1 - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.31 - '@mui/private-theming@5.17.1(@types/react@18.3.31)(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -15456,18 +14022,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - '@mui/styled-engine@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@emotion/cache': 11.14.0 - '@emotion/serialize': 1.3.3 - csstype: 3.2.3 - prop-types: 15.8.1 - react: 18.3.1 - optionalDependencies: - '@emotion/react': 11.14.0(@types/react@18.3.31)(react@18.3.1) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1) - '@mui/styled-engine@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -15480,22 +14034,6 @@ snapshots: '@emotion/react': 11.14.0(@types/react@18.3.31)(react@19.2.6) '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) - '@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@mui/private-theming': 5.17.1(@types/react@18.3.31)(react@18.3.1) - '@mui/styled-engine': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(react@18.3.1) - '@mui/types': 7.2.24(@types/react@18.3.31) - '@mui/utils': 5.17.1(@types/react@18.3.31)(react@18.3.1) - clsx: 2.1.1 - csstype: 3.2.3 - prop-types: 15.8.1 - react: 18.3.1 - optionalDependencies: - '@emotion/react': 11.14.0(@types/react@18.3.31)(react@18.3.1) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1) - '@types/react': 18.3.31 - '@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -15516,18 +14054,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - '@mui/utils@5.17.1(@types/react@18.3.31)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@mui/types': 7.2.24(@types/react@18.3.31) - '@types/prop-types': 15.7.15 - clsx: 2.1.1 - prop-types: 15.8.1 - react: 18.3.1 - react-is: 19.2.7 - optionalDependencies: - '@types/react': 18.3.31 - '@mui/utils@5.17.1(@types/react@18.3.31)(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -15540,18 +14066,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - '@mui/utils@6.4.9(@types/react@18.3.31)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@mui/types': 7.2.24(@types/react@18.3.31) - '@types/prop-types': 15.7.15 - clsx: 2.1.1 - prop-types: 15.8.1 - react: 18.3.1 - react-is: 19.2.7 - optionalDependencies: - '@types/react': 18.3.31 - '@mui/utils@6.4.9(@types/react@18.3.31)(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -15564,29 +14078,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - '@mui/x-date-pickers@6.20.2(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(date-fns@3.6.0)(dayjs@1.11.21)(luxon@3.7.2)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@mui/base': 5.0.0-beta.70(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mui/material': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mui/system': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1) - '@mui/utils': 5.17.1(@types/react@18.3.31)(react@18.3.1) - '@types/react-transition-group': 4.4.12(@types/react@18.3.31) - clsx: 2.1.1 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - optionalDependencies: - '@emotion/react': 11.14.0(@types/react@18.3.31)(react@18.3.1) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1) - date-fns: 3.6.0 - dayjs: 1.11.21 - luxon: 3.7.2 - moment: 2.30.1 - transitivePeerDependencies: - - '@types/react' - '@mui/x-date-pickers@6.20.2(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(date-fns@3.6.0)(dayjs@1.11.21)(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -15610,6 +14101,29 @@ snapshots: transitivePeerDependencies: - '@types/react' + '@mui/x-date-pickers@6.20.2(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(date-fns@4.4.0)(dayjs@1.11.21)(luxon@3.7.2)(moment@2.30.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + dependencies: + '@babel/runtime': 7.29.7 + '@mui/base': 5.0.0-beta.70(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@mui/material': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@mui/system': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) + '@mui/utils': 5.17.1(@types/react@18.3.31)(react@19.2.6) + '@types/react-transition-group': 4.4.12(@types/react@18.3.31) + clsx: 2.1.1 + prop-types: 15.8.1 + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + react-transition-group: 4.4.5(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + optionalDependencies: + '@emotion/react': 11.14.0(@types/react@18.3.31)(react@19.2.6) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) + date-fns: 4.4.0 + dayjs: 1.11.21 + luxon: 3.7.2 + moment: 2.30.1 + transitivePeerDependencies: + - '@types/react' + '@napi-rs/canvas-android-arm64@0.1.100': optional: true @@ -16019,14 +14533,6 @@ snapshots: '@parcel/watcher-win32-ia32': 2.5.6 '@parcel/watcher-win32-x64': 2.5.6 - '@pdf-lib/standard-fonts@1.0.0': - dependencies: - pako: 1.0.11 - - '@pdf-lib/upng@1.0.1': - dependencies: - pako: 1.0.11 - '@phc/format@1.0.0': {} '@pkgjs/parseargs@0.11.0': @@ -17568,14 +16074,6 @@ snapshots: '@radix-ui/rect@1.1.2': {} - '@react-pdf-viewer/attachment@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/attachment@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17584,14 +16082,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/bookmark@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/bookmark@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17600,30 +16090,12 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/core@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - pdfjs-dist: 5.4.296 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - '@react-pdf-viewer/core@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: pdfjs-dist: 5.4.296 react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - '@react-pdf-viewer/default-layout@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/attachment': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/bookmark': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/thumbnail': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/toolbar': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/default-layout@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/attachment': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17636,14 +16108,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/full-screen@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/full-screen@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17652,14 +16116,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/get-file@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/get-file@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17668,14 +16124,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/open@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/open@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17684,14 +16132,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/page-navigation@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/page-navigation@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17700,14 +16140,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/print@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/print@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17716,14 +16148,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/properties@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/properties@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17732,14 +16156,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/rotate@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/rotate@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17748,14 +16164,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/scroll-mode@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/scroll-mode@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17764,14 +16172,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/search@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/search@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17780,14 +16180,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/selection-mode@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/selection-mode@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17796,14 +16188,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/theme@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/theme@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17812,14 +16196,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/thumbnail@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/thumbnail@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17828,26 +16204,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/toolbar@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/full-screen': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/get-file': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/open': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/page-navigation': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/print': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/properties': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/rotate': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/scroll-mode': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/search': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/selection-mode': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/theme': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-pdf-viewer/zoom': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/toolbar@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17868,14 +16224,6 @@ snapshots: transitivePeerDependencies: - pdfjs-dist - '@react-pdf-viewer/zoom@3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - pdfjs-dist - '@react-pdf-viewer/zoom@3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -17926,12 +16274,6 @@ snapshots: '@react-pdf/primitives@4.3.0': {} - '@react-pdf/reconciler@2.0.0(react@18.3.1)': - dependencies: - object-assign: 4.1.1 - react: 18.3.1 - scheduler: 0.25.0-rc-603e6108-20241029 - '@react-pdf/reconciler@2.0.0(react@19.2.6)': dependencies: object-assign: 4.1.1 @@ -17951,23 +16293,6 @@ snapshots: parse-svg-path: 0.1.2 svg-arc-to-cubic-bezier: 3.2.0 - '@react-pdf/renderer@4.5.1(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@react-pdf/fns': 3.1.3 - '@react-pdf/font': 4.0.8 - '@react-pdf/layout': 4.6.1 - '@react-pdf/pdfkit': 5.1.1 - '@react-pdf/primitives': 4.3.0 - '@react-pdf/reconciler': 2.0.0(react@18.3.1) - '@react-pdf/render': 4.5.1 - '@react-pdf/types': 2.11.1 - events: 3.3.0 - object-assign: 4.1.1 - prop-types: 15.8.1 - queue: 6.0.2 - react: 18.3.1 - '@react-pdf/renderer@4.5.1(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -18011,18 +16336,6 @@ snapshots: '@react-pdf/primitives': 4.3.0 '@react-pdf/stylesheet': 6.2.1 - '@reduxjs/toolkit@2.12.0(react-redux@9.3.0(@types/react@18.3.31)(react@18.3.1)(redux@5.0.1))(react@18.3.1)': - dependencies: - '@standard-schema/spec': 1.1.0 - '@standard-schema/utils': 0.3.0 - immer: 11.1.8 - redux: 5.0.1 - redux-thunk: 3.1.0(redux@5.0.1) - reselect: 5.2.0 - optionalDependencies: - react: 18.3.1 - react-redux: 9.3.0(@types/react@18.3.31)(react@18.3.1)(redux@5.0.1) - '@reduxjs/toolkit@2.12.0(react-redux@9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1))(react@19.2.6)': dependencies: '@standard-schema/spec': 1.1.0 @@ -18175,11 +16488,6 @@ snapshots: '@tabby_ai/hijri-converter@1.0.5': {} - '@tabler/icons-react@3.44.0(react@18.3.1)': - dependencies: - '@tabler/icons': 3.44.0 - react: 18.3.1 - '@tabler/icons-react@3.44.0(react@19.2.6)': dependencies: '@tabler/icons': 3.44.0 @@ -18265,27 +16573,10 @@ snapshots: tailwindcss: 4.3.0 vite: 5.4.21(@types/node@24.13.1)(lightningcss@1.32.0)(terser@5.48.0) - '@tailwindcss/vite@4.3.0(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)(yaml@2.9.0))': - dependencies: - '@tailwindcss/node': 4.3.0 - '@tailwindcss/oxide': 4.3.0 - tailwindcss: 4.3.0 - vite: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)(yaml@2.9.0) - - '@tanstack/match-sorter-utils@8.19.4': - dependencies: - remove-accents: 0.5.0 - '@tanstack/query-core@5.101.0': {} '@tanstack/query-devtools@5.101.0': {} - '@tanstack/react-query-devtools@5.101.0(@tanstack/react-query@5.101.0(react@18.3.1))(react@18.3.1)': - dependencies: - '@tanstack/query-devtools': 5.101.0 - '@tanstack/react-query': 5.101.0(react@18.3.1) - react: 18.3.1 - '@tanstack/react-query-devtools@5.101.0(@tanstack/react-query@5.101.0(react@19.2.6))(react@19.2.6)': dependencies: '@tanstack/query-devtools': 5.101.0 @@ -18302,12 +16593,6 @@ snapshots: '@tanstack/query-core': 5.101.0 react: 19.2.6 - '@tanstack/react-table@8.20.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@tanstack/table-core': 8.20.5 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - '@tanstack/react-table@8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@tanstack/table-core': 8.21.3 @@ -18320,56 +16605,8 @@ snapshots: react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - '@tanstack/react-virtual@3.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@tanstack/virtual-core': 3.11.2 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - '@tanstack/table-core@8.20.5': {} - '@tanstack/table-core@8.21.3': {} - '@tanstack/virtual-core@3.11.2': {} - - '@testing-library/dom@10.4.1': - dependencies: - '@babel/code-frame': 7.29.7 - '@babel/runtime': 7.29.7 - '@types/aria-query': 5.0.4 - aria-query: 5.3.0 - dom-accessibility-api: 0.5.16 - lz-string: 1.5.0 - picocolors: 1.1.1 - pretty-format: 27.5.1 - - '@testing-library/jest-dom@6.9.1': - dependencies: - '@adobe/css-tools': 4.5.0 - aria-query: 5.3.2 - css.escape: 1.5.1 - dom-accessibility-api: 0.6.3 - picocolors: 1.1.1 - redent: 3.0.0 - - '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.29.7 - '@testing-library/dom': 10.4.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.31 - '@types/react-dom': 18.3.7(@types/react@18.3.31) - - '@tinymce/tinymce-react@6.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tinymce@7.9.3)': - dependencies: - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - tinymce: 7.9.3 - '@tinymce/tinymce-react@6.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(tinymce@7.9.3)': dependencies: prop-types: 15.8.1 @@ -18579,8 +16816,6 @@ snapshots: '@tokenizer/token@0.3.0': {} - '@tootallnate/once@2.0.1': {} - '@tootallnate/quickjs-emscripten@0.23.0': {} '@tria-plc/api-common@1.4.3(8585e1bb20832aa29a6196252fda5dd7)': @@ -18801,6 +17036,146 @@ snapshots: - webpack-command - worker-loader + '@tria-plc/iamui-common@1.1.2(9eda5000a9f7ac3b614e21a2a3a3f1e2)': + dependencies: + '@chakra-ui/react': 3.35.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@emotion/react': 11.14.0(@types/react@18.3.31)(react@19.2.6) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@19.2.6))(@types/react@18.3.31)(react@19.2.6) + '@hookform/resolvers': 5.4.0(react-hook-form@7.77.0(react@19.2.6)) + '@lottiefiles/react-lottie-player': 3.6.0(react@19.2.6) + '@mantine/core': 8.3.18(@mantine/hooks@8.3.18(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@mantine/dates': 8.3.18(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@19.2.6))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(@mantine/hooks@8.3.18(react@19.2.6))(dayjs@1.11.21)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@mantine/hooks': 8.3.18(react@19.2.6) + '@onlyoffice/document-editor-react': 2.2.0(@onlyoffice/doceditor-types@9.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-accordion': 1.2.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-alert-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-avatar': 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-checkbox': 1.3.4(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-collapsible': 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-context-menu': 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-dropdown-menu': 2.1.17(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-hover-card': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-label': 2.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-navigation-menu': 1.2.15(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-popover': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-progress': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-radio-group': 1.4.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-scroll-area': 1.2.11(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-select': 2.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-separator': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-slider': 1.4.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-slot': 1.2.5(@types/react@18.3.31)(react@19.2.6) + '@radix-ui/react-switch': 1.3.0(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-tabs': 1.1.14(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-toast': 1.2.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-toggle-group': 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-tooltip': 1.2.9(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@react-pdf-viewer/core': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@react-pdf-viewer/default-layout': 3.12.0(pdfjs-dist@5.4.296)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@react-pdf/renderer': 4.5.1(react@19.2.6) + '@reduxjs/toolkit': 2.12.0(react-redux@9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1))(react@19.2.6) + '@tabler/icons-react': 3.44.0(react@19.2.6) + '@tailwindcss/vite': 4.3.0(vite@5.4.21(@types/node@24.13.1)(lightningcss@1.32.0)(terser@5.48.0)) + '@tanstack/react-query': 5.101.0(react@19.2.6) + '@tanstack/react-query-devtools': 5.101.0(@tanstack/react-query@5.101.0(react@19.2.6))(react@19.2.6) + '@tanstack/react-table': 8.21.3(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@tinymce/tinymce-react': 6.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(tinymce@7.9.3) + '@tiptap/extension-color': 3.26.0(@tiptap/extension-text-style@3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0))) + '@tiptap/extension-highlight': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0)) + '@tiptap/extension-image': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0)) + '@tiptap/extension-link': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0))(@tiptap/pm@3.26.0) + '@tiptap/extension-text-align': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0)) + '@tiptap/extension-text-style': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0)) + '@tiptap/extension-underline': 3.26.0(@tiptap/core@3.26.0(@tiptap/pm@3.26.0)) + '@tiptap/react': 3.26.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.26.0(@tiptap/pm@3.26.0))(@tiptap/pm@3.26.0)(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@tiptap/starter-kit': 3.26.0 + '@types/node': 24.13.1 + '@types/tinymce': 4.6.9 + axios: 1.17.0 + class-variance-authority: 0.7.1 + clsx: 2.1.1 + cmdk: 1.1.1(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + date-fns: 4.4.0 + dayjs: 1.11.21 + ethiopian-calendar-date-converter: 2.1.6 + ethiopian-calendar-new: 1.1.0 + file-type: 18.7.0 + force: 0.0.3 + framer-motion: 12.40.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + html2canvas: 1.4.1 + i18next: 25.10.10(typescript@5.9.3) + i18next-browser-languagedetector: 8.2.1 + jquery: 3.7.1 + js-cookie: 3.0.8 + jspdf: 3.0.4 + loadash: 1.0.0 + lodash: 4.18.1 + lucide-react: 0.513.0(react@19.2.6) + mui-ethiopian-datepicker: 0.3.2(7d86988bc4fd0020aebaf3d4b373b1a0) + next-themes: 0.4.6(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + path: 0.12.7 + qs: 6.15.2 + react: 19.2.6 + react-cookie: 8.1.2(@types/react@18.3.31)(react@19.2.6) + react-datepicker: 8.10.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react-day-picker: 9.14.0(react@19.2.6) + react-dom: 19.2.6(react@19.2.6) + react-dropzone: 14.4.1(react@19.2.6) + react-hook-form: 7.77.0(react@19.2.6) + react-i18next: 15.7.4(i18next@25.10.10(typescript@5.9.3))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3) + react-icons: 5.6.0(react@19.2.6) + react-image-crop: 11.0.10(react@19.2.6) + react-intersection-observer: 9.16.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react-is: 19.2.7 + react-joyride: 2.9.3(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react-pdf: 10.4.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react-pdf-html: 2.1.5(@react-pdf/renderer@4.5.1(react@19.2.6))(react@19.2.6) + react-pdf-viewer: 0.1.0 + react-redux: 9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1) + react-resizable-panels: 3.0.6(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react-router-dom: 7.17.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react-signature-canvas: 1.1.0-alpha.2(@types/prop-types@15.7.15)(@types/react@18.3.31)(prop-types@15.8.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + recharts: 3.8.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6)(redux@5.0.1) + socket.io-client: 4.8.3 + sonner: 2.0.7(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + tailwind-merge: 3.6.0 + tailwind-scrollbar-hide: 4.0.0(tailwindcss@4.3.0) + tailwindcss: 4.3.0 + tailwindcss-animate: 1.0.7(tailwindcss@4.3.0) + tesseract.js: 7.0.0 + tinymce: 7.9.3 + url: 0.11.4 + vaul: 1.1.2(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + xlsx: 0.18.5 + zod: 3.25.76 + transitivePeerDependencies: + - '@emotion/is-prop-valid' + - '@floating-ui/dom' + - '@mui/icons-material' + - '@mui/material' + - '@mui/x-date-pickers' + - '@onlyoffice/doceditor-types' + - '@tiptap/core' + - '@tiptap/pm' + - '@types/prop-types' + - '@types/react' + - '@types/react-dom' + - bufferutil + - debug + - encoding + - pdfjs-dist + - prop-types + - react-native + - redux + - supports-color + - typescript + - utf-8-validate + - vite + - webpack-cli + - webpack-command + - worker-loader + '@ts-morph/common@0.27.0': dependencies: fast-glob: 3.3.3 @@ -18842,8 +17217,6 @@ snapshots: dependencies: '@types/node': 20.19.42 - '@types/aria-query@5.0.4': {} - '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.29.7 @@ -18908,10 +17281,6 @@ snapshots: '@types/d3-timer@3.0.2': {} - '@types/dompurify@3.2.0': - dependencies: - dompurify: 3.4.8 - '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 @@ -18937,10 +17306,6 @@ snapshots: '@types/express-serve-static-core': 5.1.1 '@types/serve-static': 2.2.0 - '@types/file-type@10.9.3': - dependencies: - file-type: 18.7.0 - '@types/graceful-fs@4.1.9': dependencies: '@types/node': 20.19.42 @@ -18967,20 +17332,8 @@ snapshots: expect: 29.7.0 pretty-format: 29.7.0 - '@types/jquery@3.5.34': - dependencies: - '@types/sizzle': 2.3.10 - '@types/jquery@4.0.1': {} - '@types/js-cookie@3.0.6': {} - - '@types/jsdom@20.0.1': - dependencies: - '@types/node': 20.19.42 - '@types/tough-cookie': 4.0.5 - parse5: 7.3.0 - '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} @@ -19081,8 +17434,6 @@ snapshots: '@types/signature_pad@2.3.6': {} - '@types/sizzle@2.3.10': {} - '@types/stack-utils@2.0.3': {} '@types/statuses@2.0.6': {} @@ -19103,8 +17454,6 @@ snapshots: dependencies: '@types/jquery': 4.0.1 - '@types/tough-cookie@4.0.5': {} - '@types/trusted-types@2.0.7': optional: true @@ -19141,22 +17490,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@8.61.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3) - '@typescript-eslint/scope-manager': 8.61.0 - '@typescript-eslint/type-utils': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3) - '@typescript-eslint/utils': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.61.0 - eslint: 9.39.4(jiti@2.7.0) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@5.8.3) - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/parser@8.60.1(eslint@8.57.1)(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.60.1 @@ -19169,18 +17502,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.61.0 - '@typescript-eslint/types': 8.61.0 - '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.61.0 - debug: 4.4.3(supports-color@5.5.0) - eslint: 9.39.4(jiti@2.7.0) - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/project-service@8.60.1(typescript@5.9.3)': dependencies: '@typescript-eslint/tsconfig-utils': 8.60.1(typescript@5.9.3) @@ -19190,33 +17511,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.61.0(typescript@5.8.3)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.61.0(typescript@5.8.3) - '@typescript-eslint/types': 8.61.0 - debug: 4.4.3(supports-color@5.5.0) - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/scope-manager@8.60.1': dependencies: '@typescript-eslint/types': 8.60.1 '@typescript-eslint/visitor-keys': 8.60.1 - '@typescript-eslint/scope-manager@8.61.0': - dependencies: - '@typescript-eslint/types': 8.61.0 - '@typescript-eslint/visitor-keys': 8.61.0 - '@typescript-eslint/tsconfig-utils@8.60.1(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/tsconfig-utils@8.61.0(typescript@5.8.3)': - dependencies: - typescript: 5.8.3 - '@typescript-eslint/type-utils@8.60.1(eslint@8.57.1)(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.60.1 @@ -19229,22 +17532,8 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3)': - dependencies: - '@typescript-eslint/types': 8.61.0 - '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.8.3) - '@typescript-eslint/utils': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3) - debug: 4.4.3(supports-color@5.5.0) - eslint: 9.39.4(jiti@2.7.0) - ts-api-utils: 2.5.0(typescript@5.8.3) - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/types@8.60.1': {} - '@typescript-eslint/types@8.61.0': {} - '@typescript-eslint/typescript-estree@8.60.1(typescript@5.9.3)': dependencies: '@typescript-eslint/project-service': 8.60.1(typescript@5.9.3) @@ -19260,21 +17549,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.61.0(typescript@5.8.3)': - dependencies: - '@typescript-eslint/project-service': 8.61.0(typescript@5.8.3) - '@typescript-eslint/tsconfig-utils': 8.61.0(typescript@5.8.3) - '@typescript-eslint/types': 8.61.0 - '@typescript-eslint/visitor-keys': 8.61.0 - debug: 4.4.3(supports-color@5.5.0) - minimatch: 10.2.5 - semver: 7.8.2 - tinyglobby: 0.2.17 - ts-api-utils: 2.5.0(typescript@5.8.3) - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/utils@8.60.1(eslint@8.57.1)(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) @@ -19286,27 +17560,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3)': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) - '@typescript-eslint/scope-manager': 8.61.0 - '@typescript-eslint/types': 8.61.0 - '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.8.3) - eslint: 9.39.4(jiti@2.7.0) - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/visitor-keys@8.60.1': dependencies: '@typescript-eslint/types': 8.60.1 eslint-visitor-keys: 5.0.1 - '@typescript-eslint/visitor-keys@8.61.0': - dependencies: - '@typescript-eslint/types': 8.61.0 - eslint-visitor-keys: 5.0.1 - '@ungap/structured-clone@1.3.1': {} '@unrs/resolver-binding-android-arm-eabi@1.12.2': @@ -19391,18 +17649,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@4.7.0(vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)(yaml@2.9.0))': - dependencies: - '@babel/core': 7.29.7 - '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) - '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7) - '@rolldown/pluginutils': 1.0.0-beta.27 - '@types/babel__core': 7.20.5 - react-refresh: 0.17.0 - vite: 6.4.3(@types/node@24.13.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)(yaml@2.9.0) - transitivePeerDependencies: - - supports-color - '@vitest/expect@2.1.9': dependencies: '@vitest/spy': 2.1.9 @@ -20099,8 +18345,6 @@ snapshots: jsonparse: 1.3.1 through: 2.3.8 - abab@2.0.6: {} - abbrev@1.1.1: {} abort-controller@3.0.0: @@ -20123,11 +18367,6 @@ snapshots: dependencies: acorn: 4.0.13 - acorn-globals@7.0.1: - dependencies: - acorn: 8.16.0 - acorn-walk: 8.3.5 - acorn-import-phases@1.0.4(acorn@8.16.0): dependencies: acorn: 8.16.0 @@ -20479,10 +18718,6 @@ snapshots: dependencies: tslib: 2.8.1 - aria-query@5.3.0: - dependencies: - dequal: 2.0.3 - aria-query@5.3.2: {} arr-diff@4.0.0: {} @@ -20704,17 +18939,6 @@ snapshots: cosmiconfig: 7.1.0 resolve: 1.22.12 - babel-plugin-styled-components@2.3.0(@babel/core@7.29.7)(styled-components@5.3.11(@babel/core@7.29.7)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1))(supports-color@5.5.0): - dependencies: - '@babel/core': 7.29.7 - '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-module-imports': 7.29.7(supports-color@5.5.0) - '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) - picomatch: 4.0.4 - styled-components: 5.3.11(@babel/core@7.29.7)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1) - transitivePeerDependencies: - - supports-color - babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.7): dependencies: '@babel/core': 7.29.7 @@ -21117,8 +19341,6 @@ snapshots: camelcase@6.3.0: {} - camelize@1.0.1: {} - caniuse-lite@1.0.30001797: {} canvg@3.0.11: @@ -21331,18 +19553,6 @@ snapshots: clsx@2.1.1: {} - cmdk@1.1.1(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.31)(react@18.3.1) - '@radix-ui/react-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.2(@types/react@18.3.31)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.5(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - cmdk@1.1.1(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: '@radix-ui/react-compose-refs': 1.1.3(@types/react@18.3.31)(react@19.2.6) @@ -21599,21 +19809,6 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)): - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - create-require@1.1.1: {} cron@4.4.0: @@ -21652,8 +19847,6 @@ snapshots: dependencies: tiny-invariant: 1.3.3 - css-color-keywords@1.0.0: {} - css-line-break@2.1.0: dependencies: utrie: 1.0.2 @@ -21666,12 +19859,6 @@ snapshots: domutils: 3.2.2 nth-check: 2.1.1 - css-to-react-native@3.2.0: - dependencies: - camelize: 1.0.1 - css-color-keywords: 1.0.0 - postcss-value-parser: 4.2.0 - css-tree@1.1.3: dependencies: mdn-data: 2.0.14 @@ -21679,18 +19866,8 @@ snapshots: css-what@6.2.2: {} - css.escape@1.5.1: {} - cssesc@3.0.0: {} - cssom@0.3.8: {} - - cssom@0.5.0: {} - - cssstyle@2.3.0: - dependencies: - cssom: 0.3.8 - cssstyle@4.6.0: dependencies: '@asamuzakjp/css-color': 3.2.0 @@ -21759,12 +19936,6 @@ snapshots: data-uri-to-buffer@6.0.2: {} - data-urls@3.0.2: - dependencies: - abab: 2.0.6 - whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 - data-urls@5.0.0: dependencies: whatwg-mimetype: 4.0.0 @@ -21993,10 +20164,6 @@ snapshots: dependencies: esutils: 2.0.3 - dom-accessibility-api@0.5.16: {} - - dom-accessibility-api@0.6.3: {} - dom-helpers@5.2.1: dependencies: '@babel/runtime': 7.29.7 @@ -22012,10 +20179,6 @@ snapshots: domelementtype@2.3.0: {} - domexception@4.0.0: - dependencies: - webidl-conversions: 7.0.0 - domhandler@5.0.3: dependencies: domelementtype: 2.3.0 @@ -22025,6 +20188,7 @@ snapshots: dompurify@3.4.8: optionalDependencies: '@types/trusted-types': 2.0.7 + optional: true domutils@3.2.2: dependencies: @@ -22359,35 +20523,6 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - esbuild@0.25.12: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 - escalade@3.2.0: {} escape-html@1.0.3: {} @@ -22521,18 +20656,10 @@ snapshots: dependencies: eslint: 8.57.1 - eslint-plugin-react-hooks@5.2.0(eslint@9.39.4(jiti@2.7.0)): - dependencies: - eslint: 9.39.4(jiti@2.7.0) - eslint-plugin-react-refresh@0.4.26(eslint@8.57.1): dependencies: eslint: 8.57.1 - eslint-plugin-react-refresh@0.4.26(eslint@9.39.4(jiti@2.7.0)): - dependencies: - eslint: 9.39.4(jiti@2.7.0) - eslint-plugin-react@7.37.5(eslint@8.57.1): dependencies: array-includes: 3.1.9 @@ -22565,15 +20692,8 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 - eslint-scope@8.4.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.2.1: {} - eslint-visitor-keys@5.0.1: {} eslint@8.57.1: @@ -22619,47 +20739,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint@9.39.4(jiti@2.7.0): - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) - '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.2 - '@eslint/config-helpers': 0.4.2 - '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.5 - '@eslint/js': 9.39.4 - '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.8 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.9 - ajv: 6.15.0 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@5.5.0) - escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.7.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.5 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.7.0 - transitivePeerDependencies: - - supports-color - esniff@2.0.1: dependencies: d: 1.0.2 @@ -22667,12 +20746,6 @@ snapshots: event-emitter: 0.3.5 type: 2.7.3 - espree@10.4.0: - dependencies: - acorn: 8.16.0 - acorn-jsx: 5.3.2(acorn@8.16.0) - eslint-visitor-keys: 4.2.1 - espree@9.6.1: dependencies: acorn: 8.16.0 @@ -23072,10 +21145,6 @@ snapshots: dependencies: flat-cache: 3.2.0 - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - file-selector@2.1.2: dependencies: tslib: 2.8.1 @@ -23167,11 +21236,6 @@ snapshots: keyv: 4.5.4 rimraf: 3.0.2 - flat-cache@4.0.1: - dependencies: - flatted: 3.4.2 - keyv: 4.5.4 - flat@5.0.2: {} flatted@3.4.2: {} @@ -23266,16 +21330,6 @@ snapshots: dependencies: map-cache: 0.2.2 - framer-motion@12.40.0(@emotion/is-prop-valid@1.4.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - motion-dom: 12.40.0 - motion-utils: 12.39.0 - tslib: 2.8.1 - optionalDependencies: - '@emotion/is-prop-valid': 1.4.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - framer-motion@12.40.0(@emotion/is-prop-valid@1.4.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: motion-dom: 12.40.0 @@ -23507,10 +21561,6 @@ snapshots: dependencies: type-fest: 0.20.2 - globals@14.0.0: {} - - globals@16.5.0: {} - globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -23603,8 +21653,6 @@ snapshots: ajv: 6.15.0 har-schema: 2.0.0 - harmony-reflect@1.6.2: {} - has-bigints@1.1.0: {} has-flag@2.0.0: {} @@ -23726,10 +21774,6 @@ snapshots: hsl-to-rgb-for-reals@1.1.1: {} - html-encoding-sniffer@3.0.0: - dependencies: - whatwg-encoding: 2.0.0 - html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 @@ -23772,14 +21816,6 @@ snapshots: http-parser-js@0.5.10: {} - http-proxy-agent@5.0.0: - dependencies: - '@tootallnate/once': 2.0.1 - agent-base: 6.0.2 - debug: 4.4.3(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 @@ -23841,12 +21877,6 @@ snapshots: dependencies: '@babel/runtime': 7.29.7 - i18next@25.10.10(typescript@5.8.3): - dependencies: - '@babel/runtime': 7.29.7 - optionalDependencies: - typescript: 5.8.3 - i18next@25.10.10(typescript@5.9.3): dependencies: '@babel/runtime': 7.29.7 @@ -23867,10 +21897,6 @@ snapshots: idb-keyval@6.2.5: {} - identity-obj-proxy@3.0.0: - dependencies: - harmony-reflect: 1.6.2 - ieee754@1.2.1: {} ignore@5.3.2: {} @@ -23906,8 +21932,6 @@ snapshots: dependencies: repeating: 2.0.1 - indent-string@4.0.0: {} - inflight@1.0.6: dependencies: once: 1.4.0 @@ -24359,25 +22383,6 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)): - dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - jest-config@29.7.0(@types/node@20.19.42)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.19.42)(typescript@5.9.3)): dependencies: '@babel/core': 7.29.7 @@ -24409,68 +22414,6 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@20.19.42)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)): - dependencies: - '@babel/core': 7.29.7 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.29.7) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0(babel-plugin-macros@3.1.0) - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 20.19.42 - ts-node: 10.9.2(@types/node@24.13.1)(typescript@5.9.3) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-config@29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)): - dependencies: - '@babel/core': 7.29.7 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.29.7) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0(babel-plugin-macros@3.1.0) - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 24.13.1 - ts-node: 10.9.2(@types/node@24.13.1)(typescript@5.9.3) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - jest-diff@29.7.0: dependencies: chalk: 4.1.2 @@ -24490,21 +22433,6 @@ snapshots: jest-util: 29.7.0 pretty-format: 29.7.0 - jest-environment-jsdom@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/jsdom': 20.0.1 - '@types/node': 20.19.42 - jest-mock: 29.7.0 - jest-util: 29.7.0 - jsdom: 20.0.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - jest-environment-node@29.7.0: dependencies: '@jest/environment': 29.7.0 @@ -24719,18 +22647,6 @@ snapshots: - supports-color - ts-node - jest@29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)): - dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)) - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - jiti@1.21.7: {} jiti@2.6.1: {} @@ -24770,39 +22686,6 @@ snapshots: jsbn@0.1.1: {} - jsdom@20.0.3: - dependencies: - abab: 2.0.6 - acorn: 8.16.0 - acorn-globals: 7.0.1 - cssom: 0.5.0 - cssstyle: 2.3.0 - data-urls: 3.0.2 - decimal.js: 10.6.0 - domexception: 4.0.0 - escodegen: 2.1.0 - form-data: 4.0.5 - html-encoding-sniffer: 3.0.0 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 - is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.24 - parse5: 7.3.0 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 4.1.4 - w3c-xmlserializer: 4.0.0 - webidl-conversions: 7.0.0 - whatwg-encoding: 2.0.0 - whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 - ws: 8.21.0 - xml-name-validator: 4.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - jsdom@25.0.1: dependencies: cssstyle: 4.6.0 @@ -25305,10 +23188,6 @@ snapshots: dependencies: react: 18.3.1 - lucide-react@0.513.0(react@18.3.1): - dependencies: - react: 18.3.1 - lucide-react@0.513.0(react@19.2.6): dependencies: react: 19.2.6 @@ -25323,8 +23202,6 @@ snapshots: luxon@3.7.2: {} - lz-string@1.5.0: {} - magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -25351,20 +23228,6 @@ snapshots: dependencies: tmpl: 1.0.5 - mantine-react-table@2.0.0-beta.9(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/dates@7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(dayjs@1.11.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(@tabler/icons-react@3.44.0(react@18.3.1))(clsx@2.1.1)(dayjs@1.11.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@mantine/core': 7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mantine/dates': 7.17.8(@mantine/core@7.17.8(@mantine/hooks@7.17.8(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@7.17.8(react@18.3.1))(dayjs@1.11.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mantine/hooks': 7.17.8(react@18.3.1) - '@tabler/icons-react': 3.44.0(react@18.3.1) - '@tanstack/match-sorter-utils': 8.19.4 - '@tanstack/react-table': 8.20.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@tanstack/react-virtual': 3.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - clsx: 2.1.1 - dayjs: 1.11.21 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - map-cache@0.2.2: {} map-obj@1.0.1: {} @@ -25522,8 +23385,6 @@ snapshots: mimic-function@5.0.1: {} - min-indent@1.0.1: {} - minimalistic-assert@1.0.1: {} minimalistic-crypto-utils@1.0.1: {} @@ -25645,17 +23506,6 @@ snapshots: react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - mui-ethiopian-datepicker@0.3.2(3a08e075008fbda84afcc45f3c40f97b): - dependencies: - '@emotion/react': 11.14.0(@types/react@18.3.31)(react@18.3.1) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1) - '@mui/icons-material': 5.18.0(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.31)(react@18.3.1) - '@mui/material': 5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mui/x-date-pickers': 6.20.2(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@mui/material@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.18.0(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(react@18.3.1))(@types/react@18.3.31)(date-fns@3.6.0)(dayjs@1.11.21)(luxon@3.7.2)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - date-fns: 3.6.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - mui-ethiopian-datepicker@0.3.2(7d86988bc4fd0020aebaf3d4b373b1a0): dependencies: '@emotion/react': 11.14.0(@types/react@18.3.31)(react@19.2.6) @@ -25751,11 +23601,6 @@ snapshots: netmask@2.1.1: {} - next-themes@0.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - next-themes@0.4.6(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: react: 19.2.6 @@ -26290,13 +24135,6 @@ snapshots: sha.js: 2.4.12 to-buffer: 1.2.2 - pdf-lib@1.17.1: - dependencies: - '@pdf-lib/standard-fonts': 1.0.0 - '@pdf-lib/upng': 1.0.1 - pako: 1.0.11 - tslib: 1.14.1 - pdfjs-dist@2.16.105: dependencies: dommatrix: 1.0.3 @@ -26475,12 +24313,6 @@ snapshots: prettier@3.8.3: {} - pretty-format@27.5.1: - dependencies: - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 - pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3 @@ -26884,15 +24716,6 @@ snapshots: defu: 6.1.7 destr: 2.0.5 - react-cookie@8.1.2(@types/react@18.3.31)(react@18.3.1): - dependencies: - '@types/hoist-non-react-statics': 3.3.7(@types/react@18.3.31) - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - universal-cookie: 8.1.2 - transitivePeerDependencies: - - '@types/react' - react-cookie@8.1.2(@types/react@18.3.31)(react@19.2.6): dependencies: '@types/hoist-non-react-statics': 3.3.7(@types/react@18.3.31) @@ -26902,15 +24725,6 @@ snapshots: transitivePeerDependencies: - '@types/react' - react-css-nocode-editor@1.0.13(@babel/core@7.29.7)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1): - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - styled-components: 5.3.11(@babel/core@7.29.7)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1) - transitivePeerDependencies: - - '@babel/core' - - react-is - react-datepicker@8.10.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: '@floating-ui/react': 0.27.19(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -26919,11 +24733,6 @@ snapshots: react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - react-day-picker@8.10.2(date-fns@3.6.0)(react@18.3.1): - dependencies: - date-fns: 3.6.0 - react: 18.3.1 - react-day-picker@9.14.0(react@19.2.6): dependencies: '@date-fns/tz': 1.5.0 @@ -26951,13 +24760,6 @@ snapshots: react: 19.2.6 scheduler: 0.27.0 - react-dropzone@14.4.1(react@18.3.1): - dependencies: - attr-accept: 2.2.5 - file-selector: 2.1.2 - prop-types: 15.8.1 - react: 18.3.1 - react-dropzone@14.4.1(react@19.2.6): dependencies: attr-accept: 2.2.5 @@ -26990,16 +24792,6 @@ snapshots: react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - react-i18next@15.7.4(i18next@25.10.10(typescript@5.8.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3): - dependencies: - '@babel/runtime': 7.29.7 - html-parse-stringify: 3.0.1 - i18next: 25.10.10(typescript@5.8.3) - react: 18.3.1 - optionalDependencies: - react-dom: 18.3.1(react@18.3.1) - typescript: 5.8.3 - react-i18next@15.7.4(i18next@25.10.10(typescript@5.9.3))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3): dependencies: '@babel/runtime': 7.29.7 @@ -27010,18 +24802,10 @@ snapshots: react-dom: 19.2.6(react@19.2.6) typescript: 5.9.3 - react-icons@5.6.0(react@18.3.1): - dependencies: - react: 18.3.1 - react-icons@5.6.0(react@19.2.6): dependencies: react: 19.2.6 - react-image-crop@11.0.10(react@18.3.1): - dependencies: - react: 18.3.1 - react-image-crop@11.0.10(react@19.2.6): dependencies: react: 19.2.6 @@ -27031,12 +24815,6 @@ snapshots: '@types/react': 18.3.31 react: 19.2.6 - react-intersection-observer@9.16.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - react: 18.3.1 - optionalDependencies: - react-dom: 18.3.1(react@18.3.1) - react-intersection-observer@9.16.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: react: 19.2.6 @@ -27045,8 +24823,6 @@ snapshots: react-is@16.13.1: {} - react-is@17.0.2: {} - react-is@18.3.1: {} react-is@19.2.7: {} @@ -27069,23 +24845,11 @@ snapshots: transitivePeerDependencies: - '@types/react' - react-number-format@5.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-number-format@5.4.5(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - react-pdf-html@2.1.5(@react-pdf/renderer@4.5.1(react@18.3.1))(react@18.3.1): - dependencies: - '@react-pdf/renderer': 4.5.1(react@18.3.1) - css-tree: 1.1.3 - node-html-parser: 6.1.13 - react: 18.3.1 - react-pdf-html@2.1.5(@react-pdf/renderer@4.5.1(react@19.2.6))(react@19.2.6): dependencies: '@react-pdf/renderer': 4.5.1(react@19.2.6) @@ -27105,21 +24869,6 @@ snapshots: - webpack-command - worker-loader - react-pdf@10.4.1(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - clsx: 2.1.1 - dequal: 2.0.3 - make-cancellable-promise: 2.0.0 - make-event-props: 2.0.0 - merge-refs: 2.0.0(@types/react@18.3.31) - pdfjs-dist: 5.4.296 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - tiny-invariant: 1.3.3 - warning: 4.0.3 - optionalDependencies: - '@types/react': 18.3.31 - react-pdf@10.4.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: clsx: 2.1.1 @@ -27135,15 +24884,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - react-redux@9.3.0(@types/react@18.3.31)(react@18.3.1)(redux@5.0.1): - dependencies: - '@types/use-sync-external-store': 0.0.6 - react: 18.3.1 - use-sync-external-store: 1.6.0(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.31 - redux: 5.0.1 - react-redux@9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 @@ -27193,11 +24933,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - react-resizable-panels@3.0.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-resizable-panels@3.0.6(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: react: 19.2.6 @@ -27210,12 +24945,6 @@ snapshots: react-dom: 19.2.6(react@19.2.6) react-router: 6.30.4(react@19.2.6) - react-router-dom@7.17.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-router: 7.17.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-router-dom@7.17.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: react: 19.2.6 @@ -27227,14 +24956,6 @@ snapshots: '@remix-run/router': 1.23.3 react: 19.2.6 - react-router@7.17.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - cookie: 1.1.1 - react: 18.3.1 - set-cookie-parser: 2.7.2 - optionalDependencies: - react-dom: 18.3.1(react@18.3.1) - react-router@7.17.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: cookie: 1.1.1 @@ -27243,19 +24964,6 @@ snapshots: optionalDependencies: react-dom: 19.2.6(react@19.2.6) - react-signature-canvas@1.1.0-alpha.2(@types/prop-types@15.7.15)(@types/react@18.3.31)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.29.7 - '@types/signature_pad': 2.3.6 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - signature_pad: 2.3.2 - trim-canvas: 0.1.2 - optionalDependencies: - '@types/prop-types': 15.7.15 - '@types/react': 18.3.31 - react-signature-canvas@1.1.0-alpha.2(@types/prop-types@15.7.15)(@types/react@18.3.31)(prop-types@15.8.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: '@babel/runtime': 7.29.7 @@ -27297,15 +25005,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - react-textarea-autosize@8.5.9(@types/react@18.3.31)(react@18.3.1): - dependencies: - '@babel/runtime': 7.29.7 - react: 18.3.1 - use-composed-ref: 1.4.0(@types/react@18.3.31)(react@18.3.1) - use-latest: 1.3.0(@types/react@18.3.31)(react@18.3.1) - transitivePeerDependencies: - - '@types/react' - react-textarea-autosize@8.5.9(@types/react@18.3.31)(react@19.2.6): dependencies: '@babel/runtime': 7.29.7 @@ -27451,26 +25150,6 @@ snapshots: tiny-invariant: 1.3.3 victory-vendor: 36.9.2 - recharts@3.8.1(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1)(redux@5.0.1): - dependencies: - '@reduxjs/toolkit': 2.12.0(react-redux@9.3.0(@types/react@18.3.31)(react@18.3.1)(redux@5.0.1))(react@18.3.1) - clsx: 2.1.1 - decimal.js-light: 2.5.1 - es-toolkit: 1.47.0 - eventemitter3: 5.0.4 - immer: 10.2.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-is: 19.2.7 - react-redux: 9.3.0(@types/react@18.3.31)(react@18.3.1)(redux@5.0.1) - reselect: 5.1.1 - tiny-invariant: 1.3.3 - use-sync-external-store: 1.6.0(react@18.3.1) - victory-vendor: 37.3.6 - transitivePeerDependencies: - - '@types/react' - - redux - recharts@3.8.1(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react-is@19.2.7)(react@19.2.6)(redux@5.0.1): dependencies: '@reduxjs/toolkit': 2.12.0(react-redux@9.3.0(@types/react@18.3.31)(react@19.2.6)(redux@5.0.1))(react@19.2.6) @@ -27496,11 +25175,6 @@ snapshots: indent-string: 2.1.0 strip-indent: 1.0.1 - redent@3.0.0: - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - redux-thunk@3.1.0(redux@5.0.1): dependencies: redux: 5.0.1 @@ -27547,8 +25221,6 @@ snapshots: argparse: 1.0.10 autolinker: 0.28.1 - remove-accents@0.5.0: {} - remove-trailing-separator@1.1.0: {} repeat-element@1.1.4: {} @@ -27672,15 +25344,6 @@ snapshots: hash-base: 3.1.2 inherits: 2.0.4 - rollup-plugin-visualizer@7.0.1(rollup@4.61.1): - dependencies: - open: 11.0.0 - picomatch: 4.0.4 - source-map: 0.7.6 - yargs: 18.0.0 - optionalDependencies: - rollup: 4.61.1 - rollup@4.61.1: dependencies: '@types/estree': 1.0.9 @@ -27981,8 +25644,6 @@ snapshots: - supports-color - typescript - shallowequal@1.1.0: {} - shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 @@ -28135,11 +25796,6 @@ snapshots: ip-address: 10.2.0 smart-buffer: 4.2.0 - sonner@2.0.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - sonner@2.0.7(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: react: 19.2.6 @@ -28436,10 +26092,6 @@ snapshots: dependencies: get-stdin: 4.0.1 - strip-indent@3.0.0: - dependencies: - min-indent: 1.0.1 - strip-json-comments@3.1.1: {} striptags@3.2.0: {} @@ -28457,24 +26109,6 @@ snapshots: style-object-to-css-string@1.1.3: {} - styled-components@5.3.11(@babel/core@7.29.7)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1): - dependencies: - '@babel/helper-module-imports': 7.29.7(supports-color@5.5.0) - '@babel/traverse': 7.29.7(supports-color@5.5.0) - '@emotion/is-prop-valid': 1.4.0 - '@emotion/stylis': 0.8.5 - '@emotion/unitless': 0.7.5 - babel-plugin-styled-components: 2.3.0(@babel/core@7.29.7)(styled-components@5.3.11(@babel/core@7.29.7)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.7)(react@18.3.1))(supports-color@5.5.0) - css-to-react-native: 3.2.0 - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-is: 19.2.7 - shallowequal: 1.1.0 - supports-color: 5.5.0 - transitivePeerDependencies: - - '@babel/core' - styled-jsx@5.1.1(babel-plugin-macros@3.1.0)(react@18.3.1): dependencies: client-only: 0.0.1 @@ -28818,13 +26452,6 @@ snapshots: psl: 1.15.0 punycode: 2.3.1 - tough-cookie@4.1.4: - dependencies: - psl: 1.15.0 - punycode: 2.3.1 - universalify: 0.2.0 - url-parse: 1.5.10 - tough-cookie@5.1.2: dependencies: tldts: 6.1.86 @@ -28835,10 +26462,6 @@ snapshots: tr46@0.0.3: {} - tr46@3.0.0: - dependencies: - punycode: 2.3.1 - tr46@5.1.1: dependencies: punycode: 2.3.1 @@ -28859,10 +26482,6 @@ snapshots: trim-newlines@1.0.0: {} - ts-api-utils@2.5.0(typescript@5.8.3): - dependencies: - typescript: 5.8.3 - ts-api-utils@2.5.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -28889,26 +26508,6 @@ snapshots: babel-jest: 29.7.0(@babel/core@7.29.7) jest-util: 29.7.0 - ts-jest@29.4.11(@babel/core@7.29.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.29.7))(jest-util@29.7.0)(jest@29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)))(typescript@5.8.3): - dependencies: - bs-logger: 0.2.6 - fast-json-stable-stringify: 2.1.0 - handlebars: 4.7.9 - jest: 29.7.0(@types/node@24.13.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.13.1)(typescript@5.9.3)) - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.8.2 - type-fest: 4.41.0 - typescript: 5.8.3 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.29.7 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.29.7) - jest-util: 29.7.0 - ts-loader@9.6.0(loader-utils@1.4.2)(typescript@5.9.3)(webpack@5.106.0): dependencies: chalk: 4.1.2 @@ -28983,8 +26582,6 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 - tslib@1.14.1: {} - tslib@2.8.1: {} tty-browserify@0.0.0: {} @@ -29137,19 +26734,6 @@ snapshots: - babel-plugin-macros - supports-color - typescript-eslint@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.61.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3) - '@typescript-eslint/parser': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3) - '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.8.3) - '@typescript-eslint/utils': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.8.3) - eslint: 9.39.4(jiti@2.7.0) - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color - - typescript@5.8.3: {} - typescript@5.9.3: {} uglify-js@2.8.29: @@ -29214,8 +26798,6 @@ snapshots: dependencies: cookie: 1.1.1 - universalify@0.2.0: {} - universalify@2.0.1: {} unpipe@1.0.0: {} @@ -29307,12 +26889,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - use-composed-ref@1.4.0(@types/react@18.3.31)(react@18.3.1): - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.31 - use-composed-ref@1.4.0(@types/react@18.3.31)(react@19.2.6): dependencies: react: 19.2.6 @@ -29331,13 +26907,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.31 - use-latest@1.3.0(@types/react@18.3.31)(react@18.3.1): - dependencies: - react: 18.3.1 - use-isomorphic-layout-effect: 1.2.1(@types/react@18.3.31)(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.31 - use-latest@1.3.0(@types/react@18.3.31)(react@19.2.6): dependencies: react: 19.2.6 @@ -29364,6 +26933,7 @@ snapshots: use-sync-external-store@1.6.0(react@18.3.1): dependencies: react: 18.3.1 + optional: true use-sync-external-store@1.6.0(react@19.2.6): dependencies: @@ -29420,15 +26990,6 @@ snapshots: vary@1.1.2: {} - vaul@1.1.2(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@radix-ui/react-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - vaul@1.1.2(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: '@radix-ui/react-dialog': 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.31))(@types/react@18.3.31)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -29513,22 +27074,6 @@ snapshots: lightningcss: 1.32.0 terser: 5.48.0 - vite@6.4.3(@types/node@24.13.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)(yaml@2.9.0): - dependencies: - esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - postcss: 8.5.15 - rollup: 4.61.1 - tinyglobby: 0.2.17 - optionalDependencies: - '@types/node': 24.13.1 - fsevents: 2.3.3 - jiti: 2.7.0 - lightningcss: 1.32.0 - terser: 5.48.0 - yaml: 2.9.0 - vitest@2.1.9(@types/node@24.13.1)(jsdom@25.0.1)(lightningcss@1.32.0)(msw@2.14.6(@types/node@24.13.1)(typescript@5.9.3))(terser@5.48.0): dependencies: '@vitest/expect': 2.1.9 @@ -29571,10 +27116,6 @@ snapshots: w3c-keyname@2.2.8: {} - w3c-xmlserializer@4.0.0: - dependencies: - xml-name-validator: 4.0.0 - w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 @@ -29758,23 +27299,12 @@ snapshots: websocket-extensions@0.1.4: {} - whatwg-encoding@2.0.0: - dependencies: - iconv-lite: 0.6.3 - whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 - whatwg-mimetype@3.0.0: {} - whatwg-mimetype@4.0.0: {} - whatwg-url@11.0.0: - dependencies: - tr46: 3.0.0 - webidl-conversions: 7.0.0 - whatwg-url@14.2.0: dependencies: tr46: 5.1.1 @@ -29932,8 +27462,6 @@ snapshots: wmf: 1.0.2 word: 0.3.0 - xml-name-validator@4.0.0: {} - xml-name-validator@5.0.0: {} xml2js@0.5.0: From 05da2ce27a635ca7c33430477b5285f8f9c777bd Mon Sep 17 00:00:00 2001 From: Nathnael Date: Tue, 16 Jun 2026 08:29:40 +0000 Subject: [PATCH 10/12] feat: ui status updates --- .../src/pages/bookings/BookingDetailPage.tsx | 25 +- apps/edr-freight-web/portal/src/App.tsx | 2 - .../portal/src/pages/MyPortalPage.tsx | 225 ++++++++++++++++-- 3 files changed, 223 insertions(+), 29 deletions(-) diff --git a/apps/edr-freight-web/backoffice/src/pages/bookings/BookingDetailPage.tsx b/apps/edr-freight-web/backoffice/src/pages/bookings/BookingDetailPage.tsx index 39040db19..e225bea0b 100644 --- a/apps/edr-freight-web/backoffice/src/pages/bookings/BookingDetailPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/bookings/BookingDetailPage.tsx @@ -1,21 +1,20 @@ -import { useParams, useNavigate } from "react-router-dom"; -import { Container, Stack, Grid } from "@mantine/core"; +import { Container, Grid, Stack } from "@mantine/core"; +import { useNavigate, useParams } from "react-router-dom"; -import Breadcrumbs from "@/components/ui/Breadcrumbs"; import { - detailStyles, - type BookingDetailView, - BookingDetailToolbar, - BookingDetailHeader, - BookingLifecycleStepper, - BookingRouteCard, - BookingContainersCard, BookingApprovalCard, - BookingReviewNotesCard, - BookingPaymentCard, - BookingFactsCard, + BookingContainersCard, + BookingDetailToolbar, BookingDocumentsCard, + BookingFactsCard, + BookingLifecycleStepper, + BookingPaymentCard, + BookingReviewNotesCard, + BookingRouteCard, + detailStyles, + type BookingDetailView } from "@/components/bookings/detail"; +import Breadcrumbs from "@/components/ui/Breadcrumbs"; const BookingDetailPage = () => { const { id } = useParams<{ id: string }>(); diff --git a/apps/edr-freight-web/portal/src/App.tsx b/apps/edr-freight-web/portal/src/App.tsx index c0eb0ac34..789589900 100644 --- a/apps/edr-freight-web/portal/src/App.tsx +++ b/apps/edr-freight-web/portal/src/App.tsx @@ -79,8 +79,6 @@ function RequireCompany({path}: {path: string}) { const { customerQuery } = useAuth(); if (customerQuery.isPending) return ; - if (customerQuery.isSuccess && !customerQuery.data && path !== "/portal") - return ; return ; } diff --git a/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx b/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx index 710e607f0..7b488bc7d 100644 --- a/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/MyPortalPage.tsx @@ -1,5 +1,4 @@ import { - Alert, Box, Grid, Group, @@ -91,19 +90,162 @@ const STATUS_CONFIG: Record = { badgeDot: "edr-blue-dot", action: { label: "View", kind: "outline" }, }, + CHANGES_REQUESTED: { + stage: 1, + icon: FilePen, + iconColor: "edr-amber-text", + tile: "edr-amber-soft", + hint: "Changes requested · please update", + step: "edr-accent", + badgeLabel: "Revise", + badgeBg: "edr-amber-soft", + badgeText: "edr-amber-text", + badgeDot: "edr-accent", + action: { label: "Update", kind: "dark" }, + }, PENDING_APPROVAL: { + stage: 2, + icon: FileCheck2, + iconColor: "edr-blue", + tile: "edr-blue-soft", + hint: "Pending internal approval", + step: "edr-blue-dot", + badgeLabel: "Pending", + badgeBg: "edr-blue-soft", + badgeText: "edr-blue", + badgeDot: "edr-blue-dot", + action: { label: "View", kind: "outline" }, + }, + APPROVED_PENDING_SIGNATURE: { + stage: 2, + icon: FileCheck2, + iconColor: "edr-blue", + tile: "edr-blue-soft", + hint: "Approved · awaiting signature", + step: "edr-blue-dot", + badgeLabel: "For Signature", + badgeBg: "edr-blue-soft", + badgeText: "edr-blue", + badgeDot: "edr-blue-dot", + action: { label: "Review", kind: "outline" }, + }, + APPROVED: { + stage: 2, + icon: CheckCircle2, + iconColor: "edr-green.7", + tile: "edr-soft", + hint: "Quote approved · ready to sign", + step: "edr-green.5", + badgeLabel: "Approved", + badgeBg: "edr-soft", + badgeText: "edr-green.7", + badgeDot: "edr-green.5", + action: { label: "View", kind: "outline" }, + }, + CONTRACT_READY: { + stage: 2, + icon: CheckCircle2, + iconColor: "edr-green.7", + tile: "edr-soft", + hint: "Contract ready · awaiting signature", + step: "edr-green.5", + badgeLabel: "Contract Ready", + badgeBg: "edr-soft", + badgeText: "edr-green.7", + badgeDot: "edr-green.5", + action: { label: "Review", kind: "outline" }, + }, + SIGNED_CUSTOMER: { + stage: 3, + icon: CheckCircle2, + iconColor: "edr-green.7", + tile: "edr-soft", + hint: "Signed by customer · internal processing", + step: "edr-green.5", + badgeLabel: "Signed", + badgeBg: "edr-soft", + badgeText: "edr-green.7", + badgeDot: "edr-green.5", + action: { label: "View", kind: "outline" }, + }, + FULLY_EXECUTED: { + stage: 3, + icon: CheckCircle2, + iconColor: "edr-green.7", + tile: "edr-soft", + hint: "Fully executed · generating PNR", + step: "edr-green.5", + badgeLabel: "Executed", + badgeBg: "edr-soft", + badgeText: "edr-green.7", + badgeDot: "edr-green.5", + action: { label: "View", kind: "outline" }, + }, + PNR_GENERATED: { + stage: 3, + icon: FileCheck2, + iconColor: "edr-blue", + tile: "edr-blue-soft", + hint: "PNR generated · awaiting payment verification", + step: "edr-blue-dot", + badgeLabel: "PNR Ready", + badgeBg: "edr-blue-soft", + badgeText: "edr-blue", + badgeDot: "edr-blue-dot", + action: { label: "View", kind: "outline" }, + }, + PAYMENT_VERIFICATION_IN_PROGRESS: { + stage: 2, + icon: Clock3, + iconColor: "edr-amber-text", + tile: "edr-amber-soft", + hint: "Verifying payment · please wait", + step: "edr-accent", + badgeLabel: "Verifying", + badgeBg: "edr-amber-soft", + badgeText: "edr-amber-text", + badgeDot: "edr-accent", + action: { label: "View", kind: "outline" }, + }, + SELECTED_FOR_BATCH: { stage: 2, icon: Wallet, iconColor: "edr-amber-text", tile: "edr-amber-soft", - hint: "Quote ready · awaiting payment", + hint: "Selected for batch · payment due within 1 hour", step: "edr-accent", - badgeLabel: "Awaiting Payment", + badgeLabel: "Pay Now", badgeBg: "edr-amber-soft", badgeText: "edr-amber-text", badgeDot: "edr-accent", action: { label: "Pay now", kind: "amber", icon: ArrowRight }, }, + EXPIRED: { + stage: 1, + icon: Clock3, + iconColor: "edr-red", + tile: "edr-red-soft", + hint: "Payment window expired · contact support", + step: "edr-red", + badgeLabel: "Expired", + badgeBg: "edr-red-soft", + badgeText: "edr-red", + badgeDot: "edr-red", + action: { label: "Contact", kind: "outline" }, + }, + PAID: { + stage: 3, + icon: CheckCircle2, + iconColor: "edr-green.7", + tile: "edr-soft", + hint: "Payment received · awaiting dispatch", + step: "edr-green.5", + badgeLabel: "Paid", + badgeBg: "edr-soft", + badgeText: "edr-green.7", + badgeDot: "edr-green.5", + action: { label: "View", kind: "outline" }, + }, IN_TRANSIT: { stage: 3, icon: Truck, @@ -118,6 +260,19 @@ const STATUS_CONFIG: Record = { action: { label: "Track", kind: "outline", icon: MapPin }, }, COMPLETED: { + stage: 4, + icon: CheckCircle2, + iconColor: "edr-slate", + tile: "edr-slate-soft2", + hint: "Completed · awaiting delivery", + step: "edr-green.5", + badgeLabel: "Completed", + badgeBg: "edr-slate-soft2", + badgeText: "edr-slate", + badgeDot: "edr-step", + action: { label: "View", kind: "outline" }, + }, + DELIVERED: { stage: 4, icon: CheckCircle2, iconColor: "edr-slate", @@ -148,12 +303,38 @@ const STATUS_CONFIG: Record = { icon: FilePen, iconColor: "edr-red", tile: "edr-red-soft", - hint: "Rejected", + hint: "Rejected · contact support", step: "edr-red", badgeLabel: "Rejected", badgeBg: "edr-red-soft", badgeText: "edr-red", badgeDot: "edr-red", + action: { label: "Contact", kind: "outline" }, + }, + PENDING_CONSOLIDATION: { + stage: 3, + icon: Clock3, + iconColor: "edr-blue", + tile: "edr-blue-soft", + hint: "Awaiting consolidation", + step: "edr-blue-dot", + badgeLabel: "Consolidating", + badgeBg: "edr-blue-soft", + badgeText: "edr-blue", + badgeDot: "edr-blue-dot", + action: { label: "View", kind: "outline" }, + }, + CONSOLIDATED: { + stage: 3, + icon: CheckCircle2, + iconColor: "edr-green.7", + tile: "edr-soft", + hint: "Consolidated · ready for dispatch", + step: "edr-green.5", + badgeLabel: "Consolidated", + badgeBg: "edr-soft", + badgeText: "edr-green.7", + badgeDot: "edr-green.5", action: { label: "View", kind: "outline" }, }, }; @@ -256,16 +437,32 @@ export default function MyPortalPage() { - - - - Setup your Company Profile to start booking shipments and managing invoices. - - Get started - - . - - + + {!customer&& ( + + + + + Setup your Company Profile + + + Complete your company information to unlock all features and start booking shipments. + + + + + Complete Setup + + + + + + + + + + + )} {/* ── Stats Strip ───────────────────────────────────────────────────── */} From 570c5ee12516d19011ddc5976377dc5f52e21ab9 Mon Sep 17 00:00:00 2001 From: Nathnael Date: Tue, 16 Jun 2026 08:51:23 +0000 Subject: [PATCH 11/12] feat: setted up the renewal contract --- .../src/pages/bookings/NewBookingPage.tsx | 42 +++++++- .../bookings/new-booking-form/shared.tsx | 94 +++++++++++++++- .../new-booking-form/step1-contract-type.tsx | 102 ++++++++++++++++-- 3 files changed, 226 insertions(+), 12 deletions(-) diff --git a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx index 7de208301..513b93a45 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/NewBookingPage.tsx @@ -7,6 +7,7 @@ import { AlertCircle, Check, ChevronLeft, ChevronRight } from "lucide-react"; import { useMemo, useState } from "react"; import { useForm } from "react-hook-form"; import { useNavigate } from "react-router-dom"; +import useAuth from "@/hooks/useAuth"; import { BookingFormInputValues, STEPS, @@ -31,10 +32,49 @@ export default function NewBookingPage() { const navigate = useNavigate(); const queryClient = useQueryClient(); const [step, setStep] = useState(1); + const auth = useAuth(); const { data: referenceData, isLoading: refDataLoading } = useQuery( api.bookings.referenceData.queryOptions(), ); + if (!auth.isPending && !auth.company) { + return ( + + } + radius="md" + style={{ maxWidth: "500px" }} + mb="lg" + > + + Complete Your Company Setup + + + You need to complete your company onboarding before you can create + bookings. Please follow the onboarding process to get started. + + + + + ); + } + const createMutation = useMutation({ mutationFn: async (payload: CreateBookingPayload) => { const booking = await api.bookings.create.call(payload); @@ -264,7 +304,7 @@ export default function NewBookingPage() { )} - {step === 1 && } + {step === 1 && } {step === 2 && ( )} diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/shared.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/shared.tsx index e4b53cfd1..55b6eda44 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/shared.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/shared.tsx @@ -1,7 +1,8 @@ +import { Alert, Combobox, Input, InputBase, Select, Text, Title, useCombobox } from "@mantine/core"; +import { AlertTriangle, Check, CheckCircle2, Info, Loader, XCircle } from "lucide-react"; import type { ReactNode } from "react"; +import { useMemo } from "react"; import type { ControllerRenderProps, FieldError as RhfFieldError } from "react-hook-form"; -import { AlertTriangle, Check, CheckCircle2, Info, XCircle } from "lucide-react"; -import { Alert, Select, Text, Title } from "@mantine/core"; import type { BookingFormInputValues } from "./schema"; export function OptionFieldError({ error }: { error?: { message?: string } }) { @@ -124,3 +125,92 @@ export function SelectField({ /> ); } + +interface AsyncComboboxOption { + value: string; + label: string; +} + +export function AsyncComboboxField({ + field, + error, + label, + placeholder, + options, + isLoading, + searchQuery, + onSearchChange, + onSelect, + disabled, +}: { + field: ControllerRenderProps; + error?: RhfFieldError; + label: string; + placeholder: string; + options: AsyncComboboxOption[]; + isLoading?: boolean; + searchQuery: string; + onSearchChange: (query: string) => void; + onSelect: (value: string) => void; + disabled?: boolean; +}) { + const combobox = useCombobox(); + + const selectedLabel = useMemo(() => { + return options.find((opt) => opt.value === field.value)?.label || ""; + }, [field.value, options]); + + const handleSelectOption = (val: string) => { + onSelect(val); + combobox.closeDropdown(); + }; + + return ( + + + + { + onSearchChange(e.currentTarget.value); + combobox.openDropdown(); + }} + onFocus={() => combobox.openDropdown()} + onBlur={() => { + field.onBlur(); + combobox.closeDropdown(); + if (!selectedLabel) { + onSearchChange(""); + } + }} + rightSection={ + isLoading ? : + } + /> + + + + + {isLoading ? ( + Loading contracts... + ) : options.length === 0 ? ( + No contracts found + ) : ( + options.map((option) => ( + handleSelectOption(option.value)} + > + {option.label} + + )) + )} + + + + + ); +} diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step1-contract-type.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step1-contract-type.tsx index 1b4e91e3a..6070f6157 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step1-contract-type.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step1-contract-type.tsx @@ -1,23 +1,98 @@ -import { Controller, type UseFormReturn } from "react-hook-form"; +import { api } from "@/services/api"; +import type { Freight } from "@edr/types"; +import { useQuery } from "@tanstack/react-query"; import { FileText, RefreshCw } from "lucide-react"; +import { useMemo, useState } from "react"; +import { Controller, type UseFormReturn } from "react-hook-form"; import { BookingFormInputValues, - MOCK_VALID_CONTRACTS, type BookingFormValues, } from "./schema"; import { AlertBox, + AsyncComboboxField, OptionCard, OptionFieldError, - SelectField, StepHeader, } from "./shared"; type BookingForm = UseFormReturn; -export function Step1ContractType({ form }: { form: BookingForm }) { +interface PreviousContractOption { + value: string; + label: string; + booking: Freight.IBooking; +} + +export function Step1ContractType({ + form, + referenceData, +}: { + form: BookingForm; + referenceData?: Freight.BookingReferenceData; +}) { const contractType = form.watch("contractType"); const previousContractRef = form.watch("previousContractRef"); + const [searchQuery, setSearchQuery] = useState(""); + + const { data: bookings, isLoading, error } = useQuery( +api.bookings.list.queryOptions({ + input: { + + page: 1, + pageSize: 100, + sortBy: "createdAt", + sortOrder: "DESC", + } + }) + ); + + const contractOptions = useMemo(() => { + console.log("Bookings data:", bookings); + if(!bookings) return [] + + return bookings?.items + .map((booking) => { + const origin = booking.originYard?.label || "Unknown"; + const destination = booking.destinationYard?.label || "Unknown"; + return { + value: booking.reference, + label: `${booking.reference} - Route: ${origin} to ${destination}`, + booking, + }; + }) + .filter((opt) => + opt.label.toLowerCase().includes(searchQuery.toLowerCase()) + ); + }, [bookings, searchQuery]); + + const handleSelectContract = async (contractId: string) => { + const selected = contractOptions.find((opt) => opt.value === contractId); + if (!selected) return; + + form.setValue("previousContractRef", contractId); + + // Auto-fill from previous contract + const booking = selected.booking; + if (booking) { + form.setValue("originYard", booking.originYardId); + form.setValue("destinationYard", booking.destinationYardId); + form.setValue("serviceTypeId", booking.serviceTypeId); + form.setValue("cargoType", booking.freightType === "CONTAINER" ? "container" : "bulk"); + form.setValue("equipmentReturn", booking.equipmentReturn === "WITH_RETURN" ? "with_return" : "without_return"); + if (booking.isHazardous) form.setValue("isHazardous", booking.isHazardous); + + // Look up shipping line name from reference data + if (booking.shippingLineId && referenceData?.shipping_line) { + const shippingLine = referenceData.shipping_line.find( + (sl) => sl.id === booking.shippingLineId, + ); + if (shippingLine) { + form.setValue("shippingLine", shippingLine.name); + } + } + } + } return (
@@ -73,23 +148,32 @@ export function Step1ContractType({ form }: { form: BookingForm }) { {contractType === "renewal" && (
+ {error && ( + + Failed to load previous contracts. Please try again later. + + )} ( - )} /> {previousContractRef && ( - Contract found. Company details, route, and wagon - preferences will be pre-filled. + Contract found. Route, service type, and cargo + details will be pre-filled. )}
From 7044dcfb432e00cb1257fb042c509c9f64bd053c Mon Sep 17 00:00:00 2001 From: Nathnael Date: Tue, 16 Jun 2026 09:20:31 +0000 Subject: [PATCH 12/12] payment ui for booking --- .../bookings/BookingStatusBadge.tsx | 2 + .../detail/BookingPaymentCountdownCard.tsx | 92 +++++++++++ .../bookings/detail/booking-detail.styles.ts | 2 + .../src/components/bookings/detail/index.ts | 1 + .../bookings/booking-status.config.ts | 12 ++ .../src/pages/bookings/BookingDetailPage.tsx | 7 +- .../BookingDetailPage/ReadonlyBookingView.tsx | 22 ++- .../components/PaymentDeadlineCard.tsx | 144 ++++++++++++++++++ .../bookings/BookingDetailPage/constants.ts | 14 ++ .../new-booking-form/step1-contract-type.tsx | 4 +- packages/types/src/freight/index.ts | 8 + 11 files changed, 302 insertions(+), 6 deletions(-) create mode 100644 apps/edr-freight-web/backoffice/src/components/bookings/detail/BookingPaymentCountdownCard.tsx create mode 100644 apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/components/PaymentDeadlineCard.tsx diff --git a/apps/edr-freight-web/backoffice/src/components/bookings/BookingStatusBadge.tsx b/apps/edr-freight-web/backoffice/src/components/bookings/BookingStatusBadge.tsx index 4b801d99f..3d8a0792a 100644 --- a/apps/edr-freight-web/backoffice/src/components/bookings/BookingStatusBadge.tsx +++ b/apps/edr-freight-web/backoffice/src/components/bookings/BookingStatusBadge.tsx @@ -13,6 +13,8 @@ const statusColorMap: Record = { FULLY_EXECUTED: "indigo", PNR_GENERATED: "violet", PAYMENT_VERIFICATION_IN_PROGRESS: "yellow", + SELECTED_FOR_BATCH: "orange", + EXPIRED: "red", PAID: "green", IN_TRANSIT: "cyan", COMPLETED: "indigo", diff --git a/apps/edr-freight-web/backoffice/src/components/bookings/detail/BookingPaymentCountdownCard.tsx b/apps/edr-freight-web/backoffice/src/components/bookings/detail/BookingPaymentCountdownCard.tsx new file mode 100644 index 000000000..2242fb278 --- /dev/null +++ b/apps/edr-freight-web/backoffice/src/components/bookings/detail/BookingPaymentCountdownCard.tsx @@ -0,0 +1,92 @@ +import { useEffect, useState } from "react"; +import { Group, Stack, Text } from "@mantine/core"; +import { Timer } from "lucide-react"; + +import { SectionCard } from "./SectionCard"; + +export interface BookingPaymentCountdownCardProps { + /** ISO timestamp marking the end of the pay window. */ + paymentDeadline: string; +} + +interface Remaining { + days: number; + hours: number; + minutes: number; + seconds: number; + expired: boolean; +} + +function getRemaining(deadlineMs: number): Remaining { + const diff = deadlineMs - Date.now(); + if (diff <= 0) { + return { days: 0, hours: 0, minutes: 0, seconds: 0, expired: true }; + } + const totalSeconds = Math.floor(diff / 1000); + return { + days: Math.floor(totalSeconds / 86400), + hours: Math.floor((totalSeconds % 86400) / 3600), + minutes: Math.floor((totalSeconds % 3600) / 60), + seconds: totalSeconds % 60, + expired: false, + }; +} + +function Segment({ value, label }: { value: number; label: string }) { + return ( + + + {String(value).padStart(2, "0")} + + + {label} + + + ); +} + +/** Live countdown to the payment deadline. Ticks every second; shows an expired state past the deadline. */ +export function BookingPaymentCountdownCard({ paymentDeadline }: BookingPaymentCountdownCardProps) { + const deadlineMs = new Date(paymentDeadline).getTime(); + const [remaining, setRemaining] = useState(() => getRemaining(deadlineMs)); + + useEffect(() => { + setRemaining(getRemaining(deadlineMs)); + const interval = setInterval(() => { + const next = getRemaining(deadlineMs); + setRemaining(next); + if (next.expired) { + clearInterval(interval); + } + }, 1000); + return () => clearInterval(interval); + }, [deadlineMs]); + + const accent = remaining.expired ? "red" : "orange"; + + return ( + + {remaining.expired ? ( + + Expired + + ) : ( + + + + + + + )} + + ); +} diff --git a/apps/edr-freight-web/backoffice/src/components/bookings/detail/booking-detail.styles.ts b/apps/edr-freight-web/backoffice/src/components/bookings/detail/booking-detail.styles.ts index e12b7220b..c53cbccbd 100644 --- a/apps/edr-freight-web/backoffice/src/components/bookings/detail/booking-detail.styles.ts +++ b/apps/edr-freight-web/backoffice/src/components/bookings/detail/booking-detail.styles.ts @@ -137,6 +137,8 @@ export interface BookingDetailView { priorityScore: number; cargoTotalWeightVgm: number; pnrCode?: string | null; + /** End of the pay window once the booking is SELECTED_FOR_BATCH. */ + paymentDeadline?: string | null; createdAt: string; updatedAt: string; company?: BookingNamedRefView; diff --git a/apps/edr-freight-web/backoffice/src/components/bookings/detail/index.ts b/apps/edr-freight-web/backoffice/src/components/bookings/detail/index.ts index 06f3c1e5d..36d782730 100644 --- a/apps/edr-freight-web/backoffice/src/components/bookings/detail/index.ts +++ b/apps/edr-freight-web/backoffice/src/components/bookings/detail/index.ts @@ -9,6 +9,7 @@ export * from "./BookingContainersCard"; export * from "./BookingApprovalCard"; export * from "./BookingReviewNotesCard"; export * from "./BookingPaymentCard"; +export * from "./BookingPaymentCountdownCard"; export * from "./BookingFactsCard"; export * from "./BookingDocumentsCard"; export * from "./BookingRequestHero"; diff --git a/apps/edr-freight-web/backoffice/src/features/bookings/booking-status.config.ts b/apps/edr-freight-web/backoffice/src/features/bookings/booking-status.config.ts index a220c1f06..834dcee3e 100644 --- a/apps/edr-freight-web/backoffice/src/features/bookings/booking-status.config.ts +++ b/apps/edr-freight-web/backoffice/src/features/bookings/booking-status.config.ts @@ -50,6 +50,14 @@ export const BOOKING_STATUS_STYLES: Record = { label: "Payment Verification", color: "bg-amber-50 text-amber-800 border-amber-200", }, + SELECTED_FOR_BATCH: { + label: "Selected for Batch", + color: "bg-orange-50 text-orange-700 border-orange-200", + }, + EXPIRED: { + label: "Expired", + color: "bg-red-50 text-red-700 border-red-200", + }, PAID: { label: "Paid", color: "bg-[color:var(--freight-brand-muted)] text-[color:var(--freight-brand)] border-[color:var(--freight-brand-border)]", @@ -241,6 +249,8 @@ export const BOOKING_LIST_TABS = [ "FULLY_EXECUTED", "PNR_GENERATED", "PAYMENT_VERIFICATION_IN_PROGRESS", + "SELECTED_FOR_BATCH", + "EXPIRED", ], }, { @@ -270,6 +280,8 @@ export const WORKFLOW_STAGES = [ "FULLY_EXECUTED", "PNR_GENERATED", "PAYMENT_VERIFICATION_IN_PROGRESS", + "SELECTED_FOR_BATCH", + "EXPIRED", ], }, { diff --git a/apps/edr-freight-web/backoffice/src/pages/bookings/BookingDetailPage.tsx b/apps/edr-freight-web/backoffice/src/pages/bookings/BookingDetailPage.tsx index e225bea0b..42cde3d90 100644 --- a/apps/edr-freight-web/backoffice/src/pages/bookings/BookingDetailPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/bookings/BookingDetailPage.tsx @@ -9,6 +9,7 @@ import { BookingFactsCard, BookingLifecycleStepper, BookingPaymentCard, + BookingPaymentCountdownCard, BookingReviewNotesCard, BookingRouteCard, detailStyles, @@ -24,8 +25,9 @@ const BookingDetailPage = () => { const booking: BookingDetailView = { id: id || "a61955b7-af21-4664-84d3-7e4e66293b6f", reference: "BKG-2026-001456", - status: "IN_TRANSIT", + status: "SELECTED_FOR_BATCH", scheduledDate: "2026-06-15", + paymentDeadline: "2026-06-18T17:00:00Z", totalAmount: 15750.5, paymentCurrency: "USD", paymentStatus: "PAID", @@ -137,6 +139,9 @@ const BookingDetailPage = () => { {/* RIGHT — summary sidebar */} + {booking.status === "SELECTED_FOR_BATCH" && booking.paymentDeadline && ( + + )} } @@ -70,6 +74,13 @@ export function ReadonlyBookingView({ booking }: { booking: Freight.IBooking }) reason={booking.latestChangeRequestNote} onRebook={() => navigate("/bookings/new")} /> + ) : isExpired ? ( + navigate("/bookings/new")} + /> ) : ( )} @@ -114,6 +125,13 @@ export function ReadonlyBookingView({ booking }: { booking: Freight.IBooking }) } right={ <> + {showCountdown && ( + payMutation.mutate()} + paying={payMutation.isPending} + /> + )} + + {String(value).padStart(2, "0")} + + + {label} + + + ); +} + +export function PaymentDeadlineCard({ + paymentDeadline, + onPay, + paying, +}: { + /** ISO timestamp marking the end of the pay window. */ + paymentDeadline: string; + onPay?: () => void; + paying?: boolean; +}) { + const deadlineMs = new Date(paymentDeadline).getTime(); + const [remaining, setRemaining] = useState(() => getRemaining(deadlineMs)); + + useEffect(() => { + setRemaining(getRemaining(deadlineMs)); + const interval = setInterval(() => { + const next = getRemaining(deadlineMs); + setRemaining(next); + if (next.expired) clearInterval(interval); + }, 1000); + return () => clearInterval(interval); + }, [deadlineMs]); + + const accentBg = remaining.expired ? "#FBEAE7" : "#FDF3E0"; + const accentFg = remaining.expired ? "#C0392B" : "#9A5B00"; + + return ( + + + Payment deadline + + + {remaining.expired ? "Expired" : "Pay window open"} + + + + {remaining.expired ? ( + + The payment window has closed. Move this booking to another schedule or + contact support. + + ) : ( + <> + + + + + + + + Complete payment before the window closes to secure your slot. + + {onPay && ( + + )} + + )} + + + + Deadline:{" "} + {new Date(paymentDeadline).toLocaleString(undefined, { + month: "short", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + })} + + + ); +} diff --git a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/constants.ts b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/constants.ts index 80f0b7ab2..c6e19fb9b 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/constants.ts +++ b/apps/edr-freight-web/portal/src/pages/bookings/BookingDetailPage/constants.ts @@ -32,6 +32,8 @@ export const PROGRESS_STAGES = [ label: "In Transit", icon: Train, statuses: [ + "SELECTED_FOR_BATCH", + "EXPIRED", "PNR_GENERATED", "PAYMENT_VERIFICATION_IN_PROGRESS", "PAID", @@ -99,6 +101,18 @@ export const STATUS_MAP: Record< description: "Signed by all parties. You can now proceed to payment.", stage: 2, }, + SELECTED_FOR_BATCH: { + title: "Selected for a train — payment due", + description: + "Your booking was selected for a scheduled train. Complete payment within the pay window to secure your slot.", + stage: 3, + }, + EXPIRED: { + title: "Pay window expired", + description: + "The payment window was missed. You can move this booking to another schedule or cancel it.", + stage: 3, + }, PNR_GENERATED: { title: "Payment reference generated", description: diff --git a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step1-contract-type.tsx b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step1-contract-type.tsx index 6070f6157..55b81a816 100644 --- a/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step1-contract-type.tsx +++ b/apps/edr-freight-web/portal/src/pages/bookings/new-booking-form/step1-contract-type.tsx @@ -56,7 +56,7 @@ api.bookings.list.queryOptions({ const origin = booking.originYard?.label || "Unknown"; const destination = booking.destinationYard?.label || "Unknown"; return { - value: booking.reference, + value: booking.id, label: `${booking.reference} - Route: ${origin} to ${destination}`, booking, }; @@ -75,8 +75,6 @@ api.bookings.list.queryOptions({ // Auto-fill from previous contract const booking = selected.booking; if (booking) { - form.setValue("originYard", booking.originYardId); - form.setValue("destinationYard", booking.destinationYardId); form.setValue("serviceTypeId", booking.serviceTypeId); form.setValue("cargoType", booking.freightType === "CONTAINER" ? "container" : "bulk"); form.setValue("equipmentReturn", booking.equipmentReturn === "WITH_RETURN" ? "with_return" : "without_return"); diff --git a/packages/types/src/freight/index.ts b/packages/types/src/freight/index.ts index a3c4f1a59..6672f95e9 100644 --- a/packages/types/src/freight/index.ts +++ b/packages/types/src/freight/index.ts @@ -282,6 +282,9 @@ export interface IBooking extends BaseEntity { totalAmount: number; paymentStatus: PaymentStatus; + shippingLineId?: string | null; + serviceTypeId: string; + contractType: "NEW" | "RENEWAL"; previousContractId?: string | null; serviceType: "RAIL_ONLY" | "RAIL_AND_FORWARDING"; @@ -311,6 +314,11 @@ export interface IBooking extends BaseEntity { endDate?: string | null; financialTerms?: string | null; + /** When the batch engine picked this booking and opened the pay window. */ + selectedForBatchAt?: string | null; + /** End of the pay window once the booking is SELECTED_FOR_BATCH. */ + paymentDeadline?: string | null; + containers?: Array<{ type: string; qty: number; vgm: number }> | null; versionNumber: number;