Files
edr-platform/apps/edr-freight-web/backoffice/src/components/customers/PersonCard.tsx
2026-08-12 09:33:21 +00:00

113 lines
2.8 KiB
TypeScript

import { Badge, Card, Divider, Group, Stack, Text } from "@mantine/core";
import type { ReactNode } from "react";
export interface PersonField {
label: string;
value?: string | null;
}
export interface PersonCardProps {
/** OWNER / POA / CONTACT PERSON — the person's role, not their name. */
title: string;
icon?: ReactNode;
/**
* Identity state. `undefined` = this person has no identity check at all
* (contact person), so no badge is rendered rather than a misleading "not
* verified" one.
*/
verified?: boolean;
/** Extra pills after the verification badge (e.g. "Verifies for this company"). */
badges?: ReactNode;
/** Rendered between the header and the fields — alerts, match warnings. */
notice?: ReactNode;
fields: PersonField[];
/** Shown when the API returned nothing for every field. */
emptyMessage: string;
/** Attachments or anything else that belongs to this person. */
children?: ReactNode;
}
/**
* One person in the customer's people column: owner, power of attorney, contact
* person. Empty fields are dropped rather than rendered as "—", so a field the
* API stops sending simply disappears instead of leaving a dead row behind.
*/
export function PersonCard({
title,
icon,
verified,
badges,
notice,
fields,
emptyMessage,
children,
}: PersonCardProps) {
const filled = fields.filter(
(f) => f.value != null && String(f.value).trim(),
);
return (
<Card>
<Stack gap="sm">
<Group gap={8} wrap="wrap">
{icon}
<Text
size="xs"
fw={700}
c="edr-muted"
tt="uppercase"
style={{ letterSpacing: "0.06em" }}
>
{title}
</Text>
{verified !== undefined &&
(verified ? (
<Badge size="xs" color="edr-green" variant="light">
Fayda verified
</Badge>
) : (
<Badge size="xs" color="gray" variant="light">
Not verified
</Badge>
))}
{badges}
</Group>
{notice}
{filled.length > 0 ? (
<Stack gap="xs">
{filled.map((f) => (
<Stack key={f.label} gap={0}>
<Text size="xs" c="edr-muted">
{f.label}
</Text>
<Text
size="sm"
c="edr-text"
style={{ wordBreak: "break-word" }}
>
{f.value}
</Text>
</Stack>
))}
</Stack>
) : (
<Text size="sm" c="dimmed">
{emptyMessage}
</Text>
)}
{children && (
<>
<Divider />
{children}
</>
)}
</Stack>
</Card>
);
}
export default PersonCard;