diff --git a/apps/edr-freight-web/backoffice/src/pages/customers/CustomerDetailPage.tsx b/apps/edr-freight-web/backoffice/src/pages/customers/CustomerDetailPage.tsx
index 317f915fb..5d0655f8d 100644
--- a/apps/edr-freight-web/backoffice/src/pages/customers/CustomerDetailPage.tsx
+++ b/apps/edr-freight-web/backoffice/src/pages/customers/CustomerDetailPage.tsx
@@ -7,6 +7,7 @@ import {
Card,
Center,
Container,
+ Divider,
Group,
Loader,
SimpleGrid,
@@ -90,6 +91,9 @@ function tableStatus(query: { isLoading: boolean; isError: boolean }) {
return query.isLoading ? "loading" : query.isError ? "error" : "success";
}
+/** Matches the fileKey seeded in the API's file-upload-settings seeder. */
+const POA_DELEGATION_CODE = "poa_delegation_letter";
+
export default function CustomerDetailPage() {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
@@ -531,6 +535,26 @@ export default function CustomerDetailPage() {
(p) => p.licenseFiles && p.licenseFiles.length > 0,
);
+ const poaDocuments = useMemo(
+ () => documents.filter((d) => d.code === POA_DELEGATION_CODE),
+ [documents],
+ );
+ const poaFields = [
+ { label: "PoA name", value: company?.poaName },
+ { label: "PoA email", value: company?.poaEmail },
+ { label: "PoA phone", value: company?.poaPhone },
+ { label: "PoA location", value: company?.poaLocation },
+ { label: "PoA address", value: company?.poaAddress },
+ ];
+ const hasPoaDetails = poaFields.some((f) => f.value?.trim());
+ // A freight forwarder acts on other companies' behalf, so its PoA — details
+ // and delegation letter both — is mandatory rather than optional.
+ const poaMandatory = (company?.companyProfiles ?? []).some(
+ (p) => p.type === "freight_forwarder",
+ );
+ const delegationMissing =
+ (hasPoaDetails || poaMandatory) && poaDocuments.length === 0;
+
if (isLoading) {
return (
@@ -672,6 +696,149 @@ export default function CustomerDetailPage() {
+
+
+
+
+
+ Power of Attorney
+
+ {poaMandatory && (
+
+ Required for freight forwarder
+
+ )}
+
+ {delegationMissing ? (
+
+ Delegation letter missing
+
+ ) : poaDocuments.length > 0 ? (
+
+ Delegation letter on file
+
+ ) : (
+
+ Not provided
+
+ )}
+
+
+ {hasPoaDetails ? (
+
+ {poaFields.map((f) => (
+
+ ))}
+
+ ) : (
+
+ No Power of Attorney representative recorded for this
+ customer.
+
+ )}
+
+
+
+
+
+ Delegation letter
+
+
+ {documentsQuery.isLoading ? (
+
+
+
+ Loading documents…
+
+
+ ) : documentsQuery.isError ? (
+
+
+ Failed to load documents.
+
+ void documentsQuery.refetch()}
+ >
+ Retry
+
+
+ ) : poaDocuments.length === 0 ? (
+
+ No delegation letter uploaded.
+
+ ) : (
+ poaDocuments.map((doc) => (
+
+
+
+
+ view({
+ name: doc.name,
+ url: fileViewUrl(doc.id),
+ mimeType: doc.mimeType,
+ })
+ }
+ >
+ {doc.name}
+
+
+ {formatBytes(doc.size)} ·{" "}
+ {formatDate(doc.uploadedAt)}
+
+
+
+
+ view({
+ name: doc.name,
+ url: fileViewUrl(doc.id),
+ mimeType: doc.mimeType,
+ })
+ }
+ >
+
+
+
+
+
+
+
+ ))
+ )}
+
+
+
+
diff --git a/apps/edr-freight-web/backoffice/src/services/customers.service.ts b/apps/edr-freight-web/backoffice/src/services/customers.service.ts
index 0476d41bb..c9a649946 100644
--- a/apps/edr-freight-web/backoffice/src/services/customers.service.ts
+++ b/apps/edr-freight-web/backoffice/src/services/customers.service.ts
@@ -33,6 +33,11 @@ function mapCompany(dto: Record): Company {
generalManagerName: (attrs.generalManagerName as string | null) ?? null,
generalManagerEmail: (attrs.generalManagerEmail as string | null) ?? null,
generalManagerPhone: (attrs.generalManagerPhone as string | null) ?? null,
+ poaName: (attrs.poaName as string | null) ?? null,
+ poaEmail: (attrs.poaEmail as string | null) ?? null,
+ poaPhone: (attrs.poaPhone as string | null) ?? null,
+ poaLocation: (attrs.poaLocation as string | null) ?? null,
+ poaAddress: (attrs.poaAddress as string | null) ?? null,
};
}
diff --git a/apps/edr-freight-web/backoffice/src/types/customer.ts b/apps/edr-freight-web/backoffice/src/types/customer.ts
index 7328decf0..5931ea5d6 100644
--- a/apps/edr-freight-web/backoffice/src/types/customer.ts
+++ b/apps/edr-freight-web/backoffice/src/types/customer.ts
@@ -127,6 +127,11 @@ export interface Company {
generalManagerName?: string | null;
generalManagerEmail?: string | null;
generalManagerPhone?: string | null;
+ poaName?: string | null;
+ poaEmail?: string | null;
+ poaPhone?: string | null;
+ poaLocation?: string | null;
+ poaAddress?: string | null;
website?: string | null;
attributes?: Record | null;
companyProfiles: CompanyProfile[];