---
phase: 16-multi-signer-ui
plan: 03
type: execute
wave: 2
depends_on: ["16-01"]
files_modified:
  - teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx
autonomous: true
requirements: [MSIGN-02, MSIGN-03]

must_haves:
  truths:
    - "Active signer dropdown appears above palette when signers.length > 0"
    - "Dragged fields auto-get signerEmail of the active signer"
    - "Field boxes with signerEmail render in signer color instead of type color"
    - "Fields with no signerEmail render in existing type color (unchanged)"
    - "Fields in unassignedFieldIds set show red validation outline"
    - "Active signer defaults to first signer on load"
  artifacts:
    - path: "teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx"
      provides: "Active signer selector, per-signer field coloring, validation overlay"
      contains: "Active signer:"
  key_links:
    - from: "FieldPlacer handleDragEnd"
      to: "newField.signerEmail"
      via: "activeSigner.email assignment on field creation"
      pattern: "signerEmail.*activeSigner"
    - from: "FieldPlacer renderFields"
      to: "signer color lookup"
      via: "signers.find matching field.signerEmail for color"
      pattern: "signers.*find.*signerEmail.*color"
---

<objective>
Add the active signer selector dropdown and per-signer field coloring to FieldPlacer per D-05, D-06, D-07, D-08, D-09/D-10.

Purpose: MSIGN-02 (tag fields to signers) and MSIGN-03 (color-coded fields by signer). When a signer is active, every field dropped gets that signer's email. Field boxes render in the signer's color when assigned.

Output: FieldPlacer with active signer dropdown, signer-aware field creation, per-signer color rendering, and red validation overlay for unassigned fields.
</objective>

<execution_context>
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/16-multi-signer-ui/16-CONTEXT.md
@.planning/phases/16-multi-signer-ui/16-UI-SPEC.md
@.planning/phases/16-multi-signer-ui/16-01-SUMMARY.md

<interfaces>
<!-- From Plan 01: signers and unassignedFieldIds are now props on FieldPlacer -->

From FieldPlacer (after Plan 01):
```typescript
interface FieldPlacerProps {
  // ... existing props ...
  signers?: DocumentSigner[];          // from DocumentPageClient via PdfViewerWrapper
  unassignedFieldIds?: Set<string>;    // from DocumentPageClient for send-block validation
}
```

From schema.ts:
```typescript
export interface DocumentSigner {
  email: string;
  color: string;
}
export interface SignatureFieldData {
  id: string; page: number; x: number; y: number;
  width: number; height: number;
  type?: SignatureFieldType;
  signerEmail?: string;
}
```

FieldPlacer existing color system (lines 70-78):
```typescript
const PALETTE_TOKENS: Array<{ id: SignatureFieldType; label: string; color: string }> = [
  { id: 'client-signature', label: 'Signature',       color: '#2563eb' },
  { id: 'initials',         label: 'Initials',        color: '#7c3aed' },
  { id: 'checkbox',         label: 'Checkbox',        color: '#059669' },
  { id: 'date',             label: 'Date',            color: '#d97706' },
  { id: 'text',             label: 'Text',            color: '#64748b' },
  { id: 'agent-signature',  label: 'Agent Signature', color: '#dc2626' },
  { id: 'agent-initials',   label: 'Agent Initials',  color: '#ea580c' },
];
```

Color Override Rule (D-06, D-07):
- field.signerEmail set AND matching signer in signers[] => use signer.color
- field.signerEmail absent => use PALETTE_TOKENS type color (unchanged)

Validation overlay (D-09/D-10, UI-SPEC section 3):
- unassignedFieldIds contains field.id => border: 2px solid #ef4444, bg: #ef444414
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Add active signer selector and signer-aware field coloring</name>
  <read_first>
    - teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx (FULL FILE — 822 lines)
    - teressa-copeland-homes/src/lib/db/schema.ts (DocumentSigner, SignatureFieldData)
    - .planning/phases/16-multi-signer-ui/16-CONTEXT.md (D-05, D-06, D-07, D-08, D-09, D-10)
    - .planning/phases/16-multi-signer-ui/16-UI-SPEC.md (Component Inventory sections 2 and 3)
  </read_first>
  <files>teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx</files>
  <action>
    **1. Active signer state (inside FieldPlacer function body):**
    ```typescript
    const [activeSignerEmail, setActiveSignerEmail] = useState<string | null>(null);
    ```
    Default to first signer on load and when signers change (per D-08):
    ```typescript
    useEffect(() => {
      if (signers && signers.length > 0) {
        setActiveSignerEmail(prev => {
          // Keep current selection if still valid
          if (prev && signers.some(s => s.email === prev)) return prev;
          return signers[0].email;
        });
      } else {
        setActiveSignerEmail(null);
      }
    }, [signers]);
    ```

    **2. Active signer selector UI** — insert ABOVE the palette div (line ~756), ONLY when `signers && signers.length > 0`:
    ```tsx
    {!readOnly && signers && signers.length > 0 && (
      <div style={{
        display: 'flex',
        alignItems: 'center',
        gap: '8px',
        marginBottom: '8px',
        padding: '8px 12px',
        background: '#f8fafc',
        border: '1px solid #e2e8f0',
        borderRadius: '6px',
      }}>
        <span style={{ fontSize: '12px', color: '#6b7280', fontWeight: 500, whiteSpace: 'nowrap' }}>
          Active signer:
        </span>
        <select
          value={activeSignerEmail ?? ''}
          onChange={(e) => setActiveSignerEmail(e.target.value)}
          style={{
            flex: 1,
            height: '32px',
            border: '1px solid #D1D5DB',
            borderRadius: '0.375rem',
            fontSize: '0.875rem',
            padding: '0 8px',
            background: 'white',
          }}
        >
          {signers.map(s => (
            <option key={s.email} value={s.email}>
              {s.email}
            </option>
          ))}
        </select>
        {/* Color indicator dot next to the dropdown */}
        {(() => {
          const activeSigner = signers.find(s => s.email === activeSignerEmail);
          return activeSigner ? (
            <span style={{
              width: '8px', height: '8px', borderRadius: '50%',
              backgroundColor: activeSigner.color, flexShrink: 0,
            }} />
          ) : null;
        })()}
      </div>
    )}
    ```

    **3. handleDragEnd modification** — at line ~294 where `newField` is created, add `signerEmail`:
    Change the `newField` construction to include:
    ```typescript
    const newField: SignatureFieldData = {
      id: crypto.randomUUID(),
      page: currentPage,
      x: pdfX,
      y: pdfY,
      width: fieldW,
      height: fieldH,
      type: droppedType,
      ...(activeSignerEmail ? { signerEmail: activeSignerEmail } : {}),
    };
    ```
    Add `activeSignerEmail` to the useCallback dependency array of handleDragEnd.

    **4. renderFields color override** — in the renderFields function (around line 581-584), replace the existing color lookup:
    ```typescript
    // Per-type color and label
    const fieldType = getFieldType(field);
    const tokenMeta = PALETTE_TOKENS.find((t) => t.id === fieldType);

    // Color override: signer color when signerEmail is set (D-06), else type color (D-07)
    let fieldColor = tokenMeta?.color ?? '#2563eb';
    if (field.signerEmail && signers) {
      const matchedSigner = signers.find(s => s.email === field.signerEmail);
      if (matchedSigner) {
        fieldColor = matchedSigner.color;
      }
    }

    // Validation overlay: unassigned field highlight (D-09/D-10)
    const isUnassigned = unassignedFieldIds?.has(field.id) ?? false;
    const fieldLabel = tokenMeta?.label ?? 'Signature';
    ```

    **5. Field box style override for validation** — in the field box's `style` object (around line 627-653):
    - Change `border` line to: `border: isUnassigned ? '2px solid #ef4444' : \`2px solid ${fieldColor}\``,
    - Change `background` line to: `background: isUnassigned ? '#ef444414' : (readOnly ? \`${fieldColor}0d\` : \`${fieldColor}1a\`)`,

    **6. DragOverlay ghost color** — in the DragOverlay section (around line 796-798), the ghost should also use signer color if active signer is set. Update:
    ```typescript
    {isDraggingToken ? (() => {
      const tokenMeta = PALETTE_TOKENS.find((t) => t.id === isDraggingToken);
      const label = tokenMeta?.label ?? 'Field';
      // Ghost uses active signer color if one is selected, else type color
      let ghostColor = tokenMeta?.color ?? '#2563eb';
      if (activeSignerEmail && signers) {
        const activeSigner = signers.find(s => s.email === activeSignerEmail);
        if (activeSigner) ghostColor = activeSigner.color;
      }
      const isCheckbox = isDraggingToken === 'checkbox';
      // ... rest uses ghostColor instead of color
    ```
  </action>
  <verify>
    <automated>cd /Users/ccopeland/temp/red/teressa-copeland-homes && npx tsc --noEmit 2>&1 | head -30</automated>
  </verify>
  <acceptance_criteria>
    - `grep -n "Active signer:" teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx` shows dropdown label
    - `grep -n "activeSignerEmail" teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx` shows state variable
    - `grep -n "signerEmail.*activeSignerEmail" teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx` shows field creation sets signerEmail
    - `grep -n "signers.*find.*signerEmail" teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx` shows signer color lookup in renderFields
    - `grep -n "#ef4444" teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx` shows validation overlay border color
    - `grep -n "#ef444414" teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx` shows validation overlay background
    - `grep -n "height.*32px" teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx` shows dropdown is 32px tall
    - `npx tsc --noEmit` passes
  </acceptance_criteria>
  <done>
    - Active signer dropdown appears above palette when signers exist, hidden otherwise per D-05
    - Dropdown defaults to first signer per D-08
    - Dragged fields get signerEmail = active signer's email per D-06
    - Fields with signerEmail render in signer color; fields without use type color per D-06/D-07
    - Fields in unassignedFieldIds set show red #ef4444 outline and #ef444414 background per D-09/D-10
    - TypeScript compiles cleanly
  </done>
</task>

</tasks>

<verification>
- `npx tsc --noEmit` passes
- Active signer selector renders above palette with correct styling
- Field color follows signer color when assigned, type color when not
- Validation overlay visible on unassigned fields
</verification>

<success_criteria>
- Agent can select active signer from dropdown before placing fields
- Fields placed with active signer are tagged and colored accordingly
- Unassigned fields show red validation highlight when send-block triggers
- Existing behavior unchanged when no signers configured
- TypeScript compiles with no errors
</success_criteria>

<output>
After completion, create `.planning/phases/16-multi-signer-ui/16-03-SUMMARY.md`
</output>
