mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 09:30:59 +00:00
interchange document generation and acknowledgement
This commit is contained in:
@@ -77,6 +77,7 @@ import WarehouseInventoryPage from "./pages/warehouses/WarehouseInventoryPage";
|
||||
import WarehouseInvoicesPage from "./pages/warehouses/WarehouseInvoicesPage";
|
||||
import WarehouseListPage from "./pages/warehouses/WarehouseListPage";
|
||||
import WarehouseRulesPage from "./pages/warehouses/WarehouseRulesPage";
|
||||
import { HealthCheck } from "./features/health/HealthCheck";
|
||||
|
||||
const buildSidebarSections = (demoItems: SidebarItem[]): SidebarSection[] => [
|
||||
{
|
||||
@@ -374,6 +375,7 @@ const App = () => {
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/um/*" element={<UserManagementHostPage />} />
|
||||
<Route path="/health" element={<HealthCheck />} />
|
||||
<Route path="/" element={<Navigate to="/dashboard/overview" replace />} />
|
||||
<Route path="/dashboard" element={<Navigate to="/dashboard/overview" replace />} />
|
||||
<Route path="/dashboard" element={<DashboardShell />}>
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
LayoutGrid,
|
||||
Package,
|
||||
} from "lucide-react";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useMemo } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
@@ -84,9 +84,6 @@ export default function CustomerDetailPage() {
|
||||
enabled: Boolean(id),
|
||||
}),
|
||||
);
|
||||
const approveMutation = useMutation(
|
||||
api.customers.setCompanyStatus.mutationOptions(),
|
||||
);
|
||||
const bookingsQuery = useQuery(
|
||||
api.customers.bookings.queryOptions({
|
||||
input: { id: id ?? "" },
|
||||
@@ -394,28 +391,12 @@ export default function CustomerDetailPage() {
|
||||
]}
|
||||
backTo="/dashboard/customers"
|
||||
title={company.name}
|
||||
subtitle={`TIN ${company.tin}${
|
||||
company.country ? ` · ${company.country}` : ""
|
||||
}`}
|
||||
subtitle={`TIN ${company.tin}${company.country ? ` · ${company.country}` : ""
|
||||
}`}
|
||||
meta={
|
||||
<Group gap="xs" wrap="nowrap">
|
||||
<CompanyTypeBadge type={company.type} />
|
||||
<CompanyStatusBadge status={company.status} />
|
||||
{company.status === "pending" && (
|
||||
<Button
|
||||
size="xs"
|
||||
color="green"
|
||||
loading={approveMutation.isPending}
|
||||
onClick={() =>
|
||||
approveMutation.mutate({
|
||||
companyId: company.id,
|
||||
status: "active",
|
||||
})
|
||||
}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
)}
|
||||
</Group>
|
||||
}
|
||||
/>
|
||||
@@ -546,9 +527,9 @@ export default function CustomerDetailPage() {
|
||||
error={
|
||||
bookingsQuery.isError
|
||||
? {
|
||||
message: "Failed to load bookings.",
|
||||
onRetry: () => void bookingsQuery.refetch(),
|
||||
}
|
||||
message: "Failed to load bookings.",
|
||||
onRetry: () => void bookingsQuery.refetch(),
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
@@ -567,9 +548,9 @@ export default function CustomerDetailPage() {
|
||||
error={
|
||||
documentsQuery.isError
|
||||
? {
|
||||
message: "Failed to load documents.",
|
||||
onRetry: () => void documentsQuery.refetch(),
|
||||
}
|
||||
message: "Failed to load documents.",
|
||||
onRetry: () => void documentsQuery.refetch(),
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
@@ -588,9 +569,9 @@ export default function CustomerDetailPage() {
|
||||
error={
|
||||
paymentsQuery.isError
|
||||
? {
|
||||
message: "Failed to load payments.",
|
||||
onRetry: () => void paymentsQuery.refetch(),
|
||||
}
|
||||
message: "Failed to load payments.",
|
||||
onRetry: () => void paymentsQuery.refetch(),
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -1,23 +1,34 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { createRoot, type Root } from "react-dom/client";
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
import {
|
||||
UserManagementApp,
|
||||
type UserManagementRuntimeOptions,
|
||||
type UserManagementSessionSeed,
|
||||
} from "@tria-plc/iamui";
|
||||
} from '@tria-plc/iamui';
|
||||
import { iamConfig } from './iamConfig';
|
||||
|
||||
import { getCookie } from "@/auth/cookies";
|
||||
function readCookieValue(name: string): string | null {
|
||||
const escaped = name.replace(/([.$?*|{}()[\]\\/+^])/g, '\\$1');
|
||||
const match = document.cookie.match(
|
||||
new RegExp(`(?:^|; )${escaped}=([^;]*)`),
|
||||
);
|
||||
|
||||
import { iamConfig } from "./iamConfig";
|
||||
return match ? decodeURIComponent(match[1]) : null;
|
||||
}
|
||||
|
||||
function readInitialSession(): UserManagementSessionSeed | null {
|
||||
const token = getCookie("auth-token");
|
||||
const token =
|
||||
localStorage.getItem('fhc-backoffice-auth-token') ??
|
||||
readCookieValue('auth-token');
|
||||
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const refreshToken = getCookie("refresh-token") ?? undefined;
|
||||
const refreshToken =
|
||||
localStorage.getItem('fhc-backoffice-auth-refresh-token') ??
|
||||
readCookieValue('refresh-token') ??
|
||||
undefined;
|
||||
|
||||
return {
|
||||
token,
|
||||
@@ -47,15 +58,14 @@ export default function UserManagementHostPage() {
|
||||
rootRef.current = createRoot(mountNode);
|
||||
}
|
||||
|
||||
const apiBaseUrl = import.meta.env.VITE_BASE_API_URL.replace(/\/+$/, "");
|
||||
const iamApiUrl = "/um-api";
|
||||
const apiBaseUrl = import.meta.env.VITE_BASE_API_URL.replace(/\/+$/, '');
|
||||
const runtime: UserManagementRuntimeOptions = {
|
||||
basename: "/um",
|
||||
basename: '/um',
|
||||
apiBaseUrl,
|
||||
apiUrl: iamApiUrl,
|
||||
recordApiUrl: iamApiUrl,
|
||||
chronicleUrl: iamApiUrl,
|
||||
auditApiUrl: iamApiUrl,
|
||||
apiUrl: `${apiBaseUrl}/api`,
|
||||
recordApiUrl: `${apiBaseUrl}/api`,
|
||||
chronicleUrl: `${apiBaseUrl}/api`,
|
||||
auditApiUrl: `${apiBaseUrl}/api`,
|
||||
};
|
||||
|
||||
rootRef.current.render(
|
||||
@@ -78,5 +88,5 @@ export default function UserManagementHostPage() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
return <div ref={mountRef} style={{ position: "fixed", inset: 0 }} />;
|
||||
return <div ref={mountRef} style={{ position: 'fixed', inset: 0 }} />;
|
||||
}
|
||||
|
||||
@@ -379,6 +379,9 @@ const FirstMilePage = () => {
|
||||
mutationFn: async ({ reference, vehicleId }: { reference: string; vehicleId: string | null }) => {
|
||||
const res = await firstMileService.accept(reference);
|
||||
const created = res.data;
|
||||
if (!created?.id) {
|
||||
throw new Error("First-mile leg was not created for this booking.");
|
||||
}
|
||||
if (vehicleId) await firstMileService.update(created.id, { vehicleId });
|
||||
return created;
|
||||
},
|
||||
@@ -387,8 +390,11 @@ const FirstMilePage = () => {
|
||||
toast({ title: "Booking accepted", description: "First-mile leg created successfully." });
|
||||
closeAccept();
|
||||
},
|
||||
onError: () => {
|
||||
toast({ title: "Accept failed", variant: "destructive" });
|
||||
onError: (err: unknown) => {
|
||||
const description =
|
||||
(err as { response?: { data?: { message?: string } } })?.response?.data?.message ??
|
||||
(err instanceof Error ? err.message : undefined);
|
||||
toast({ title: "Accept failed", description, variant: "destructive" });
|
||||
},
|
||||
});
|
||||
|
||||
@@ -407,7 +413,6 @@ const FirstMilePage = () => {
|
||||
paidBookings.filter(
|
||||
(booking) =>
|
||||
booking.tradeDirection === "EXPORT" &&
|
||||
Boolean(booking.firstMilePickupAddress?.trim()) &&
|
||||
!existingFirstMileBookingIds.has(booking.id),
|
||||
),
|
||||
[existingFirstMileBookingIds, paidBookings],
|
||||
|
||||
Reference in New Issue
Block a user