Rename invoice-settings to company-settings, add its own Live Preview, and refine invoice PDF layout

Company data now has its own Payload admin group and a live in-browser
PDF preview (react-pdf's PDFViewer) instead of just a plain settings
form. Invoice header is a brand-colored rule instead of a filled band,
and the footer is now pinned to the page bottom instead of following
content flow.
This commit is contained in:
Marco
2026-07-22 11:11:58 +00:00
parent f144ad25f2
commit e50d43ea44
8 changed files with 261 additions and 75 deletions
@@ -0,0 +1,37 @@
"use client";
import dynamic from "next/dynamic";
import { useLivePreview } from "@payloadcms/live-preview-react";
import { InvoiceDocument, SAMPLE_INVOICE_ORDER } from "../../lib/invoicePdf";
import type { CompanySettings } from "../../lib/payload";
const PAYLOAD_URL = process.env.NEXT_PUBLIC_PAYLOAD_URL || "https://payload.mk360.de";
// @react-pdf/renderer's PDFViewer renders into an <iframe> via direct DOM
// access — it has to be excluded from the server render pass entirely
// (ssr: false), unlike the HTML-string email previews elsewhere in this
// app, which can render server-side fine since they're just
// dangerouslySetInnerHTML.
const PDFViewer = dynamic(() => import("@react-pdf/renderer").then((mod) => mod.PDFViewer), { ssr: false });
// Same useLivePreview() mechanism as LiveEmailPreviewClient.tsx — connects
// to the Payload admin's iframe via postMessage and updates `data` as the
// admin edits company-settings fields, no save required. Renders through
// the exact same InvoiceDocument component the real invoice PDF uses
// (app/lib/invoicePdf.tsx), against a fixed sample order
// (SAMPLE_INVOICE_ORDER) — there's no "current" real order to preview
// against generically, same reasoning as the email-templates preview's
// own SAMPLE_ORDER.
export function LiveCompanySettingsPreviewClient({ initialSettings }: { initialSettings: CompanySettings }) {
const { data } = useLivePreview<CompanySettings>({
initialData: initialSettings,
serverURL: PAYLOAD_URL,
depth: 0,
});
return (
<PDFViewer style={{ width: "100%", height: "100vh", border: "none" }}>
<InvoiceDocument order={SAMPLE_INVOICE_ORDER} seller={data} />
</PDFViewer>
);
}