Prosento_RepEx / frontend /src /lib /pageTemplates.ts
ChristopherJKoen's picture
Add page template system and UI
25058c7
import type { Page, PageTemplateDefinition } from "../types/session";
export const BUILTIN_PAGE_TEMPLATES: PageTemplateDefinition[] = [
{
id: "repex:standard",
name: "Standard Job Sheet",
description: "Observations + up to two photos.",
blank: false,
variant: "full",
source: "builtin",
},
{
id: "repex:photos",
name: "Photo Continuation",
description: "Photo-only continuation page.",
blank: false,
variant: "photos",
source: "builtin",
},
{
id: "repex:blank",
name: "Blank Canvas",
description: "Blank white page.",
blank: true,
variant: "full",
source: "builtin",
},
];
export function mergePageTemplates(
customTemplates?: PageTemplateDefinition[],
): PageTemplateDefinition[] {
const byId = new Map<string, PageTemplateDefinition>();
BUILTIN_PAGE_TEMPLATES.forEach((template) => {
byId.set(template.id, template);
});
(customTemplates ?? []).forEach((template) => {
if (!template?.id) return;
byId.set(template.id, { ...template, source: "custom" });
});
return Array.from(byId.values());
}
export function inferPageTemplateId(page?: Page | null): string {
if (page?.page_template) return page.page_template;
if (page?.blank) return "repex:blank";
if (page?.variant === "photos") return "repex:photos";
return "repex:standard";
}
export function resolvePageTemplate(
page: Page | null | undefined,
templates: PageTemplateDefinition[],
): PageTemplateDefinition {
const id = inferPageTemplateId(page);
return (
templates.find((template) => template.id === id) ??
BUILTIN_PAGE_TEMPLATES[0]
);
}
export function applyPageTemplateToPage(
page: Page,
template: PageTemplateDefinition,
): Page {
const next: Page = {
...page,
page_template: template.id,
blank: Boolean(template.blank),
variant: template.variant ?? "full",
};
if (template.photo_layout) {
next.photo_layout = template.photo_layout;
}
return next;
}
export function createCustomTemplateId() {
return `tpl_${crypto.randomUUID().replace(/-/g, "")}`;
}