feat(registratura): auto-detect {proiect} placeholder in subject and switch to template mode
Typing {proiect}, {nr}, {an}, {detalii} or {text} in the subject field
now auto-transforms to template mode with the appropriate input widgets
(project dropdown, number fields, etc.).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -589,6 +589,73 @@ export function filterTemplates(
|
||||
);
|
||||
}
|
||||
|
||||
/** Recognized field placeholder names that can be used in dynamic templates */
|
||||
const DYNAMIC_FIELD_NAMES = new Set(["nr", "an", "detalii", "proiect", "text"]);
|
||||
|
||||
/** Regex to detect at least one valid {fieldName} placeholder */
|
||||
const HAS_PLACEHOLDER_RE = /\{(nr|an|detalii|proiect|text)\}/;
|
||||
|
||||
/**
|
||||
* Create a dynamic SubjectTemplate from free text containing `{fieldName}`
|
||||
* placeholders. Recognised names: nr, an, detalii, proiect, text.
|
||||
*
|
||||
* Returns `null` when the text contains no valid placeholder.
|
||||
*
|
||||
* Example:
|
||||
* createDynamicTemplate("Cerere CU — {proiect}")
|
||||
* → SubjectTemplate with static "Cerere CU — " + field(proiect)
|
||||
*/
|
||||
export function createDynamicTemplate(
|
||||
pattern: string,
|
||||
): SubjectTemplate | null {
|
||||
if (!HAS_PLACEHOLDER_RE.test(pattern)) return null;
|
||||
|
||||
const tokens: TemplateToken[] = [];
|
||||
const fields: TemplateField[] = [];
|
||||
let fIdx = 0;
|
||||
|
||||
// Split by {fieldName} placeholders (keeping the delimiters)
|
||||
const parts = pattern.split(/(\{[^}]+\})/);
|
||||
for (const part of parts) {
|
||||
if (!part) continue;
|
||||
const fieldMatch = part.match(/^\{(\w+)\}$/);
|
||||
if (fieldMatch) {
|
||||
const name = fieldMatch[1]!;
|
||||
if (!DYNAMIC_FIELD_NAMES.has(name)) {
|
||||
// Unknown placeholder — treat as static text
|
||||
tokens.push({ type: "static", value: part });
|
||||
continue;
|
||||
}
|
||||
const ft = resolveFieldType(name);
|
||||
const field: TemplateField = {
|
||||
id: `f${fIdx}`,
|
||||
name,
|
||||
placeholder: fieldPlaceholder(ft),
|
||||
width: fieldWidth(ft),
|
||||
fieldType: ft,
|
||||
defaultValue: ft === "an" ? CURRENT_YEAR : undefined,
|
||||
};
|
||||
fields.push(field);
|
||||
tokens.push({ type: "field", value: "", field });
|
||||
fIdx++;
|
||||
} else {
|
||||
tokens.push({ type: "static", value: part });
|
||||
}
|
||||
}
|
||||
|
||||
if (fields.length === 0) return null;
|
||||
|
||||
return {
|
||||
id: `dyn_${hashPattern(pattern)}`,
|
||||
pattern,
|
||||
tokens,
|
||||
fields,
|
||||
frequency: 0,
|
||||
exampleSubject: pattern,
|
||||
isSeed: true,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter existing subjects by query (plain text substring match).
|
||||
* Returns unique matches, limited to `limit`.
|
||||
|
||||
Reference in New Issue
Block a user