Files
edr-platform/apps/edr-freight-web/backoffice/src/pages/contract_templates/ContractTemplatesPage.tsx
2026-07-09 21:13:07 +00:00

153 lines
5.0 KiB
TypeScript

import { useState } from "react";
import { useNavigate } from "react-router-dom";
import {
Badge,
Button,
Card,
Center,
Group,
Loader,
SimpleGrid,
Stack,
Text,
ThemeIcon,
} from "@mantine/core";
import { Boxes, Container, Eye, FileSignature, Pencil } from "lucide-react";
import { PageContainer, PageHeader } from "@/components/page";
import { useContractTemplates } from "@/hooks/contract-templates/useContractTemplates";
import type { ContractTemplate } from "@/services/contract-templates.service";
import TemplatePreviewModal from "./TemplatePreviewModal";
const DIRECTION_LABEL: Record<string, string> = {
IMPORT: "Import",
EXPORT: "Export",
INTERCITY: "Intercity",
};
const DIRECTION_COLOR: Record<string, string> = {
IMPORT: "edr-green",
EXPORT: "teal",
INTERCITY: "lime",
};
function templateDirection(code: ContractTemplate["code"]): string {
return code.split("_")[0];
}
function isBulk(code: ContractTemplate["code"]): boolean {
return code.endsWith("_BULK");
}
export default function ContractTemplatesPage() {
const navigate = useNavigate();
const { data: templates, isLoading } = useContractTemplates();
const [previewCode, setPreviewCode] = useState<string | null>(null);
const previewTemplate = templates?.find((t) => t.code === previewCode);
return (
<PageContainer>
<PageHeader
title="Contract templates"
subtitle="The six contract documents generated when a contract is approved — one per trade direction and freight type. Articles are fully editable."
/>
{isLoading ? (
<Center h={320}>
<Loader color="edr-green" />
</Center>
) : (
<SimpleGrid cols={{ base: 1, md: 2, xl: 3 }} spacing="lg">
{(templates ?? []).map((template) => {
const direction = templateDirection(template.code);
return (
<Card key={template.code} withBorder radius="xl" padding="lg">
<Stack gap="sm" h="100%">
<Group justify="space-between" align="flex-start">
<ThemeIcon
size={44}
radius="md"
variant="light"
color="edr-green"
>
{isBulk(template.code) ? (
<Boxes size={24} />
) : (
<Container size={24} />
)}
</ThemeIcon>
<Group gap={6}>
<Badge
variant="light"
color={DIRECTION_COLOR[direction] ?? "edr-green"}
>
{DIRECTION_LABEL[direction] ?? direction}
</Badge>
<Badge variant="outline" color="gray">
{isBulk(template.code) ? "Bulk" : "Container"}
</Badge>
{!template.isActive && (
<Badge variant="light" color="red">
Inactive
</Badge>
)}
</Group>
</Group>
<div>
<Text fw={700} size="lg">
{template.name}
</Text>
<Text size="sm" c="dimmed" lineClamp={3}>
{template.description || template.documentTitle}
</Text>
</div>
<Group gap="xs" mt="auto">
<FileSignature size={14} className="text-edr-primary" />
<Text size="xs" c="dimmed">
{template.articles.length} articles · updated{" "}
{new Date(template.updatedAt).toLocaleDateString("en-GB", {
day: "numeric",
month: "short",
year: "numeric",
})}
</Text>
</Group>
<Group grow>
<Button
variant="light"
color="edr-green"
leftSection={<Eye size={16} />}
onClick={() => setPreviewCode(template.code)}
>
Preview
</Button>
<Button
color="edr-green"
leftSection={<Pencil size={16} />}
onClick={() =>
navigate(`/dashboard/contract-templates/${template.code}`)
}
>
Edit articles
</Button>
</Group>
</Stack>
</Card>
);
})}
</SimpleGrid>
)}
<TemplatePreviewModal
code={previewCode}
title={previewTemplate ? `${previewTemplate.name} — preview` : undefined}
onClose={() => setPreviewCode(null)}
/>
</PageContainer>
);
}