Commit Graph

258 Commits

Author SHA1 Message Date
Chandler Copeland
43f396b4c5 fix(12-02): body scroll lock and z-index/portal fix for PreviewModal
- Bug 1: add useEffect that locks document.body.overflow on mount and
  restores original value on unmount — prevents page scrolling behind modal
- Bug 2: render modal via ReactDOM.createPortal to document.body so it
  escapes the sticky sidebar's stacking context; raise z-index to 9999
  so backdrop sits definitively above all FieldPlacer overlay boxes
  (zIndex: 10/12) and dnd-kit DragOverlay regardless of parent context
2026-03-21 15:50:22 -06:00
Chandler Copeland
422c9a89aa docs(12-02): checkpoint after tasks 1+2 — PreparePanel preview wiring complete
- SUMMARY.md created documenting Tasks 1+2 completion
- STATE.md updated: position at checkpoint:human-verify Task 3
- Decisions recorded: previewToken lifted to DocumentPageClient, wiring pattern
2026-03-21 15:38:18 -06:00
Chandler Copeland
720d07fd54 feat(12-02): FieldPlacer onFieldsChanged callback prop after every persistFields call
- Add onFieldsChanged?: () => void to FieldPlacerProps interface
- Destructure onFieldsChanged in function signature
- Call onFieldsChanged?.() after persistFields in handleDragEnd (new field drop)
- Call onFieldsChanged?.() after persistFields in handleZonePointerUp move case
- Call onFieldsChanged?.() after persistFields in handleZonePointerUp resize case
- Call onFieldsChanged?.() after persistFields in delete button onClick
- Add onFieldsChanged to useCallback dependency arrays (handleDragEnd, handleZonePointerUp)
2026-03-21 15:36:56 -06:00
Chandler Copeland
de195a3e80 feat(12-02): PreparePanel preview state, button, gating, modal, and DocumentPageClient wiring
- Add previewToken/onPreviewTokenChange props to PreparePanel (lifted to DocumentPageClient)
- Add handlePreview async function fetching POST /api/documents/[id]/preview
- Add Preview button (gray-700) before Send button; text cycles Preview/Preview again
- Gate Send button on previewToken === null (requires fresh preview before send)
- Wrap TextFillForm onChange to reset previewToken on text fill changes
- Render PreviewModal conditionally when showPreview && previewBytes
- Create DocumentPageClient.tsx: holds previewToken state, passes reset callback to both FieldPlacer (via PdfViewerWrapper/PdfViewer) and PreparePanel
- Update PdfViewerWrapper and PdfViewer to accept and forward onFieldsChanged prop
- Update page.tsx to use DocumentPageClient instead of direct PreparePanel/PdfViewerWrapper siblings
2026-03-21 15:36:47 -06:00
Chandler Copeland
aba622a765 docs(12-01): complete filled-document-preview plan 01
- SUMMARY.md with task commits, decisions, self-check
- STATE.md updated: position advanced to phase 12 plan 1/2 complete
- ROADMAP.md updated: phase 12 in progress (1/2 plans complete)
- PREV-01 marked complete in REQUIREMENTS.md
2026-03-21 15:31:42 -06:00
Chandler Copeland
f4589391ff feat(12-01): PreviewModal component with react-pdf Document/Page
- 'use client' component accepting ArrayBuffer prop and onClose callback
- Configures pdfjs worker independently from PdfViewer module
- Imports AnnotationLayer.css and TextLayer.css
- Prev/Next page navigation with disabled states
- Fixed overlay (rgba black 70%) with white inner container
2026-03-21 15:30:07 -06:00
Chandler Copeland
99205bca9f feat(12-01): POST /api/documents/[id]/preview route
- Auth-guarded Next.js 15 route handler with async params
- Versioned temp path (_preview_{timestamp}.pdf) — never overwrites _prepared.pdf
- Path traversal guard mirrors prepare route
- Mirrors 422 guards for agent-signature-missing and agent-initials-missing
- try/finally ensures temp file deleted after bytes are read
2026-03-21 15:29:47 -06:00
Chandler Copeland
10d4eb738a docs(12-filled-document-preview): create phase 12 plan
Two-plan wave structure for PREV-01: preview API route + modal (Plan 01,
Wave 1) then PreparePanel/FieldPlacer wiring + human verification (Plan 02,
Wave 2). Send button gated on previewToken staleness detection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 15:25:48 -06:00
Chandler Copeland
06b96cd3c2 docs(12): research phase filled-document-preview 2026-03-21 15:20:26 -06:00
Chandler Copeland
f3cf24078b docs(phase-11.1): complete phase execution 2026-03-21 15:15:08 -06:00
Chandler Copeland
a9607763fa docs(11.1-03): complete agent-and-client-initials E2E verification plan 2026-03-21 15:08:49 -06:00
Chandler Copeland
babc92be34 docs(11.1-02): complete agent-initials prepare pipeline plan
- Add 11.1-02-SUMMARY.md with plan execution results
- Update STATE.md: current position, session continuity, decisions
- Update ROADMAP.md: phase 11.1 progress (2/3 summaries)
2026-03-21 15:05:00 -06:00
Chandler Copeland
c876579637 feat(11.1-02): update prepare route to fetch agentInitialsData, add 422 guard, pass to preparePdf
- Fetch agentInitialsData alongside agentSignatureData in single DB query
- Add 422 guard returning { error: 'agent-initials-missing' } when agent-initials fields present but no initials saved
- Pass agentInitialsData as 6th arg to preparePdf()
2026-03-21 15:03:14 -06:00
Chandler Copeland
fae1cf1b68 feat(11.1-02): add agentInitialsData param to preparePdf and embed at agent-initials fields
- Add agentInitialsData as 6th optional param (default null)
- Embed agent initials PNG once before field loop (embed-once-draw-many pattern)
- Add agent-initials branch in field loop: drawImage at field coordinates
- Existing initials (client-initials) and agent-signature branches untouched
2026-03-21 15:02:51 -06:00
Chandler Copeland
ec7f726cae docs(11.1-01): complete agent initials storage and UI plan
- Create 11.1-01-SUMMARY.md with task commits, decisions, and file inventory
- Update STATE.md: position, decisions (4 recorded), session continuity
- Update ROADMAP.md: phase 11.1 progress (1/3 plans complete, In Progress)
- Mark INIT-01, INIT-02, INIT-03, INIT-04 complete in REQUIREMENTS.md
2026-03-21 15:01:32 -06:00
Chandler Copeland
d9f618f69a feat(11.1-01): AgentInitialsPanel component, profile page section, FieldPlacer token
- Create AgentInitialsPanel.tsx (clone of AgentSignaturePanel with 80px canvas, /api/agent/initials endpoint)
- Update profile/page.tsx to fetch agentInitialsData and render AgentInitialsPanel below signature section
- Add orange 'Agent Initials' token (7th entry) to FieldPlacer PALETTE_TOKENS
- Add 'agent-initials' to FieldPlacer validTypes Set
2026-03-21 14:59:29 -06:00
Chandler Copeland
33f499c61b feat(11.1-01): DB migration, API routes, schema type updates for agent initials storage
- Add agentInitialsData text column to users table (drizzle/0009_luxuriant_catseye.sql)
- Add 'agent-initials' to SignatureFieldType union in schema.ts
- Update isClientVisibleField() to exclude both agent-signature and agent-initials
- Create GET/PUT /api/agent/initials route with auth guard and 50KB size limit
2026-03-21 14:58:39 -06:00
Chandler Copeland
ae17e017d3 docs(11.1): create phase plan — agent and client initials
Added INIT-01 through INIT-04 requirements to REQUIREMENTS.md. Updated
ROADMAP.md with Phase 11.1 goal, success criteria, and plan list. Created
three plan files mirroring Phase 11 structure: 11.1-01 (DB migration, API
routes, AgentInitialsPanel, FieldPlacer token), 11.1-02 (preparePdf
agentInitialsData param + prepare route guard), 11.1-03 (human E2E
verification checkpoint).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 14:55:00 -06:00
Chandler Copeland
e673799246 docs(11.1): research phase — agent and client initials
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 14:46:00 -06:00
Chandler Copeland
efa7edddbb docs(phase-11): complete phase execution 2026-03-21 14:39:13 -06:00
Chandler Copeland
e594e27f4e docs(11-03): complete Phase 11 human verification — all AGENT requirements confirmed
- Created 11-03-SUMMARY.md: E2E human verification approved; AGENT-01 through AGENT-04 confirmed live
- Updated STATE.md: Phase 11 complete (11/13 phases), plan 3/3 done, decisions appended
- Updated ROADMAP.md: Phase 11 marked 3/3 Complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 14:33:10 -06:00
Chandler Copeland
f8de782a64 docs(11-02): complete agent signature bake-in prepare pipeline plan
- 11-02-SUMMARY.md: preparePdf() embeds agent PNG + prepare route 422 guard
- STATE.md: advance to plan 2 of 3, add phase 11-02 decisions, update metrics
- ROADMAP.md: phase 11 progress updated (2/3 plans complete)
- REQUIREMENTS.md: AGENT-04 marked complete
2026-03-21 14:08:37 -06:00
Chandler Copeland
b2e9810d60 feat(11-02): prepare route fetches agentSignatureData, 422 guard, passes to preparePdf
- Import users and getFieldType from @/lib/db/schema
- Strengthen session guard to !session?.user?.id (matches established pattern)
- Fetch agentSignatureData from users table for the authenticated agent
- 422 guard: return { error: 'agent-signature-missing' } when agent-sig fields exist but no signature saved
- Pass agentSignatureData as 5th arg to preparePdf()
2026-03-21 14:07:01 -06:00
Chandler Copeland
d9652e1f87 feat(11-02): preparePdf() gains agentSignatureData param and embeds at agent-sig fields
- Add optional agentSignatureData: string | null = null as 5th parameter
- Import PDFImage from @cantoo/pdf-lib for typed agentSigImage variable
- Embed PNG once before field loop, store as agentSigImage
- Replace agent-signature stub with drawImage at field.x/y/width/height
2026-03-21 14:06:12 -06:00
Chandler Copeland
f1dbf45e37 docs(11-01): complete agent saved signature storage and UI plan
- Create 11-01-SUMMARY.md documenting agentSignatureData DB column, API routes, AgentSignaturePanel, profile page, nav link, FieldPlacer token
- Update STATE.md: advance to Plan 1 of 3, record Phase 11 decisions and metrics
- Update ROADMAP.md: Phase 11 now In Progress (1/3 summaries)
- Mark requirements AGENT-01, AGENT-02, AGENT-03 complete in REQUIREMENTS.md
2026-03-21 14:04:54 -06:00
Chandler Copeland
f383f91445 feat(11-01): AgentSignaturePanel, profile page, PortalNav link, FieldPlacer token
- Create AgentSignaturePanel.tsx with signature_pad canvas, save/update/thumbnail flow
- Create /portal/profile page (server component fetching agentSignatureData)
- Add Profile link to PortalNav navLinks array
- Add red 'Agent Signature' token to FieldPlacer PALETTE_TOKENS (6th entry)
2026-03-21 14:02:51 -06:00
Chandler Copeland
e07ed306cd feat(11-01): DB migration and API routes for agent signature storage
- Add agentSignatureData TEXT column to users table in schema.ts
- Generate migration 0008_windy_cloak.sql (ALTER TABLE users ADD COLUMN agent_signature_data text)
- Apply migration to local postgres database
- Create GET/PUT /api/agent/signature route with auth guard and input validation
2026-03-21 14:02:01 -06:00
Chandler Copeland
7783543158 docs(11-agent-saved-signature-and-signing-workflow): create phase plan 2026-03-21 13:55:38 -06:00
Chandler Copeland
e89c2b3f1b docs(11): research agent saved signature phase 2026-03-21 13:48:26 -06:00
Chandler Copeland
eeb533e3e0 docs(10-03): complete Phase 10 — expanded field types end-to-end
10-03-SUMMARY.md created. ROADMAP.md marks all phase 10 plans complete.
STATE.md advances to Phase 11 (Agent Saved Signature), 10/13 phases done.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 13:42:28 -06:00
Chandler Copeland
e179b9284f fix(10-03): transparent field boxes and fixed-size checkbox in FieldPlacer
- preparePdf: remove opaque fill from all field type rectangles (signature,
  initials, checkbox, date, text) — underlying PDF content now shows through
- preparePdf: checkbox draws X lines only (no border rectangle); date draws
  no placeholder at all; text draws nothing (position marker only)
- sign route: remove white overwrite rectangle on date stamp — date text
  draws directly on existing PDF content
- FieldPlacer: suppress resize corner handles for checkbox fields; hide
  "Checkbox" label (too small at 24x24pt); checkbox is fixed-size only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 13:41:04 -06:00
Chandler Copeland
4d699fd474 wip: phase-10 paused at plan-03 task-2/2 (human verification checkpoint) 2026-03-21 13:30:44 -06:00
Chandler Copeland
a5173fe455 fix(portal): serve signed PDF in viewer after document is signed
When signedFilePath is set, /api/documents/[id]/file now returns the
signed PDF so agent sees embedded signatures and initials in the portal
viewer. Falls back to original PDF when not yet signed.
2026-03-21 13:25:26 -06:00
Chandler Copeland
50f082d20f feat(10-03): extend signing page for initials, overlay suppression, and updated progress counting
- Add optional title prop to SignatureModal (defaults to "Add Signature"); button label derives from title
- Add activeFieldType state and setActiveFieldType in SigningPageClient
- handleFieldClick opens modal for both client-signature and initials fields
- handleSubmit and SigningProgressBar total now count both client-signature and initials
- handleJumpToNext jumps to next unsigned required field (client-signature or initials only)
- Non-interactive fields (text/checkbox/date) suppressed from field overlay rendering via early return
- Initials overlays use purple pulse animation (pulse-border-purple); signature overlays use blue
- SignatureModal receives title prop: "Add Initials" for initials, "Add Signature" for client-signature
2026-03-21 12:54:57 -06:00
Chandler Copeland
9f190b3fc8 docs(10-01): complete expanded field types palette plan — SUMMARY, STATE, ROADMAP, REQUIREMENTS
- Create 10-01-SUMMARY.md with decisions, deviations, and phase readiness
- Update STATE.md: phase 10 current position, 10-01 decisions recorded
- Update ROADMAP.md: phase 10 plan progress (1/3 plans complete)
- Update REQUIREMENTS.md: mark FIELD-03 complete
2026-03-21 12:52:13 -06:00
Chandler Copeland
9875c1a0af docs(10-02): complete type-branched field rendering and POST handler fix plan
- Create 10-02-SUMMARY.md with decisions, commits, and deviation docs
- Update STATE.md with decisions and metrics
- Update ROADMAP.md phase 10 progress (2/3 summaries)
- Mark FIELD-02 and FIELD-04 requirements complete
2026-03-21 12:51:42 -06:00
Chandler Copeland
d395d85ebb feat(10-02): fix POST handler — signable field filter and date stamping at sign time
- Add getFieldType to schema import
- Add PDFDocument, StandardFonts, rgb from @cantoo/pdf-lib for date stamping
- Add readFile, writeFile, unlink from node:fs/promises
- Hoist const now = new Date() to before step 8 (shared for date stamp + DB update)
- Step 8a: stamp signing date onto date fields in prepared PDF before embed
- Step 8b: filter signableFields to client-signature and initials only
- signaturesWithCoords now maps only signable fields (no 500 on text/checkbox/date)
- Update embedSignatureInPdf call to use dateStampedPath
- Fire-and-forget cleanup of temporary .datestamped.tmp file after embed
2026-03-21 12:50:21 -06:00
Chandler Copeland
1e92ca363a feat(10-01): update handleDragEnd and renderFields for typed field creation
- handleDragEnd: determine droppedType from active.id with validTypes set guard
- handleDragEnd: checkbox fields drop at 24x24pt; all other types drop at 144x36pt
- handleDragEnd: newField now includes type property set to droppedType
- renderFields: use getFieldType() + PALETTE_TOKENS lookup to get per-field color and label
- renderFields: border, background, and text color are now driven by fieldColor
- renderFields: resize handle corners use fieldColor instead of hardcoded blue
- renderFields: span displays fieldLabel instead of hardcoded 'Signature'
2026-03-21 12:50:18 -06:00
Chandler Copeland
4140c220b1 feat(10-01): parameterize DraggableToken and add four new palette tokens
- Add PALETTE_TOKENS array with 5 typed tokens (Signature/blue, Initials/purple, Checkbox/green, Date/amber, Text/slate)
- Update DraggableToken to accept id, label, color props with per-type styling
- Change isDraggingToken from boolean to string | null to track active token id
- Update onDragStart to record active.id instead of just true
- Replace single static token with PALETTE_TOKENS.map() in palette JSX
- Update DragOverlay ghost to show correct label, color, and checkbox-appropriate dimensions (24x24 vs 144x36)
2026-03-21 12:49:25 -06:00
Chandler Copeland
7510c8ee08 feat(10-02): type-branched field rendering in preparePdf()
- Add getFieldType import from @/lib/db/schema
- Replace single-variant blue loop with branched rendering per field type
- client-signature: unchanged blue rectangle + "Sign Here"
- initials: purple rectangle + "Initials" label
- checkbox: gray rectangle + X diagonal lines (embedded at prepare time)
- date: amber rectangle + "Date" label (actual date stamped at POST time)
- text: light gray rectangle, no label (visual marker only)
- agent-signature: skipped (no placeholder drawn)
2026-03-21 12:49:20 -06:00
Chandler Copeland
2205a7bce5 docs(10-expanded-field-types-end-to-end): create phase 10 plan
Three plans covering the full field type pipeline end-to-end:
- 10-01: FieldPlacer palette extension (5 typed tokens, per-type colors, typed DragOverlay)
- 10-02: preparePdf() type-branched rendering + POST route signable filter and date stamp
- 10-03: SigningPageClient initials capture + overlay suppression + human verification

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 12:45:25 -06:00
Chandler Copeland
fadfbb3fd7 docs(phase-10): research expanded field types end-to-end
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 12:38:49 -06:00
Chandler Copeland
d1e4979e1f docs(phase-9): complete phase execution 2026-03-21 12:32:39 -06:00
Chandler Copeland
27003af70f fix(09-01): bg-gray-100 on prepare panel, stack field name/value rows to fit narrow panel 2026-03-21 12:31:20 -06:00
Chandler Copeland
28a460e9cc fix(09-01): sticky prepare panel, bg-gray-50 background, max-height scroll 2026-03-21 12:29:01 -06:00
Chandler Copeland
a77a144f6f fix(09-01): fix hydration mismatch in TextFillForm — use useEffect for initialData seed 2026-03-21 12:27:09 -06:00
Chandler Copeland
a784e50e10 docs(09-01): complete client-property-address plan — SUMMARY, STATE, ROADMAP
- 09-01-SUMMARY.md created documenting all 3 tasks and 2 auto-fixed deviations
- STATE.md updated: Phase 9 complete, session continuity, two decisions added
- ROADMAP.md updated: Phase 9 marked Complete (1/1 plans)
- REQUIREMENTS.md: CLIENT-04 and CLIENT-05 marked complete
2026-03-21 12:22:12 -06:00
Chandler Copeland
11f2b80217 fix(09-01): fix propertyAddress pre-seed and polish PreparePanel text fill UI
- TextFillForm: add initialData prop; buildInitialRows seeds rows from
  pre-seeded data so propertyAddress row renders populated on mount
- PreparePanel: pass initialData={...} to TextFillForm so the lazy
  useState in PreparePanel correctly flows through to the visible UI
- TextFillForm: replace AcroForm jargon instruction with friendly copy
- TextFillForm: add Field name / Value column headers for clear layout
- TextFillForm: improve spacing (py-1.5), softer remove button (gray→red on hover)
- TypeScript: npx tsc --noEmit passes clean
2026-03-21 12:20:08 -06:00
Chandler Copeland
fa9981edd9 feat(09-01): UI layer — property address modal input, profile display, PreparePanel pre-seed
- ClientModal: add defaultPropertyAddress prop, property address input field after email
- ClientProfileClient: add propertyAddress to Props type, display address under email when non-null, pass defaultPropertyAddress to edit modal
- documents/[docId]/page.tsx: extend client select to include propertyAddress, pass as clientPropertyAddress to PreparePanel
- PreparePanel: add clientPropertyAddress prop, lazy-initialize textFillData with { propertyAddress } when client has address
2026-03-21 12:15:27 -06:00
Chandler Copeland
baa1c785a5 feat(09-01): add property_address column to clients — schema, migration, server actions
- Add propertyAddress: text("property_address") nullable column to clients pgTable
- Generate migration drizzle/0007_equal_nekra.sql: ALTER TABLE "clients" ADD COLUMN "property_address" text
- Apply migration successfully to local postgres database
- Extend clientSchema Zod schema with propertyAddress: z.string().optional()
- createClient: persist propertyAddress || null to coerce empty string to NULL
- updateClient: persist propertyAddress || null alongside name, email, updatedAt
2026-03-21 12:13:55 -06:00