143 lines
5.8 KiB
TypeScript
143 lines
5.8 KiB
TypeScript
/**
|
|
* Map a saved BadgeBatch (config) into CreateBadgePanel form state.
|
|
*/
|
|
import type { BadgeBatchRecord, BadgeLayoutElementPayload } from "../../../services/api/badgeBatches";
|
|
import type { BadgeBackgroundImageLayout, BadgeLayoutElement } from "./badgeLayout";
|
|
import { defaultBackgroundImageLayout, defaultLayoutForFields, parseBackgroundImageLayout } from "./badgeLayout";
|
|
|
|
export type BadgeFormState = {
|
|
formName: string;
|
|
formEventId: string;
|
|
sizePreset: "a6" | "a7" | "4x3in" | "4x6in" | "custom";
|
|
customW: string;
|
|
customH: string;
|
|
orientation: "portrait" | "landscape";
|
|
includeFaculty: boolean;
|
|
includeParticipants: boolean;
|
|
participantScope: "all" | "participant_list";
|
|
participantListId: string;
|
|
backgroundMode: "image" | "color";
|
|
backgroundColor: string;
|
|
backgroundImageUrl: string;
|
|
backgroundImageLayout: BadgeBackgroundImageLayout;
|
|
enabledFields: string[];
|
|
layoutElements: BadgeLayoutElement[];
|
|
customTexts: { id: string; text: string }[];
|
|
customImages: { id: string; imageUrl: string }[];
|
|
outputFormat: "pdf" | "png" | "jpeg";
|
|
badgeTypeLabel: string;
|
|
};
|
|
|
|
function eventIdFromBatch(batch: BadgeBatchRecord): string {
|
|
const ev = batch.event;
|
|
if (typeof ev === "string") return ev;
|
|
if (ev && typeof ev === "object" && "_id" in ev) return String(ev._id);
|
|
return "";
|
|
}
|
|
|
|
function duplicateExportName(name: string): string {
|
|
const base = (name || "Badge export").trim();
|
|
const copy = `Copy of ${base}`;
|
|
return copy.length > 120 ? `${copy.slice(0, 117)}…` : copy;
|
|
}
|
|
|
|
function asConfig(batch: BadgeBatchRecord): Record<string, unknown> {
|
|
return (batch.config && typeof batch.config === "object" ? batch.config : {}) as Record<string, unknown>;
|
|
}
|
|
|
|
function str(v: unknown, fallback = ""): string {
|
|
return typeof v === "string" ? v : fallback;
|
|
}
|
|
|
|
function bool(v: unknown, fallback: boolean): boolean {
|
|
return typeof v === "boolean" ? v : fallback;
|
|
}
|
|
|
|
function numStr(v: unknown, fallback: string): string {
|
|
if (typeof v === "number" && Number.isFinite(v)) return String(v);
|
|
return fallback;
|
|
}
|
|
|
|
function sizePresetFromConfig(c: Record<string, unknown>): BadgeFormState["sizePreset"] {
|
|
const p = str(c.sizePreset, "a6");
|
|
if (p === "a7" || p === "4x3in" || p === "4x6in" || p === "custom") return p;
|
|
return "a6";
|
|
}
|
|
|
|
function layoutFromConfig(c: Record<string, unknown>): BadgeLayoutElement[] {
|
|
const raw = c.layout;
|
|
if (!Array.isArray(raw) || raw.length === 0) return [];
|
|
return raw
|
|
.filter((el): el is BadgeLayoutElementPayload => el != null && typeof el === "object" && typeof (el as BadgeLayoutElementPayload).id === "string")
|
|
.map((el) => ({ ...el })) as BadgeLayoutElement[];
|
|
}
|
|
|
|
function customTextsFromConfig(c: Record<string, unknown>, layout: BadgeLayoutElement[]): { id: string; text: string }[] {
|
|
const fromConfig = Array.isArray(c.customTexts)
|
|
? c.customTexts
|
|
.filter((x): x is { id: string; text: string } => x != null && typeof x === "object" && typeof (x as { id: string }).id === "string")
|
|
.map((x) => ({ id: String(x.id), text: String((x as { text?: string }).text ?? "") }))
|
|
: [];
|
|
if (fromConfig.length) return fromConfig;
|
|
return layout
|
|
.filter((el) => el.kind === "custom_text")
|
|
.map((el) => ({ id: el.id, text: str(el.text, "Your text") }));
|
|
}
|
|
|
|
function customImagesFromConfig(c: Record<string, unknown>, layout: BadgeLayoutElement[]): { id: string; imageUrl: string }[] {
|
|
const fromConfig = Array.isArray(c.customImages)
|
|
? c.customImages
|
|
.filter((x): x is { id: string; imageUrl: string } => x != null && typeof x === "object" && typeof (x as { id: string }).id === "string")
|
|
.map((x) => ({ id: String(x.id), imageUrl: String((x as { imageUrl?: string }).imageUrl ?? "") }))
|
|
: [];
|
|
if (fromConfig.length) return fromConfig;
|
|
return layout
|
|
.filter((el) => el.kind === "custom_image")
|
|
.map((el) => ({ id: el.id, imageUrl: str(el.imageUrl, "") }))
|
|
.filter((x) => x.imageUrl);
|
|
}
|
|
|
|
export function formStateFromBadgeBatch(batch: BadgeBatchRecord): BadgeFormState {
|
|
const c = asConfig(batch);
|
|
const bgColor = str(c.backgroundColor, "#0B4DD1");
|
|
const bgImageUrl = str(c.backgroundImageUrl, "");
|
|
const bgMode = bgImageUrl.trim() ? "image" : str(c.backgroundMode, "color") === "image" ? "image" : "color";
|
|
const backgroundImageLayout =
|
|
parseBackgroundImageLayout(c.backgroundImageLayout) ??
|
|
(bgImageUrl.trim() ? defaultBackgroundImageLayout() : defaultBackgroundImageLayout());
|
|
const fields = Array.isArray(c.fields) ? c.fields.map((f) => String(f)) : ["name", "title", "org", "qr"];
|
|
let layoutElements = layoutFromConfig(c);
|
|
if (!layoutElements.length && fields.length) {
|
|
layoutElements = defaultLayoutForFields(fields, bgColor, bgMode);
|
|
}
|
|
const customTexts = customTextsFromConfig(c, layoutElements);
|
|
const customImages = customImagesFromConfig(c, layoutElements);
|
|
const scope = str(c.participantScope, "all") === "participant_list" ? "participant_list" : "all";
|
|
const out = str(c.outputFormat, "pdf");
|
|
const outputFormat: BadgeFormState["outputFormat"] =
|
|
out === "png" || out === "jpeg" ? out : "pdf";
|
|
|
|
return {
|
|
formName: duplicateExportName(batch.name),
|
|
formEventId: eventIdFromBatch(batch),
|
|
sizePreset: sizePresetFromConfig(c),
|
|
customW: numStr(c.widthMm, "105"),
|
|
customH: numStr(c.heightMm, "148"),
|
|
orientation: str(c.orientation, "portrait") === "landscape" ? "landscape" : "portrait",
|
|
includeFaculty: bool(c.includeFaculty, true),
|
|
includeParticipants: bool(c.includeParticipants, true),
|
|
participantScope: scope,
|
|
participantListId: c.participantListId != null ? String(c.participantListId) : "",
|
|
backgroundMode: bgMode,
|
|
backgroundColor: bgColor,
|
|
backgroundImageUrl: bgImageUrl,
|
|
backgroundImageLayout,
|
|
enabledFields: fields,
|
|
layoutElements,
|
|
customTexts,
|
|
customImages,
|
|
outputFormat,
|
|
badgeTypeLabel: str(c.badgeTypeLabel, "Attendee"),
|
|
};
|
|
}
|