# Phase 20: Apply Template and Portal Nav - Context **Gathered:** 2026-04-06 **Status:** Ready for planning ## Phase Boundary Wires 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: 1. `AddDocumentModal` — add "My Templates" tab showing `document_templates`; "Forms Library" tab preserved unchanged 2. `POST /api/documents` — extend to accept `documentTemplateId`; copies fields with fresh UUIDs, maps roles to client contacts 3. PreparePanel — text hints from template fields appear as quick-fill suggestion chips 4. `GET /api/templates` — already exists; needs to return enough data for the modal (name, form name, field count) ## Implementation Decisions ### 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 active `document_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/documents` accepts a new optional body field: `documentTemplateId: string`. When present, the server reads the template's `signatureFields`, copies them with new UUIDs (via `crypto.randomUUID()`), and stores the copy as the new document's `fields` (in `documents.signatureFields` or 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' `signerEmail` values. It builds a `signers` array 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 `SignatureFieldData` object copied from the template gets `id: crypto.randomUUID()`. No template field ID may appear in the new document's fields. - **D-08:** The created document's `formTemplateId` is set to the template's `formTemplateId` (so the PDF is correctly associated). The document is NOT linked to the `documentTemplate` record 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 `hint` values are copied verbatim from `documentTemplates.signatureFields[].hint` into 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 `textFillData` system 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/templates` list 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 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 tab - `teressa-copeland-homes/src/app/api/documents/route.ts` — handle `documentTemplateId` in POST - `teressa-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` — `documentTemplates` table, `SignatureFieldData` type, `clients.contacts` JSONB shape, `documents.signers` type - `teressa-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 system - `teressa-copeland-homes/src/app/portal/_components/ClientProfileClient.tsx` — context for where AddDocumentModal is called (has access to `client` object 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) - `documentTemplates` table with `signatureFields` JSONB — source of truth for template field data ## Specific Ideas - The "My Templates" tab in AddDocumentModal calls `GET /api/templates` (same endpoint used by the templates list page). If the response includes `signatureFields`, 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 `selectedFieldId` is set and `fields.find(f => f.id === selectedFieldId)?.hint` exists, render it as a chip in the Quick Fill section alongside existing suggestions. ## Deferred Ideas - 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*