# Phase 16: Multi-Signer UI - Context

**Gathered:** 2026-04-03
**Status:** Ready for planning

<domain>
## Phase Boundary

UI-only changes. No new API routes. No schema migrations. Phase 16 wires the Phase 15 backend into the agent's PreparePanel/FieldPlacer workflow and adds per-signer status to the dashboard.

Three UI areas:
1. **PreparePanel signer list** — add/remove signers by email; signers saved to `documents.signers` via existing document update API
2. **FieldPlacer signer assignment** — active-signer selector + per-signer field coloring; fields tagged with `signerEmail` via existing field placement API
3. **Send-block validation + dashboard** — pre-send check for unassigned fields; `N/M signed` badge on dashboard

</domain>

<decisions>
## Implementation Decisions

### Signer Color Palette

- **D-01:** Colors are auto-assigned when a signer is added — no agent choice needed. Fixed palette in order:
  1. `#6366f1` (indigo)
  2. `#f43f5e` (rose)
  3. `#10b981` (emerald)
  4. `#f59e0b` (amber)
  - If more than 4 signers, cycle the palette. The color is stored in `documents.signers[].color` when saved to DB.

### PreparePanel Signer List

- **D-02:** Signer list UI lives inside PreparePanel — between the existing "AI Auto-place" button section and the "Prepare and Send" button. It appears only for Draft documents (same gate as the rest of PreparePanel).
- **D-03:** UI: an email input + "Add" button. Below it, a list of added signers showing a colored dot (their color), their email, and a remove (×) button. Signers are saved to the document record immediately when added/removed (PATCH to document update API, or inline save on "Prepare and Send" click — planner decides which is simpler).
- **D-04:** Agent must add at least one signer before sending. If `documents.signers` is empty AND the document has client-visible fields, the send is blocked with a message: "Add at least one signer before sending."

### FieldPlacer Active Signer Selector

- **D-05:** An "Active signer" dropdown appears at the top of FieldPlacer (above the field palette), but ONLY when `documents.signers` has at least one signer. When no signers are configured, FieldPlacer behaves exactly as today.
- **D-06:** All fields dragged onto the canvas while a signer is selected automatically get `signerEmail` set to that signer's email. The field box is colored using the signer's color (from `documents.signers`) instead of the field-type color.
- **D-07:** Fields with no `signerEmail` (agent-signature, agent-initials, OR client fields placed before signers were configured) use the existing type-based color (unchanged behavior).
- **D-08:** The active signer selector defaults to the first signer in `documents.signers[]` when the component loads. Agent can switch before dragging fields.

### Send-Block Validation

- **D-09:** Before calling `/api/documents/[id]/send`, PreparePanel checks: count of client-visible fields (`isClientVisibleField`) with no `signerEmail`. If count > 0:
  - Show red outline on each unassigned field in FieldPlacer (pass a `validationErrors` prop or similar from DocumentPageClient)
  - Show inline error below the Send button: "X field(s) need a signer assigned before sending."
  - Block the API call.
- **D-10:** The red highlight is a validation state, not permanent — it clears as soon as the agent assigns signers to those fields.

### Dashboard Per-Signer Status

- **D-11:** The documents dashboard table gains a "Signers" column (or augments the existing Status column). For documents where `documents.signers` is non-empty AND status is "Sent" (partially signed): show `N/M signed` badge (e.g., `1/2 signed`). Computed from counting `signingTokens WHERE documentId = X AND usedAt IS NOT NULL` vs total tokens for that document.
- **D-12:** For single-signer documents (no `documents.signers`), this column shows nothing — status badge is unchanged.
- **D-13:** For fully-signed documents (status = "Signed"), the existing "Signed" badge is sufficient — no N/M badge needed.

### Claude's Discretion
- Whether to save signers on every add/remove vs on "Prepare and Send" click (planner picks simpler approach)
- Exact placement of "Active signer" selector within FieldPlacer layout
- Whether the N/M badge appears in its own column or appended to the existing Status column
- Email validation UX for the signer input (prevent duplicate emails, basic format check)

</decisions>

<canonical_refs>
## Canonical References

**Downstream agents MUST read these before planning or implementing.**

### Files Being Modified
- `teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/PreparePanel.tsx` — Add signer list UI + send-block validation
- `teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx` — Active signer selector + per-signer field coloring
- `teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/DocumentPageClient.tsx` — Thread signers state between PreparePanel and FieldPlacer
- Dashboard document table (find exact file via grep for "DocumentsTable" or similar)

### Schema (Phase 14 output)
- `teressa-copeland-homes/src/lib/db/schema.ts` — `DocumentSigner` interface `{ email, color }`, `documents.signers` JSONB, `isClientVisibleField()`

### Phase Context
- `.planning/phases/14-multi-signer-schema/14-CONTEXT.md` — Schema decisions
- `.planning/phases/15-multi-signer-backend/15-CONTEXT.md` — Backend decisions (send route, field filtering)

</canonical_refs>

<code_context>
## Existing Code Insights

### Reusable Assets
- `PALETTE_TOKENS` in `FieldPlacer.tsx` — existing per-type color palette (lines 70-78); signer colors augment this, not replace it — fields with a signer use signer color, fields without use type color
- `isClientVisibleField()` in `schema.ts` — already used in FieldPlacer; reuse for send-block validation check
- `DocumentSigner` interface — already in schema.ts from Phase 14
- Existing field-click-to-select UX in FieldPlacer — the `selectedFieldId` and `onFieldSelect` props are already threaded through; the active signer selector builds alongside this

### Established Patterns
- PreparePanel receives document state as props from DocumentPageClient (`DocumentPageClient.tsx` is the state owner)
- FieldPlacer uses `onFieldsChanged` callback to bubble field changes up — signer assignment changes follow same pattern
- Field colors computed inline in FieldPlacer at render time from `PALETTE_TOKENS.find(t => t.id === fieldType)` — signerEmail check added before this lookup
- Dashboard uses Drizzle queries in a server component — adding a token count join follows same pattern

### Integration Points
- `documents.signers` (nullable JSONB) — read in PreparePanel to seed the signer list; written via document update call when signers are modified
- `SignatureFieldData.signerEmail?` (Phase 14) — written when field is placed with active signer; read in FieldPlacer for color lookup and in PreparePanel for send-block validation
- `signingTokens` — read (count query) in dashboard server component for N/M badge

</code_context>

<specifics>
## Specific Ideas

- Signer color palette order: indigo → rose → emerald → amber (D-01). These contrast well against each other and against the existing type colors.
- The "Active signer" selector is a simple `<select>` or styled dropdown showing signer email with a colored dot. It appears only when `signers.length > 0`.
- Red highlight for unassigned fields: add a CSS border/box-shadow override (e.g., `border: 2px solid #ef4444`) when a field ID is in the `unassignedFieldIds` set passed from DocumentPageClient.

</specifics>

<deferred>
## Deferred Ideas

None — discussion stayed within phase scope.

</deferred>

---

*Phase: 16-multi-signer-ui*
*Context gathered: 2026-04-03*
