Files
online-energieausweis/src/lib/pdf/plugins/variables/index.ts
2024-03-20 12:12:35 +07:00

281 lines
6.9 KiB
TypeScript

import {
Plugin,
PropPanel,
DEFAULT_FONT_NAME,
getFallbackFontName,
PropPanelSchema,
PropPanelWidgetProps,
} from "@pdfme/common";
import { text } from "@pdfme/schemas";
import type { TextSchema } from "@pdfme/schemas/dist/types/src/text/types";
import {
DEFAULT_FONT_SIZE,
DEFAULT_ALIGNMENT,
DEFAULT_VERTICAL_ALIGNMENT,
DEFAULT_CHARACTER_SPACING,
DEFAULT_LINE_HEIGHT,
VERTICAL_ALIGN_TOP,
VERTICAL_ALIGN_MIDDLE,
VERTICAL_ALIGN_BOTTOM,
DEFAULT_FONT_COLOR,
DYNAMIC_FIT_VERTICAL,
DYNAMIC_FIT_HORIZONTAL,
DEFAULT_DYNAMIC_FIT,
DEFAULT_DYNAMIC_MIN_FONT_SIZE,
DEFAULT_DYNAMIC_MAX_FONT_SIZE,
ALIGN_RIGHT,
ALIGN_CENTER,
DEFAULT_OPACITY,
HEX_COLOR_PATTERN,
} from "./constants";
import {
GebaeudeStammdaten,
Rechnungen,
} from "@ibcornelsen/database/client";
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
import { zodGetKeys } from "#lib/helpers/zod";
import { verbrauchsausweisWohnenPDFValidator } from "#lib/validators/verbrauchsausweis-wohnen-pdf-validator";
const UseDynamicFontSize = (props: PropPanelWidgetProps) => {
const { rootElement, changeSchemas, activeSchema, i18n } = props;
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = Boolean((activeSchema as any)?.dynamicFontSize);
checkbox.onchange = (e: any) => {
const val = e.target.checked
? {
min: DEFAULT_DYNAMIC_MIN_FONT_SIZE,
max: DEFAULT_DYNAMIC_MAX_FONT_SIZE,
fit: DEFAULT_DYNAMIC_FIT,
}
: undefined;
changeSchemas([
{ key: "dynamicFontSize", value: val, schemaId: activeSchema.id },
]);
};
const label = document.createElement("label");
label.innerText = i18n("schemas.text.dynamicFontSize") || "";
label.style.cssText = "display: flex; width: 100%;";
label.appendChild(checkbox);
rootElement.appendChild(label);
};
type AusweisIndex = keyof Omit<Omit<VerbrauchsausweisWohnenClient, "gebaeude_aufnahme_allgemein">, "rechnungen">
| `gebaeude_aufnahme_allgemein.${keyof VerbrauchsausweisWohnenClient["gebaeude_aufnahme_allgemein"]}`
| `gebaeude_aufnahme_allgemein.gebaeude_stammdaten.${keyof VerbrauchsausweisWohnenClient["gebaeude_aufnahme_allgemein"]["gebaeude_stammdaten"]}`
| `rechnungen.${keyof Rechnungen}`;
const ausweisKeys = zodGetKeys(verbrauchsausweisWohnenPDFValidator);
const variableOptions: {
label: string;
value: AusweisIndex;
}[] = ausweisKeys.map((key: AusweisIndex) => ({ label: key as string, value: key }));
interface VariableSchema extends TextSchema {
variable: AusweisIndex | undefined
}
const propPanel: PropPanel<VariableSchema> = {
schema: ({ options, activeSchema, i18n }) => {
const font = options.font || {
[DEFAULT_FONT_NAME]: { data: "", fallback: true },
};
const fontNames = Object.keys(font);
const fallbackFontName = getFallbackFontName(font);
const enableDynamicFont = Boolean(
(activeSchema as any)?.dynamicFontSize
);
const textSchema: Record<string, PropPanelSchema> = {
variable: {
title: "Variable",
type: "string",
widget: "select",
props: { options: variableOptions },
span: 24,
},
fontName: {
title: i18n("schemas.text.fontName"),
type: "string",
widget: "select",
default: fallbackFontName,
props: {
options: fontNames.map((name) => ({
label: name,
value: name,
})),
},
span: 12,
},
fontSize: {
title: i18n("schemas.text.size"),
type: "number",
widget: "inputNumber",
span: 6,
disabled: enableDynamicFont,
},
characterSpacing: {
title: i18n("schemas.text.spacing"),
type: "number",
widget: "inputNumber",
span: 6,
},
alignment: {
title: i18n("schemas.text.textAlign"),
type: "string",
widget: "select",
props: {
options: [
{
label: i18n("schemas.left"),
value: DEFAULT_ALIGNMENT,
},
{ label: i18n("schemas.center"), value: ALIGN_CENTER },
{ label: i18n("schemas.right"), value: ALIGN_RIGHT },
],
},
span: 8,
},
verticalAlignment: {
title: i18n("schemas.text.verticalAlign"),
type: "string",
widget: "select",
props: {
options: [
{
label: i18n("schemas.top"),
value: VERTICAL_ALIGN_TOP,
},
{
label: i18n("schemas.middle"),
value: VERTICAL_ALIGN_MIDDLE,
},
{
label: i18n("schemas.bottom"),
value: VERTICAL_ALIGN_BOTTOM,
},
],
},
span: 8,
},
lineHeight: {
title: i18n("schemas.text.lineHeight"),
type: "number",
widget: "inputNumber",
props: {
step: 0.1,
},
span: 8,
},
useDynamicFontSize: {
type: "boolean",
widget: "UseDynamicFontSize",
bind: false,
span: 16,
},
dynamicFontSize: {
type: "object",
widget: "card",
column: 3,
properties: {
min: {
title: i18n("schemas.text.min"),
type: "number",
widget: "inputNumber",
hidden: !enableDynamicFont,
},
max: {
title: i18n("schemas.text.max"),
type: "number",
widget: "inputNumber",
hidden: !enableDynamicFont,
},
fit: {
title: i18n("schemas.text.fit"),
type: "string",
widget: "select",
hidden: !enableDynamicFont,
props: {
options: [
{
label: i18n("schemas.horizontal"),
value: DYNAMIC_FIT_HORIZONTAL,
},
{
label: i18n("schemas.vertical"),
value: DYNAMIC_FIT_VERTICAL,
},
],
},
},
},
},
fontColor: {
title: i18n("schemas.textColor"),
type: "string",
widget: "color",
rules: [
{
pattern: HEX_COLOR_PATTERN,
message: i18n("hexColorPrompt"),
},
],
},
backgroundColor: {
title: i18n("schemas.bgColor"),
type: "string",
widget: "color",
rules: [
{
pattern: HEX_COLOR_PATTERN,
message: i18n("hexColorPrompt"),
},
],
},
};
return textSchema;
},
widgets: { UseDynamicFontSize },
defaultValue: "Type Something...",
defaultSchema: {
type: "variable",
position: { x: 0, y: 0 },
width: 45,
height: 10,
rotate: 0,
alignment: DEFAULT_ALIGNMENT,
verticalAlignment: DEFAULT_VERTICAL_ALIGNMENT,
fontSize: DEFAULT_FONT_SIZE,
lineHeight: DEFAULT_LINE_HEIGHT,
characterSpacing: DEFAULT_CHARACTER_SPACING,
dynamicFontSize: undefined,
fontColor: DEFAULT_FONT_COLOR,
fontName: undefined,
backgroundColor: "",
opacity: DEFAULT_OPACITY,
variable: undefined
}
};
export const variable: Plugin<VariableSchema> = {
ui: function(props) {
// Wir binden die inputs auf dieses Element, damit wir die Werte später auslesen können.
if (props.schema.variable && this) {
props.value = (this as unknown as Record<string, string>)[props.schema.variable] as string;
}
return text.ui(props);
},
pdf: (props) => {
if (props.schema.variable && this) {
props.value = (this as unknown as Record<string, string>)[props.schema.variable] as string;
}
text.pdf(props);
},
propPanel,
};