7.3 KiB
7.3 KiB
Phase 20: Apply Template and Portal Nav - Context
Gathered: 2026-04-06 Status: Ready for planning
## Phase BoundaryWires saved document_templates into the document creation flow. The "My Templates" tab in AddDocumentModal lets the agent pick a saved template — the document is created with all fields copied (fresh UUIDs), roles auto-mapped to client contacts, and text hints surfaced as quick-fill suggestions in PreparePanel.
Note: Success criterion 5 (Templates nav link + /portal/templates list page) was completed in Phase 19 and is already live. This phase does NOT need to re-implement nav or list page.
Deliverables:
AddDocumentModal— add "My Templates" tab showingdocument_templates; "Forms Library" tab preserved unchangedPOST /api/documents— extend to acceptdocumentTemplateId; copies fields with fresh UUIDs, maps roles to client contacts- PreparePanel — text hints from template fields appear as quick-fill suggestion chips
GET /api/templates— already exists; needs to return enough data for the modal (name, form name, field count)
AddDocumentModal Redesign
- D-01: Modal gets two tabs: "Forms Library" (existing behavior, unchanged) and "My Templates" (new tab showing saved
document_templates). Tab switching is client-side state — no page reload. - D-02: "My Templates" tab fetches from
GET /api/templates— returns all activedocument_templates. Each row shows: template name, form name, field count. Agent clicks a row to select it. - D-03: No second "role mapping" step in the modal. Agent picks template → clicks "Add Document" → document is created immediately. Role assignment happens in PreparePanel (existing flow).
- D-04: The "Forms Library" tab, "Or upload a custom PDF" section, and all existing modal behavior remain completely unchanged. This is a pure additive change to
AddDocumentModal.tsx.
Apply Template Operation (API)
- D-05:
POST /api/documentsaccepts a new optional body field:documentTemplateId: string. When present, the server reads the template'ssignatureFields, copies them with new UUIDs (viacrypto.randomUUID()), and stores the copy as the new document'sfields(indocuments.signatureFieldsor the existing fields store — researcher to confirm field storage pattern). - D-06: Role-to-email mapping at creation time: the server reads the template's role labels from the copied fields'
signerEmailvalues. It builds asignersarray on the new document by mapping roles by index: role[0] →client.email, role[1] →client.contacts[0]?.email(if present), role[2+] → left as-is (role label string). This auto-mapping happens server-side during document creation. - D-07: Fresh UUIDs: every
SignatureFieldDataobject copied from the template getsid: crypto.randomUUID(). No template field ID may appear in the new document's fields. - D-08: The created document's
formTemplateIdis set to the template'sformTemplateId(so the PDF is correctly associated). The document is NOT linked to thedocumentTemplaterecord after creation — it's a snapshot, not a live reference.
Text Hints as Quick-Fill
- D-09: When a document is created from a template, field
hintvalues are copied verbatim fromdocumentTemplates.signatureFields[].hintinto the new document's fields. - D-10: In PreparePanel, when the agent selects a text field: if the field has a
hint, it appears as a clickable suggestion chip in the existing "Quick Fill" suggestions area (same location as existing suggestions). Clicking the chip fills the field with the hint text (same behavior as existing quick-fill). - D-11: Hints are NOT shown as placeholder text on the field itself — only in the PreparePanel suggestions area on the right.
- D-12: PreparePanel already has a
textFillDatasystem and a Quick Fill area. The hint chip is added to that same section — no new UI region needed.
Navigation (Already Delivered — No Work Needed)
- Already done in Phase 19: "Templates" nav link between Clients and Profile ✓
- Already done in Phase 19:
/portal/templateslist page ✓ - Phase 20 does NOT re-implement or touch the nav or templates list page.
Claude's Discretion
- Exact tab styling in AddDocumentModal (pill tabs vs underline tabs)
- Empty state for "My Templates" tab when no templates exist
- How field count is displayed in the template picker row
- Order of roles when more than 2 are present in the template
<canonical_refs>
Canonical References
Downstream agents MUST read these before planning or implementing.
Files Being Modified
teressa-copeland-homes/src/app/portal/_components/AddDocumentModal.tsx— add My Templates tabteressa-copeland-homes/src/app/api/documents/route.ts— handledocumentTemplateIdin POSTteressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/PreparePanel.tsx— surface field hints as quick-fill chips
Existing Patterns to Reuse
teressa-copeland-homes/src/lib/db/schema.ts—documentTemplatestable,SignatureFieldDatatype,clients.contactsJSONB shape,documents.signerstypeteressa-copeland-homes/src/app/api/templates/route.ts— GET /api/templates (existing, returns active templates)teressa-copeland-homes/src/app/api/documents/route.ts— existing POST handler (extend, don't replace)teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/PreparePanel.tsx— existing Quick Fill / textFillData systemteressa-copeland-homes/src/app/portal/_components/ClientProfileClient.tsx— context for where AddDocumentModal is called (has access toclientobject with contacts)
Phase 19 Output (Canonical)
teressa-copeland-homes/src/app/portal/(protected)/templates/page.tsx— list page (no changes needed)teressa-copeland-homes/src/app/portal/_components/PortalNav.tsx— Templates nav link (no changes needed)teressa-copeland-homes/src/app/api/templates/[id]/route.ts— PATCH/DELETE (no changes needed)
Phase 18 Output (Canonical)
documentTemplatestable withsignatureFieldsJSONB — source of truth for template field data
</canonical_refs>
## Specific Ideas- The "My Templates" tab in AddDocumentModal calls
GET /api/templates(same endpoint used by the templates list page). If the response includessignatureFields, the tab can show field count client-side. - Field copy pseudocode:
const copiedFields = template.signatureFields.map(f => ({ ...f, id: crypto.randomUUID() })) - Role-to-email mapping pseudocode: collect unique role labels from copied fields in order of first appearance →
roles[0]→client.email,roles[1]→client.contacts?.[0]?.email ?? roles[1] - PreparePanel hint display: when
selectedFieldIdis set andfields.find(f => f.id === selectedFieldId)?.hintexists, render it as a chip in the Quick Fill section alongside existing suggestions.
- Template versioning (when a template is updated, existing documents created from it are unaffected — already addressed by D-08 snapshot approach)
- Bulk-apply template to multiple clients at once
- Template categories or tags for organizing the My Templates list
Phase: 20-apply-template-and-portal-nav Context gathered: 2026-04-06