mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 12:18:11 +00:00
feat: add poa to the changes approval
This commit is contained in:
@@ -153,6 +153,7 @@ export function ChangeRequestReview({ company }: { company: Company }) {
|
||||
: ([] as string[]);
|
||||
const docCount = pending?.documentFileIds?.length ?? 0;
|
||||
const licenseChanges = pending?.licenseChanges ?? [];
|
||||
const documentChanges = pending?.documentChanges ?? [];
|
||||
|
||||
const confirmReject = () => {
|
||||
if (!rejectId) return;
|
||||
@@ -210,11 +211,75 @@ export function ChangeRequestReview({ company }: { company: Company }) {
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{documentChanges.length > 0 && (
|
||||
<Stack gap={8}>
|
||||
<Text size="sm" fw={600} c="edr-text">
|
||||
Document changes
|
||||
</Text>
|
||||
{documentChanges.map((c, i) => (
|
||||
<Group key={`${c.fileId}-${i}`} gap={8} wrap="nowrap">
|
||||
{c.op === "add" ? (
|
||||
<FilePlus2 size={15} className="text-edr-muted" />
|
||||
) : (
|
||||
<FileX2 size={15} className="text-edr-muted" />
|
||||
)}
|
||||
<Badge
|
||||
size="sm"
|
||||
radius="sm"
|
||||
variant="light"
|
||||
color={c.op === "add" ? "green" : "red"}
|
||||
>
|
||||
{c.op === "add" ? "Add" : "Remove"}
|
||||
</Badge>
|
||||
<Anchor
|
||||
component="button"
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
view({
|
||||
name: c.fileName ?? humanize(c.code),
|
||||
url: fileViewUrl(c.fileId),
|
||||
})
|
||||
}
|
||||
style={{
|
||||
textDecoration:
|
||||
c.op === "remove" ? "line-through" : undefined,
|
||||
}}
|
||||
>
|
||||
{c.fileName ?? humanize(c.code)}
|
||||
</Anchor>
|
||||
<Text size="xs" c="dimmed">
|
||||
{humanize(c.code)}
|
||||
</Text>
|
||||
</Group>
|
||||
))}
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
{docCount > 0 && (
|
||||
<Text size="sm" c="dimmed">
|
||||
{docCount} document{docCount === 1 ? "" : "s"} uploaded with this
|
||||
request — review them in the Documents tab.
|
||||
</Text>
|
||||
<Stack gap={8}>
|
||||
<Text size="sm" fw={600} c="edr-text">
|
||||
Documents uploaded with this request
|
||||
</Text>
|
||||
{pending!.documentFileIds.map((fileId, i) => (
|
||||
<Group key={fileId} gap={8} wrap="nowrap">
|
||||
<FilePlus2 size={15} className="text-edr-muted" />
|
||||
<Anchor
|
||||
component="button"
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
view({
|
||||
name: `Document ${i + 1}`,
|
||||
url: fileViewUrl(fileId),
|
||||
})
|
||||
}
|
||||
>
|
||||
Document {i + 1}
|
||||
</Anchor>
|
||||
</Group>
|
||||
))}
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
{licenseChanges.length > 0 && (
|
||||
|
||||
@@ -93,6 +93,8 @@ function tableStatus(query: { isLoading: boolean; isError: boolean }) {
|
||||
|
||||
/** Matches the fileKey seeded in the API's file-upload-settings seeder. */
|
||||
const POA_DELEGATION_CODE = "poa_delegation_letter";
|
||||
/** A letter uploaded by an approved customer, awaiting this reviewer's approval. */
|
||||
const POA_DELEGATION_PENDING_CODE = "poa_delegation_letter_pending";
|
||||
|
||||
export default function CustomerDetailPage() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
@@ -536,9 +538,15 @@ export default function CustomerDetailPage() {
|
||||
);
|
||||
|
||||
const poaDocuments = useMemo(
|
||||
() => documents.filter((d) => d.code === POA_DELEGATION_CODE),
|
||||
() =>
|
||||
documents.filter(
|
||||
(d) =>
|
||||
d.code === POA_DELEGATION_CODE ||
|
||||
d.code === POA_DELEGATION_PENDING_CODE,
|
||||
),
|
||||
[documents],
|
||||
);
|
||||
const poaLive = poaDocuments.filter((d) => d.code === POA_DELEGATION_CODE);
|
||||
const poaFields = [
|
||||
{ label: "PoA name", value: company?.poaName },
|
||||
{ label: "PoA email", value: company?.poaEmail },
|
||||
@@ -553,7 +561,7 @@ export default function CustomerDetailPage() {
|
||||
(p) => p.type === "freight_forwarder",
|
||||
);
|
||||
const delegationMissing =
|
||||
(hasPoaDetails || poaMandatory) && poaDocuments.length === 0;
|
||||
(hasPoaDetails || poaMandatory) && poaLive.length === 0;
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
@@ -713,7 +721,7 @@ export default function CustomerDetailPage() {
|
||||
<Badge size="sm" color="red" variant="light">
|
||||
Delegation letter missing
|
||||
</Badge>
|
||||
) : poaDocuments.length > 0 ? (
|
||||
) : poaLive.length > 0 ? (
|
||||
<Badge size="sm" color="edr-green" variant="light">
|
||||
Delegation letter on file
|
||||
</Badge>
|
||||
@@ -806,6 +814,16 @@ export default function CustomerDetailPage() {
|
||||
{formatBytes(doc.size)} ·{" "}
|
||||
{formatDate(doc.uploadedAt)}
|
||||
</Text>
|
||||
{doc.code === POA_DELEGATION_PENDING_CODE && (
|
||||
<Badge
|
||||
size="xs"
|
||||
color="yellow"
|
||||
variant="light"
|
||||
className="shrink-0"
|
||||
>
|
||||
Pending approval
|
||||
</Badge>
|
||||
)}
|
||||
</Group>
|
||||
<Group gap={4} wrap="nowrap">
|
||||
<ActionIcon
|
||||
|
||||
@@ -79,6 +79,15 @@ export interface LicenseChangeIntent {
|
||||
fileName?: string;
|
||||
}
|
||||
|
||||
/** A staged company-level document add/remove (e.g. the PoA delegation letter). */
|
||||
export interface DocumentChangeIntent {
|
||||
op: "add" | "remove";
|
||||
fileId: string;
|
||||
/** The live FileRecord code this op targets (the upload setting's fileKey). */
|
||||
code: string;
|
||||
fileName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A staged profile-edit change request. The customer's settings edits land here
|
||||
* (pending) until a reviewer approves (applies them) or rejects (with a note).
|
||||
@@ -92,6 +101,8 @@ export interface CompanyChangeRequest {
|
||||
documentFileIds: string[];
|
||||
/** Staged business-license add/remove intents attached to this request. */
|
||||
licenseChanges: LicenseChangeIntent[];
|
||||
/** Staged company-document add/remove intents (e.g. the PoA letter). */
|
||||
documentChanges: DocumentChangeIntent[];
|
||||
note: string | null;
|
||||
submittedAt: string | null;
|
||||
reviewedAt: string | null;
|
||||
|
||||
Reference in New Issue
Block a user