mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-06 07:43:38 +00:00
Currency dropdowns/pickers (AdditionalPaymentsTab, ClearanceChargesTab, PhasedClearanceActionPanel, AdviseDutyCard, ContractRequestsPage, ruleEngine/resources, WarehouseRulesPage, VehicleDetailPage, FeePreviewModal) offer DJF alongside ETB/USD; GlCreateBookingForm's currency selector gets allowDjf next to allowUsd. Narrow 'ETB'|'USD' type unions widened to include 'DJF' across the warehouse billingCurrency plumbing (useWarehouses, warehouse.service, api.ts) and the customer/invoice types. Ad-hoc money() formatters (BookingTrucksPanel, AccrualDashboard, ImportTrucksPage, EmptyReturnRequestsPage) and formatMoney call sites that hardcoded 2 decimals (wagon-cancellation cards, BookingRequestDetailPage, WagonCancellationsPage, PaymentsPage, WarehouseInvoicesPage) now use currencyDecimals() from @edr/ui-common so DJF renders with 0 decimals instead of forced cents. The 3 duplicate overview formatCurrency/ formatAmount helpers (typed 'ETB'|'USD') widen to accept any currency. Two correctness fixes: OverviewRecentBookingsTable's currency==='USD' ? 'USD' : 'ETB' was mislabeling every non-USD currency as ETB; and WarehouseInvoicesPage's gateway-method default now routes any non-ETB currency (not just USD) to WAAFI, so DJF invoices get a working default instead of TELEBIRR (ETB-only). Claude-Session: https://claude.ai/code/session_01CZy77vCWhka3pnmVF9NDkL
114 lines
3.6 KiB
TypeScript
114 lines
3.6 KiB
TypeScript
import { History } from "lucide-react";
|
|
import { Link, useNavigate } from "react-router-dom";
|
|
import { Table, Text } from "@mantine/core";
|
|
|
|
import { BookingPriorityBadge } from "@/components/bookings/BookingPriorityBadge";
|
|
import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
|
|
import type { IOverviewRecentBooking } from "@/types/overview";
|
|
import { SummaryCard } from "./summary/SummaryCard";
|
|
|
|
function formatAmount(amount: number | null, currency: string | null) {
|
|
if (amount == null) return "—";
|
|
return new Intl.NumberFormat("en-US", {
|
|
style: "currency",
|
|
currency: currency || "ETB",
|
|
maximumFractionDigits: 0,
|
|
}).format(amount);
|
|
}
|
|
|
|
export function OverviewRecentBookingsTable({
|
|
bookings,
|
|
}: {
|
|
bookings: IOverviewRecentBooking[];
|
|
}) {
|
|
const navigate = useNavigate();
|
|
|
|
return (
|
|
<SummaryCard
|
|
icon={History}
|
|
accent="gray"
|
|
title="Recent bookings"
|
|
subtitle="Latest submissions, newest first"
|
|
minHeight={260}
|
|
action={
|
|
<Text
|
|
component={Link}
|
|
to="/dashboard/booking-requests"
|
|
size="xs"
|
|
fw={600}
|
|
c="edr-green"
|
|
style={{ whiteSpace: "nowrap", textDecoration: "none" }}
|
|
>
|
|
View all →
|
|
</Text>
|
|
}
|
|
>
|
|
{bookings.length === 0 ? (
|
|
<Text size="sm" c="dimmed" ta="center" py="lg">
|
|
No recent bookings
|
|
</Text>
|
|
) : (
|
|
<Table highlightOnHover verticalSpacing="sm" horizontalSpacing="sm">
|
|
<Table.Thead>
|
|
<Table.Tr>
|
|
{["Reference", "Customer", "Status", "Priority", "Amount", "Created"].map(
|
|
(header) => (
|
|
<Table.Th
|
|
key={header}
|
|
style={{
|
|
fontSize: 11,
|
|
fontWeight: 700,
|
|
textTransform: "uppercase",
|
|
letterSpacing: 0.3,
|
|
color: "var(--mantine-color-edr-muted-6)",
|
|
borderBottom: "1px solid var(--mantine-color-gray-2)",
|
|
}}
|
|
>
|
|
{header}
|
|
</Table.Th>
|
|
),
|
|
)}
|
|
</Table.Tr>
|
|
</Table.Thead>
|
|
<Table.Tbody>
|
|
{bookings.map((booking) => (
|
|
<Table.Tr
|
|
key={booking.id}
|
|
style={{ cursor: "pointer" }}
|
|
onClick={() => navigate(`/dashboard/booking-requests/${booking.id}`)}
|
|
>
|
|
<Table.Td>
|
|
<Text fw={600} size="sm">
|
|
{booking.reference}
|
|
</Text>
|
|
</Table.Td>
|
|
<Table.Td>
|
|
<Text size="sm" truncate style={{ maxWidth: 180 }}>
|
|
{booking.customerLabel}
|
|
</Text>
|
|
</Table.Td>
|
|
<Table.Td>
|
|
<BookingStatusBadge status={booking.status} />
|
|
</Table.Td>
|
|
<Table.Td>
|
|
<BookingPriorityBadge score={booking.priorityScore} />
|
|
</Table.Td>
|
|
<Table.Td>
|
|
<Text size="sm" style={{ fontVariantNumeric: "tabular-nums" }}>
|
|
{formatAmount(booking.totalAmount, booking.paymentCurrency)}
|
|
</Text>
|
|
</Table.Td>
|
|
<Table.Td>
|
|
<Text size="sm" c="dimmed">
|
|
{new Date(booking.createdAt).toLocaleDateString()}
|
|
</Text>
|
|
</Table.Td>
|
|
</Table.Tr>
|
|
))}
|
|
</Table.Tbody>
|
|
</Table>
|
|
)}
|
|
</SummaryCard>
|
|
);
|
|
}
|