Changes
Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
co-authored by
renee-png
parent
3456ba6ad1
commit
a692b9ec7d
+73
-24
@@ -134,6 +134,47 @@ export async function fetchCustomFieldDefs(): Promise<CustomFieldVar[]> {
|
||||
return (data ?? []) as CustomFieldVar[];
|
||||
}
|
||||
|
||||
// Case modifiers usable in templates as {{var|modifier}}.
|
||||
// Supported: upper, lower, title, sentence, capitalize (alias for sentence).
|
||||
export type CaseModifier = "upper" | "lower" | "title" | "sentence" | "capitalize";
|
||||
|
||||
export function applyCase(value: string, modifier?: string | null): string {
|
||||
if (!value || !modifier) return value ?? "";
|
||||
const m = modifier.toLowerCase().trim();
|
||||
switch (m) {
|
||||
case "upper":
|
||||
return value.toUpperCase();
|
||||
case "lower":
|
||||
return value.toLowerCase();
|
||||
case "title":
|
||||
// Capitalize each word; preserve internal punctuation/whitespace.
|
||||
return value.toLowerCase().replace(/\b([a-z\u00C0-\u024F])/g, (c) => c.toUpperCase());
|
||||
case "sentence":
|
||||
case "capitalize": {
|
||||
// Lowercase the whole string, then capitalize the first letter of each sentence.
|
||||
const lower = value.toLowerCase();
|
||||
return lower.replace(/(^\s*[a-z\u00C0-\u024F])|([.!?]\s+[a-z\u00C0-\u024F])/g, (s) =>
|
||||
s.toUpperCase(),
|
||||
);
|
||||
}
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace any occurrence of {{name}} or {{name|modifier}} using the provided lookup.
|
||||
function replaceWithModifier(
|
||||
body: string,
|
||||
pattern: RegExp,
|
||||
resolver: (name: string) => string | undefined,
|
||||
): string {
|
||||
return body.replace(pattern, (_match, rawName: string, _pipe: string | undefined, mod: string | undefined) => {
|
||||
const value = resolver(rawName.trim());
|
||||
if (value == null) return "";
|
||||
return applyCase(value, mod);
|
||||
});
|
||||
}
|
||||
|
||||
export function applyVariables(
|
||||
body: string,
|
||||
ctx: {
|
||||
@@ -145,32 +186,40 @@ export function applyVariables(
|
||||
},
|
||||
): string {
|
||||
const today = format(new Date(), "MMMM d, yyyy");
|
||||
const replacements: Record<string, string> = {
|
||||
"{{clientName}}": ctx.client?.name ?? "",
|
||||
"{{ownerName}}": ownerFullName(ctx.homeowner),
|
||||
"{{propertyAddress}}": ctx.homeowner?.address ?? "",
|
||||
"{{unitNumber}}": ctx.homeowner?.unit_number ?? "",
|
||||
"{{accountNumber}}": ctx.homeowner?.unit_number ?? "",
|
||||
"{{balance}}": (ctx.homeowner?.opening_balance ?? 0).toFixed(2),
|
||||
"{{currentDate}}": today,
|
||||
"{{firmName}}": ctx.firmName ?? "",
|
||||
const systemValues: Record<string, string> = {
|
||||
clientName: ctx.client?.name ?? "",
|
||||
ownerName: ownerFullName(ctx.homeowner),
|
||||
propertyAddress: ctx.homeowner?.address ?? "",
|
||||
unitNumber: ctx.homeowner?.unit_number ?? "",
|
||||
accountNumber: ctx.homeowner?.unit_number ?? "",
|
||||
balance: (ctx.homeowner?.opening_balance ?? 0).toFixed(2),
|
||||
currentDate: today,
|
||||
firmName: ctx.firmName ?? "",
|
||||
};
|
||||
|
||||
let out = body;
|
||||
for (const [k, v] of Object.entries(replacements)) {
|
||||
out = out.split(k).join(v);
|
||||
}
|
||||
// Custom case-field variables like {{custom.mortgage_holder}}
|
||||
if (ctx.customValues) {
|
||||
for (const [k, v] of Object.entries(ctx.customValues)) {
|
||||
out = out.split(`{{custom.${k}}}`).join(v ?? "");
|
||||
}
|
||||
}
|
||||
// Per-form fillable fields like {{field.tenant_name}}
|
||||
if (ctx.fieldValues) {
|
||||
for (const [k, v] of Object.entries(ctx.fieldValues)) {
|
||||
out = out.split(`{{field.${k}}}`).join(v ?? "");
|
||||
}
|
||||
}
|
||||
|
||||
// System variables: {{name}} or {{name|modifier}}
|
||||
out = replaceWithModifier(
|
||||
out,
|
||||
/\{\{\s*([a-zA-Z][a-zA-Z0-9_]*)\s*(\|\s*([a-zA-Z]+)\s*)?\}\}/g,
|
||||
(name) => systemValues[name],
|
||||
);
|
||||
|
||||
// Custom case-field variables: {{custom.key}} or {{custom.key|modifier}}
|
||||
out = replaceWithModifier(
|
||||
out,
|
||||
/\{\{\s*custom\.([a-zA-Z0-9_]+)\s*(\|\s*([a-zA-Z]+)\s*)?\}\}/g,
|
||||
(name) => ctx.customValues?.[name],
|
||||
);
|
||||
|
||||
// Per-form fillable fields: {{field.key}} or {{field.key|modifier}}
|
||||
out = replaceWithModifier(
|
||||
out,
|
||||
/\{\{\s*field\.([a-zA-Z0-9_]+)\s*(\|\s*([a-zA-Z]+)\s*)?\}\}/g,
|
||||
(name) => ctx.fieldValues?.[name],
|
||||
);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user