- DocumentPageClient fetches /api/documents/:docId/fields on mount and aiPlacementKey change
- Derives selectedFieldHint from selected field's hint property
- Passes selectedFieldHint prop to PreparePanel
- PreparePanel renders Template Hint chip in Quick Fill section when hint exists
- Add DocumentTemplateRow type and activeTab/docTemplates/selectedDocTemplate state
- Lazy-fetch /api/templates on first My Templates tab click
- handleSwitchToTemplates lazy-loads on first click only
- handleSelectDocTemplate clears selectedTemplate and customFile (mutual exclusivity)
- handleSelectTemplate now also clears selectedDocTemplate
- handleSubmit: new branch at top sends documentTemplateId to POST /api/documents
- Guard and disabled condition updated to include selectedDocTemplate
- Tab bar renders with underline-style active indicator matching project Tailwind patterns
- Existing Forms Library content and custom upload section wrapped in activeTab === 'forms' conditional
- Parse documentTemplateId from JSON body alongside formTemplateId
- Fetch document template with formTemplate relation for PDF filename
- Copy signatureFields with fresh crypto.randomUUID per field (snapshot independence)
- Map template signer role labels to client email + contacts array
- Return early with inserted doc; existing form-library and upload paths unchanged
- SUMMARY.md updated to reflect all 9 verification steps passed
- TMPL-05 through TMPL-09 confirmed by human live browser test
- TMPL-15 and TMPL-16 marked complete in REQUIREMENTS.md
- STATE.md: Phase 19 marked COMPLETE, progress 98%
- ROADMAP.md: Phase 19 all 3 plans complete
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Server component at /portal/templates/[id] queries documentTemplates with formTemplate relation
- notFound() for archived/missing templates
- TemplatePageClient: state owner mirroring DocumentPageClient pattern
- deriveRolesFromFields initializes Buyer/Seller defaults or extracts from existing fields
- handlePersist merges textFillData hints into f.hint for type='text' fields
- handleAiAutoPlace POSTs to /api/templates/[id]/ai-prepare and increments aiPlacementKey
- Role rename/remove re-fetches fields and PATCHes with updated signerEmail values
- TemplatePanel: 280px right panel with inline styles matching portal design system
- Signers/Roles section with color dots, click-to-rename, remove with ConfirmDialog
- Add role input with preset chips (Buyer, Co-Buyer, Seller, Co-Seller)
- AI Auto-place button (navy) with spinner/loading state and error display
- Save Template button (gold) with success 'Saved' text fading after 3s
- Server component at /portal/templates queries documentTemplates with LEFT JOIN to formTemplates
- TemplatesListClient renders list rows with name, form name, field count, last updated
- Create modal POSTs to /api/templates and navigates to /portal/templates/[id] on success
- Empty state with CTA when no templates exist
- Gold #C9A84C accent, navy #1B2B4B headings, inline styles matching portal patterns
- GET /api/templates/[id]/file: streams form PDF from seeds/forms/ with path traversal guard
- GET /api/templates/[id]/fields: returns signatureFields array (or []) from documentTemplates
- POST /api/templates/[id]/ai-prepare: runs AI field placement with null client context, writes to DB
- All routes: auth guard + isNull(archivedAt) soft-delete filter consistent with Phase 18
- PATCH accepts name and signatureFields for rename and field save per D-10
- PATCH sets updatedAt: new Date() explicitly per D-05
- PATCH returns 404 for archived or missing templates
- DELETE soft-deletes by setting archivedAt: new Date() per D-07 (no hard delete)
- DELETE sets updatedAt: new Date() per D-05, returns 204 No Content
- Both handlers auth-gated with auth() per D-11
- GET lists active templates (archivedAt IS NULL) with LEFT JOIN for formName
- GET computes fieldCount server-side from signatureFields.length per D-12
- POST validates name + formTemplateId, verifies FK exists, returns 201
- Both handlers auth-gated with auth() per D-11
- CREATE TABLE document_templates with 7 columns
- FK constraint form_template_id -> form_templates(id) ON DELETE no action
- No alterations to existing tables