diff --git a/src/lib/forms-shared.ts b/src/lib/forms-shared.ts index b3c2d44..79a51a5 100644 --- a/src/lib/forms-shared.ts +++ b/src/lib/forms-shared.ts @@ -78,9 +78,29 @@ export const SYSTEM_VARIABLES = [ { key: "{{firmName}}", description: "Your firm name" }, ] as const; +export interface CustomFieldVar { + key: string; + label: string; + description: string | null; +} + +export async function fetchCustomFieldDefs(): Promise { + const { data } = await supabase + .from("custom_case_fields") + .select("key,label,description") + .eq("active", true) + .order("sort_order"); + return (data ?? []) as CustomFieldVar[]; +} + export function applyVariables( body: string, - ctx: { client?: ClientLite | null; homeowner?: HomeownerLite | null; firmName?: string }, + ctx: { + client?: ClientLite | null; + homeowner?: HomeownerLite | null; + firmName?: string; + customValues?: Record; + }, ): string { const today = format(new Date(), "MMMM d, yyyy"); const replacements: Record = { @@ -97,6 +117,12 @@ export function applyVariables( for (const [k, v] of Object.entries(replacements)) { out = out.split(k).join(v); } + // Custom variables like {{custom.mortgage_holder}} + if (ctx.customValues) { + for (const [k, v] of Object.entries(ctx.customValues)) { + out = out.split(`{{custom.${k}}}`).join(v ?? ""); + } + } return out; } diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index f509e07..f44751d 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -34,6 +34,7 @@ import { Route as SettingsProfileRouteImport } from './routes/settings.profile' import { Route as SettingsImportRouteImport } from './routes/settings.import' import { Route as SettingsImapRouteImport } from './routes/settings.imap' import { Route as SettingsFeesRouteImport } from './routes/settings.fees' +import { Route as SettingsCustomFieldsRouteImport } from './routes/settings.custom-fields' import { Route as InvoicesInvoiceIdRouteImport } from './routes/invoices.$invoiceId' import { Route as HooksPollImapRouteImport } from './routes/hooks/poll-imap' import { Route as ContactsContactIdRouteImport } from './routes/contacts.$contactId' @@ -172,6 +173,11 @@ const SettingsFeesRoute = SettingsFeesRouteImport.update({ path: '/fees', getParentRoute: () => SettingsRoute, } as any) +const SettingsCustomFieldsRoute = SettingsCustomFieldsRouteImport.update({ + id: '/custom-fields', + path: '/custom-fields', + getParentRoute: () => SettingsRoute, +} as any) const InvoicesInvoiceIdRoute = InvoicesInvoiceIdRouteImport.update({ id: '/invoices/$invoiceId', path: '/invoices/$invoiceId', @@ -247,6 +253,7 @@ export interface FileRoutesByFullPath { '/contacts/$contactId': typeof ContactsContactIdRoute '/hooks/poll-imap': typeof HooksPollImapRoute '/invoices/$invoiceId': typeof InvoicesInvoiceIdRoute + '/settings/custom-fields': typeof SettingsCustomFieldsRoute '/settings/fees': typeof SettingsFeesRoute '/settings/imap': typeof SettingsImapRoute '/settings/import': typeof SettingsImportRoute @@ -285,6 +292,7 @@ export interface FileRoutesByTo { '/contacts/$contactId': typeof ContactsContactIdRoute '/hooks/poll-imap': typeof HooksPollImapRoute '/invoices/$invoiceId': typeof InvoicesInvoiceIdRoute + '/settings/custom-fields': typeof SettingsCustomFieldsRoute '/settings/fees': typeof SettingsFeesRoute '/settings/imap': typeof SettingsImapRoute '/settings/import': typeof SettingsImportRoute @@ -325,6 +333,7 @@ export interface FileRoutesById { '/contacts/$contactId': typeof ContactsContactIdRoute '/hooks/poll-imap': typeof HooksPollImapRoute '/invoices/$invoiceId': typeof InvoicesInvoiceIdRoute + '/settings/custom-fields': typeof SettingsCustomFieldsRoute '/settings/fees': typeof SettingsFeesRoute '/settings/imap': typeof SettingsImapRoute '/settings/import': typeof SettingsImportRoute @@ -366,6 +375,7 @@ export interface FileRouteTypes { | '/contacts/$contactId' | '/hooks/poll-imap' | '/invoices/$invoiceId' + | '/settings/custom-fields' | '/settings/fees' | '/settings/imap' | '/settings/import' @@ -404,6 +414,7 @@ export interface FileRouteTypes { | '/contacts/$contactId' | '/hooks/poll-imap' | '/invoices/$invoiceId' + | '/settings/custom-fields' | '/settings/fees' | '/settings/imap' | '/settings/import' @@ -443,6 +454,7 @@ export interface FileRouteTypes { | '/contacts/$contactId' | '/hooks/poll-imap' | '/invoices/$invoiceId' + | '/settings/custom-fields' | '/settings/fees' | '/settings/imap' | '/settings/import' @@ -679,6 +691,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof SettingsFeesRouteImport parentRoute: typeof SettingsRoute } + '/settings/custom-fields': { + id: '/settings/custom-fields' + path: '/custom-fields' + fullPath: '/settings/custom-fields' + preLoaderRoute: typeof SettingsCustomFieldsRouteImport + parentRoute: typeof SettingsRoute + } '/invoices/$invoiceId': { id: '/invoices/$invoiceId' path: '/invoices/$invoiceId' @@ -767,6 +786,7 @@ declare module '@tanstack/react-router' { } interface SettingsRouteChildren { + SettingsCustomFieldsRoute: typeof SettingsCustomFieldsRoute SettingsFeesRoute: typeof SettingsFeesRoute SettingsImapRoute: typeof SettingsImapRoute SettingsImportRoute: typeof SettingsImportRoute @@ -778,6 +798,7 @@ interface SettingsRouteChildren { } const SettingsRouteChildren: SettingsRouteChildren = { + SettingsCustomFieldsRoute: SettingsCustomFieldsRoute, SettingsFeesRoute: SettingsFeesRoute, SettingsImapRoute: SettingsImapRoute, SettingsImportRoute: SettingsImportRoute,