mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 16:35:42 +00:00
feat(bookings): add Additional Payments tab, add-charge modal, portal pay
Backoffice: new tab on the booking detail page (?tab=additional-charges, already linked from the row menu) with an Add Charge modal — Save draft or Send to customer. Portal: charges panel on the booking detail page, Pay now per charge via the existing OTP/CBE-bill payment flow. Also fixes: GET /bookings/:id/additional-charges was returning DRAFT charges to the customer (hidden client-side only) — now filtered server-side per caller.
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
Milestone,
|
||||
MoreHorizontal,
|
||||
Package,
|
||||
Receipt,
|
||||
RefreshCw,
|
||||
Ship,
|
||||
Truck,
|
||||
@@ -64,6 +65,7 @@ import {
|
||||
ContractOrdersPanel,
|
||||
} from "@/components/bookings/detail";
|
||||
import { WarehouseInfoCard } from "@/components/warehouses";
|
||||
import { AdditionalPaymentsTab } from "@/components/bookings/AdditionalPaymentsTab";
|
||||
import { getStatusMeta } from "@/features/bookings/booking-status.config";
|
||||
import { toBookingListRow } from "@/features/bookings/mapBookingListRow";
|
||||
import { formatDateTime, formatMoney } from "@/lib/format";
|
||||
@@ -74,7 +76,10 @@ import {
|
||||
useBookingMutations,
|
||||
} from "@/hooks/bookings/useBookings";
|
||||
import { useScrollToHash } from "@/hooks/useScrollToHash";
|
||||
import { useFileViewer } from "@/hooks/useFileViewer";
|
||||
import { bookingsService } from "@/services/bookings.service";
|
||||
import { useAuth } from "@/auth/useAuth";
|
||||
import { FREIGHT_PERMS, hasPermission as hasFreightPermission } from "@/lib/permissions";
|
||||
|
||||
export default function BookingRequestDetailPage() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
@@ -82,6 +87,12 @@ export default function BookingRequestDetailPage() {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
// Deep-link from a warehouse fee invoice → this booking's warehouse section.
|
||||
useScrollToHash();
|
||||
const { view, viewer } = useFileViewer();
|
||||
const { user } = useAuth();
|
||||
const canSeeAdditionalCharges = hasFreightPermission(
|
||||
user,
|
||||
FREIGHT_PERMS.additionalCharges.view,
|
||||
);
|
||||
|
||||
// Consolidated pair: `?booking=<partnerId>` swaps the WHOLE page over to the
|
||||
// other half of the shared wagon. Everything below — KPIs, stepper, the
|
||||
@@ -206,7 +217,9 @@ export default function BookingRequestDetailPage() {
|
||||
? "documents"
|
||||
: requestedTab === "trucks"
|
||||
? "trucks"
|
||||
: "overview";
|
||||
: requestedTab === "additional-charges"
|
||||
? "additional-charges"
|
||||
: "overview";
|
||||
const setActiveTab = (tab: string | null) => {
|
||||
const next = new URLSearchParams(searchParams);
|
||||
if (tab && tab !== "overview") next.set("tab", tab);
|
||||
@@ -509,6 +522,14 @@ export default function BookingRequestDetailPage() {
|
||||
<Tabs.Tab value="trucks" leftSection={<Truck size={16} />}>
|
||||
Trucks
|
||||
</Tabs.Tab>
|
||||
{canSeeAdditionalCharges && (
|
||||
<Tabs.Tab
|
||||
value="additional-charges"
|
||||
leftSection={<Receipt size={16} />}
|
||||
>
|
||||
Additional payments
|
||||
</Tabs.Tab>
|
||||
)}
|
||||
</Tabs.List>
|
||||
|
||||
<Tabs.Panel value="overview">
|
||||
@@ -528,6 +549,11 @@ export default function BookingRequestDetailPage() {
|
||||
<Tabs.Panel value="trucks">
|
||||
<BookingTrucksPanel bookingId={booking.id} />
|
||||
</Tabs.Panel>
|
||||
{canSeeAdditionalCharges && (
|
||||
<Tabs.Panel value="additional-charges">
|
||||
<AdditionalPaymentsTab bookingId={booking.id} onViewFile={view} />
|
||||
</Tabs.Panel>
|
||||
)}
|
||||
</Tabs>
|
||||
</Grid.Col>
|
||||
|
||||
@@ -562,6 +588,7 @@ export default function BookingRequestDetailPage() {
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Stack>
|
||||
{viewer}
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user