82 lines
4.5 KiB
Markdown
82 lines
4.5 KiB
Markdown
---
|
|
phase: 19-template-editor-ui
|
|
plan: "01"
|
|
subsystem: template-editor
|
|
tags: [template, field-placer, api-routes, portal-nav]
|
|
dependency_graph:
|
|
requires: [18-02]
|
|
provides: [template-mode props on FieldPlacer/PdfViewer/PdfViewerWrapper, three template API routes, Templates nav link]
|
|
affects: [FieldPlacer, PdfViewer, PdfViewerWrapper, PortalNav, /api/templates/[id]/]
|
|
tech_stack:
|
|
added: []
|
|
patterns: [optional-prop-threading, seeds-forms-streaming, soft-delete-filter]
|
|
key_files:
|
|
created:
|
|
- teressa-copeland-homes/src/app/api/templates/[id]/file/route.ts
|
|
- teressa-copeland-homes/src/app/api/templates/[id]/fields/route.ts
|
|
- teressa-copeland-homes/src/app/api/templates/[id]/ai-prepare/route.ts
|
|
modified:
|
|
- teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx
|
|
- teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/PdfViewer.tsx
|
|
- teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/PdfViewerWrapper.tsx
|
|
- teressa-copeland-homes/src/app/portal/_components/PortalNav.tsx
|
|
decisions:
|
|
- "onPersist callback threads through FieldPlacer/PdfViewer/PdfViewerWrapper as optional prop — existing document callers pass no prop and behavior is unchanged"
|
|
- "fieldsUrl and fileUrl override default document API endpoints — enables template editor to redirect both field load and PDF source without forking components"
|
|
- "ai-prepare for templates passes null client context to classifyFieldsWithAI — templates have no pre-fill data by design (D-15)"
|
|
- "All three template routes use isNull(archivedAt) soft-delete filter consistent with Phase 18 pattern"
|
|
metrics:
|
|
duration_minutes: 8
|
|
completed_date: "2026-04-06"
|
|
tasks_completed: 2
|
|
files_changed: 7
|
|
---
|
|
|
|
# Phase 19 Plan 01: Template Editor Infrastructure Summary
|
|
|
|
Infrastructure additions that wire the FieldPlacer/PdfViewer component chain for template-mode operation: optional `onPersist`, `fieldsUrl`, and `fileUrl` props added non-breakingly, three new template API routes created, and Templates nav link added.
|
|
|
|
## Tasks Completed
|
|
|
|
### Task 1: Add onPersist + fieldsUrl props to FieldPlacer, fileUrl to PdfViewer/PdfViewerWrapper, and Templates to PortalNav
|
|
|
|
- Added `onPersist?: (fields: SignatureFieldData[]) => Promise<void> | void` and `fieldsUrl?: string` to `FieldPlacerProps` interface
|
|
- All 4 `persistFields` call sites (drag-drop, move, resize, delete) conditionally use `onPersist` when provided, falling back to `persistFields(docId, next)` otherwise
|
|
- `loadFields` useEffect uses `fieldsUrl ?? /api/documents/${docId}/fields`; `fieldsUrl` added to dependency array
|
|
- `PdfViewer` and `PdfViewerWrapper` accept and pass through all three new props; both `file` src and download `href` use `fileUrl ?? /api/documents/${docId}/file`
|
|
- `PortalNav` navLinks array updated with `{ href: "/portal/templates", label: "Templates" }` between Clients and Profile
|
|
- Commit: 57efd91
|
|
|
|
### Task 2: Create three template API routes — file, fields, ai-prepare
|
|
|
|
- `GET /api/templates/[id]/file` — loads `documentTemplates` with `formTemplate` relation, resolves path in `seeds/forms/`, path traversal guard, streams PDF with `Content-Type: application/pdf`
|
|
- `GET /api/templates/[id]/fields` — returns `template.signatureFields ?? []`
|
|
- `POST /api/templates/[id]/ai-prepare` — runs `extractBlanks` + `classifyFieldsWithAI(blanks, null)`, writes `signatureFields` + explicit `updatedAt: new Date()` to DB, returns `{ fields }`
|
|
- All three routes: auth guard + `isNull(documentTemplates.archivedAt)` soft-delete filter
|
|
- Commit: 275565c
|
|
|
|
## Verification
|
|
|
|
- `npx tsc --noEmit` — 0 errors after each task
|
|
- `npm run build` — succeeds; all three new route paths appear in build output
|
|
- All 7 grep checks passed (onPersist x4 sites, fieldsUrl, fileUrl x2, /portal/templates)
|
|
|
|
## Deviations from Plan
|
|
|
|
None — plan executed exactly as written.
|
|
|
|
## Known Stubs
|
|
|
|
None — all new routes are fully functional. Field loading and persisting have real implementations.
|
|
|
|
## Self-Check: PASSED
|
|
|
|
Files created:
|
|
- /Users/ccopeland/temp/red/teressa-copeland-homes/src/app/api/templates/[id]/file/route.ts — FOUND
|
|
- /Users/ccopeland/temp/red/teressa-copeland-homes/src/app/api/templates/[id]/fields/route.ts — FOUND
|
|
- /Users/ccopeland/temp/red/teressa-copeland-homes/src/app/api/templates/[id]/ai-prepare/route.ts — FOUND
|
|
|
|
Commits:
|
|
- 57efd91 — feat(19-01): add onPersist, fieldsUrl, fileUrl props and Templates nav link
|
|
- 275565c — feat(19-01): create template API routes — file, fields, ai-prepare
|