Files
edr-platform/apps/edr-freight-web/backoffice/src/pages/settings/LogoSettingsPage.tsx
Hagernesh c4bf3c9479 feat(freight): add company logo setting applied to every generated document
New logo-settings module (mirrors stamp-settings): single uploaded logo,
stored via FilesService/MinIO, injected as a data URL into invoice/receipt,
contract, warehouse, train-scheduling, and payment-receipt PDFs. Adds a
matching backoffice settings page and settings:logo:view/manage permissions.

>
2026-08-13 10:54:23 +00:00

89 lines
2.7 KiB
TypeScript

import { useEffect, useState } from "react";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/shared/common/ui/card";
import { Button } from "@/shared/common/ui/button";
import { Save, Trash2 } from "lucide-react";
import { LogoUpload } from "@/components/contracts/LogoUpload";
import {
useClearLogo,
useSetLogo,
useLogoSettingsQuery,
} from "@/hooks/useLogoSettings";
/**
* The ONE company logo, read by every document path server-side via
* LogoSettingsService: invoices and receipts, contract cover pages, warehouse
* GRN/release/handover papers, train-scheduling manifests, and the payment
* receipt. Single global image — no per-document choice.
*/
export default function LogoSettingsPage() {
const { data, isLoading } = useLogoSettingsQuery();
const setLogo = useSetLogo();
const clearLogo = useClearLogo();
const [draft, setDraft] = useState<string | null>(null);
useEffect(() => {
setDraft(null);
}, [data?.logoImageUrl]);
const value = draft !== null ? draft : (data?.logoImageUrl ?? null);
const dirty = draft !== null && draft !== data?.logoImageUrl;
const handleSave = async () => {
if (!draft) return;
await setLogo.mutateAsync(draft);
};
const handleClear = async () => {
if (!data?.logoImageUrl) return;
await clearLogo.mutateAsync();
};
return (
<div className="p-4 w-full max-w-screen-sm mx-auto">
<Card className="shadow-lg border-gray-200 dark:border-gray-700">
<CardHeader>
<CardTitle>Company logo</CardTitle>
<CardDescription>
The single EDR logo, applied to every generated document
invoices and receipts, contracts, warehouse papers, train-scheduling
manifests, and payment receipts. Replacing it here changes it
everywhere at once.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<LogoUpload
value={isLoading ? null : value}
onChange={setDraft}
label="Company logo"
description="Shown in the header of every generated document."
/>
<div className="flex items-center gap-2">
<Button onClick={handleSave} disabled={!dirty || setLogo.isPending}>
<Save className="mr-2 h-4 w-4" />
Save
</Button>
{data?.logoImageUrl && !dirty && (
<Button
variant="outline"
onClick={handleClear}
disabled={clearLogo.isPending}
>
<Trash2 className="mr-2 h-4 w-4" />
Remove
</Button>
)}
</div>
</CardContent>
</Card>
</div>
);
}