feat(bookings): enhance booking filtering and pagination

- Added createdFrom and createdTo filters to BookingListFilterOptions and FilterBookingDto for date range filtering.
- Updated BookingsService and BookingsRepository to handle pagination metadata in responses.
- Enhanced BookingsController to return pagination metadata when no company is linked.
- Introduced ModeIndicator component to display current operational mode across various pages.
- Added ContainersCard and KeyFactsStrip components for detailed booking views.
- Implemented CargoModeCell, BookingTypeBadge, and PaymentBadge for consistent display of booking attributes.
- Updated MyBookings and ContractsList pages to include new filters and display enhancements.
This commit is contained in:
Marshal
2026-06-21 07:41:04 +00:00
parent f82dad3657
commit 171e02cf7f
16 changed files with 763 additions and 42 deletions

View File

@@ -41,6 +41,7 @@ import {
type ReactNode,
useState,
} from "react";
import { PROFILE_TYPE_LABELS } from "@/constants/profileMode";
export interface SidebarItem {
label: string;
@@ -79,14 +80,6 @@ type SwitchResult =
| { success: true; data?: unknown }
| { success: false; error?: { message?: string } };
const PROFILE_TYPE_LABELS: Record<string, string> = {
importer: "Importer",
exporter: "Exporter",
freight_forwarder: "Freight Forwarder",
dj_freight_forwarder: "DJ Freight Forwarder",
transporter: "Transporter",
};
function getInitials(name: string): string {
return name
.split(" ")
@@ -813,8 +806,7 @@ export function AppLayout({
<Text size="sm" c="dimmed">
You don't have an {modeLabel(targetMode).toLowerCase()} profile yet.
Add your business license to create one and switch to{" "}
{modeLabel(targetMode).toLowerCase()} mode. A new reference will be
generated automatically.
{modeLabel(targetMode).toLowerCase()} mode.
</Text>
<FileInput
label="Business license"

View File

@@ -0,0 +1,55 @@
import { Badge, Tooltip } from "@mantine/core";
import { ArrowDownToLine, ArrowUpFromLine } from "lucide-react";
import useAuth from "@/hooks/useAuth";
import { modeDataDescription, modeDataLabel } from "@/constants/profileMode";
interface ModeIndicatorProps {
/** Mantine size token for the badge. */
size?: "sm" | "md" | "lg";
}
/**
* Small pill showing which operational mode's data is currently on screen
* (Import / Export). The data itself is scoped server-side by the active
* profile; this just makes the scope visible. Switching is done via the header
* button — this is read-only.
*
* Renders nothing for non-customer companies or when no import/export mode is
* active, so it never interferes with forwarders or not-yet-onboarded users.
*/
export function ModeIndicator({ size = "md" }: ModeIndicatorProps) {
const { companyType, activeProfileType } = useAuth();
if (companyType !== "customer") return null;
const label = modeDataLabel(activeProfileType);
if (!label) return null;
const isImport = activeProfileType === "importer";
return (
<Tooltip label={modeDataDescription(activeProfileType)} withArrow>
<Badge
size={size}
radius="sm"
variant="light"
color={isImport ? "edr-green" : "blue"}
leftSection={
isImport ? (
<ArrowDownToLine size={13} />
) : (
<ArrowUpFromLine size={13} />
)
}
styles={{
root: { textTransform: "none", letterSpacing: 0, fontWeight: 600 },
}}
>
Viewing: {label}
</Badge>
</Tooltip>
);
}
export default ModeIndicator;