Files
ArchiTools/src/modules/registratura/components/subject-template-input.tsx
T
AI Assistant b3b585e7c8 feat(registratura): subject autocomplete with inline template fields
- New subject-template-service: extracts reusable templates from existing
  subjects by detecting variable parts (numbers, years, text after separators)
- Template input component: inline editable fields within static text
  (e.g., "Cerere CU nr. [___]/[____] — [___________]")
- Two-tier autocomplete dropdown: templates sorted by frequency (top) +
  matching existing subjects (bottom)
- Learns from database: more entries = better suggestions
- Follows existing contact autocomplete pattern (focus/blur, onMouseDown)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 08:40:37 +02:00

84 lines
2.3 KiB
TypeScript

"use client";
import { useEffect, useRef } from "react";
import { X } from "lucide-react";
import { cn } from "@/shared/lib/utils";
import type { SubjectTemplate } from "../services/subject-template-service";
interface SubjectTemplateInputProps {
template: SubjectTemplate;
fieldValues: Record<string, string>;
onFieldChange: (fieldId: string, value: string) => void;
onClear: () => void;
}
export function SubjectTemplateInput({
template,
fieldValues,
onFieldChange,
onClear,
}: SubjectTemplateInputProps) {
const firstFieldRef = useRef<HTMLInputElement>(null);
// Auto-focus first field on mount
useEffect(() => {
const timer = setTimeout(() => firstFieldRef.current?.focus(), 50);
return () => clearTimeout(timer);
}, []);
let fieldRendered = 0;
return (
<div
className={cn(
"flex flex-wrap items-baseline gap-0.5",
"min-h-9 w-full rounded-md border border-input bg-transparent px-3 py-1.5",
"text-sm shadow-xs mt-1",
)}
>
{template.tokens.map((token, i) => {
if (token.type === "static") {
return (
<span
key={`s${i}`}
className="whitespace-nowrap text-muted-foreground"
>
{token.value}
</span>
);
}
const field = token.field!;
const isFirst = fieldRendered === 0;
fieldRendered++;
return (
<input
key={field.id}
ref={isFirst ? firstFieldRef : undefined}
value={fieldValues[field.id] ?? ""}
onChange={(e) => onFieldChange(field.id, e.target.value)}
placeholder={field.placeholder}
className={cn(
"border-b-2 border-dashed border-primary/40 bg-transparent",
"text-sm font-medium text-foreground",
"px-1 py-0 outline-none",
"focus:border-primary focus:border-solid",
"placeholder:text-muted-foreground/50 placeholder:italic placeholder:text-xs",
field.width,
)}
/>
);
})}
<button
type="button"
onClick={onClear}
className="ml-auto shrink-0 text-muted-foreground hover:text-foreground transition-colors"
title="Renunță la șablon"
>
<X className="h-3.5 w-3.5" />
</button>
</div>
);
}