docs(16-02): complete PreparePanel signer list plan

This commit is contained in:
Chandler Copeland
2026-04-03 16:27:13 -06:00
parent 1c8551c30d
commit 377133074b

View File

@@ -0,0 +1,55 @@
---
phase: 16-multi-signer-ui
plan: "02"
subsystem: ui
tags: [react, typescript, preparepanel, signer-list, send-block-validation]
# Dependency graph
requires:
- phase: 16-multi-signer-ui
plan: "01"
provides: signers prop, onSignersChange, onUnassignedFieldIdsChange threaded from DocumentPageClient
provides:
- SIGNER_COLORS palette constant ['#6366f1', '#f43f5e', '#10b981', '#f59e0b']
- Signer list UI in PreparePanel (email input + "Add Signer" button + colored dot rows + aria-labeled × remove)
- handleAddSigner / handleRemoveSigner with duplicate/format validation
- Send-block validation: fetch fields → check no-signers guard → check unassigned isClientVisibleField fields
- Inline error messages: "Add at least one signer..." and "{N} field(s) need a signer assigned..."
- signers persisted to documents.signers via prepare POST body
affects: [16-04-dashboard-badge]
---
# Phase 16 Plan 02: PreparePanel Signer List UI Summary
## What Was Built
Modified `PreparePanel.tsx` (+104 lines) and `prepare/route.ts` (+5 lines):
**PreparePanel.tsx:**
- `SIGNER_COLORS = ['#6366f1', '#f43f5e', '#10b981', '#f59e0b']` — auto-assigned by index
- Props destructured: `signers`, `onSignersChange`, `onUnassignedFieldIdsChange`
- `handleAddSigner` — validates email format + duplicate, assigns next color from palette, calls `onSignersChange`
- `handleRemoveSigner` — filters signer from list, clears `unassignedFieldIds`
- Signer list UI section (Draft-only, inserted above Prepare and Send):
- Email `<input>` + "Add Signer" `<button>` (height 32px)
- Per-signer row: 8×8px colored dot (`w-2 h-2 rounded-full`) + email text + `×` remove button with `aria-label="Remove signer {email}"` (32×32px touch target)
- Empty state: "No signers added yet."
- Duplicate email warning: "That email is already in the signer list."
- `handlePrepare` extended: fetches current fields via `/api/documents/{id}/fields`, checks unassigned `isClientVisibleField` fields, sets `unassignedFieldIds` and shows inline error if found
- `signers` included in prepare POST body so `documents.signers` is persisted before send route reads it
**prepare/route.ts:**
- Body type extended with `signers?: DocumentSigner[]`
- DB update spreads `{ signers: body.signers }` when provided
# Tech tracking
tech-stack:
added: []
removed: []
changed: []
# Metrics
duration: 4min
commit: 1c8551c