---
phase: 10-expanded-field-types-end-to-end
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx
autonomous: true
requirements:
  - FIELD-02
  - FIELD-03
  - FIELD-04

must_haves:
  truths:
    - "Agent can drag a Checkbox token from the palette and drop it onto any PDF page"
    - "Agent can drag an Initials token from the palette and drop it onto any PDF page"
    - "Agent can drag a Date token from the palette and drop it onto any PDF page"
    - "Agent can drag a Text token from the palette and drop it onto any PDF page"
    - "Placed fields show distinct labels and colors per type (not all 'Signature')"
    - "The drag ghost overlay shows the correct label while dragging each token type"
    - "Dropped fields persist with the correct type property in the database"
    - "Checkbox fields drop at 24x24px; all other new types drop at 144x36px"
  artifacts:
    - path: "teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx"
      provides: "5-token typed palette (Signature, Initials, Checkbox, Date, Text) with per-type colors and DragOverlay"
      contains: "DraggableToken.*id.*label.*color"
  key_links:
    - from: "DraggableToken id prop"
      to: "SignatureFieldData.type"
      via: "handleDragEnd dispatches active.id as field type"
      pattern: "active\\.id.*SignatureFieldType"
    - from: "handleDragEnd"
      to: "persistFields"
      via: "newField.type set from active.id before append"
      pattern: "type.*droppedType"
---

<objective>
Extend the FieldPlacer palette from a single generic "Signature" token to five typed tokens: Signature (client-signature), Initials, Checkbox, Date, and Text. Each token has a distinct color and label. Dropped fields write the correct `type` property to `SignatureFieldData`. Field overlays and the drag ghost display the field type rather than a generic "Signature" label.

Purpose: Agent must be able to place the correct field marker type for each intent before the prepare pipeline can distinguish how to render each field. This is the palette-side prerequisite for Plans 02 and 03.
Output: Updated `FieldPlacer.tsx` with 5 typed draggable tokens, per-type overlay colors/labels, type-aware DragOverlay ghost, and checkbox-appropriate drop dimensions.
</objective>

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

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/10-expanded-field-types-end-to-end/10-RESEARCH.md

<interfaces>
<!-- Key types used by FieldPlacer. Executor must use these directly. -->

From teressa-copeland-homes/src/lib/db/schema.ts:
```typescript
export type SignatureFieldType =
  | 'client-signature'
  | 'initials'
  | 'text'
  | 'checkbox'
  | 'date'
  | 'agent-signature';

export interface SignatureFieldData {
  id: string;
  page: number;   // 1-indexed
  x: number;      // PDF user space, bottom-left origin, points
  y: number;      // PDF user space, bottom-left origin, points
  width: number;  // PDF points (default: 144)
  height: number; // PDF points (default: 36)
  type?: SignatureFieldType;  // Optional — v1.0 docs have no type; fallback = 'client-signature'
}
```

From existing FieldPlacer.tsx (current state — to be modified):
- Single `DraggableToken` with hardcoded id `'signature-token'`, blue dashed border, "+ Signature Field" text
- `handleDragEnd` creates `newField` without setting `type` property (falls back to client-signature via getFieldType)
- `renderFields` shows generic "Signature" span for all placed fields
- `DragOverlay` renders static "Signature" label regardless of which token is being dragged
- `isDraggingToken` boolean tracks whether palette drag is active (not which token)
- Palette div: `<DraggableToken id="signature-token" />`
- newField dimensions hardcoded: width 144, height 36
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Parameterize DraggableToken and add four new palette tokens</name>
  <files>teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx</files>
  <action>
Modify `DraggableToken` to accept `id`, `label`, and `color` props (replacing the hardcoded blue dashed border style). The color prop drives the border color, background tint, and text color of the token.

Add import for `getFieldType` and `SignatureFieldType` from `@/lib/db/schema`:
```typescript
import { getFieldType, type SignatureFieldType } from '@/lib/db/schema';
```

Replace the hardcoded DraggableToken with a parameterized version:
```typescript
function DraggableToken({ id, label, color }: { id: string; label: string; color: string }) {
  const { attributes, listeners, setNodeRef, isDragging } = useDraggable({ id });
  const style: React.CSSProperties = {
    opacity: isDragging ? 0.4 : 1,
    cursor: 'grab',
    padding: '6px 12px',
    border: `2px dashed ${color}`,
    borderRadius: '4px',
    background: `${color}14`,  // ~8% opacity tint
    color,
    fontSize: '13px',
    fontWeight: 600,
    userSelect: 'none',
    touchAction: 'none',
  };
  return (
    <div ref={setNodeRef} style={style} {...listeners} {...attributes}>
      + {label}
    </div>
  );
}
```

Update the palette section to render five tokens with distinct colors:
```typescript
// Token color palette — each maps to a SignatureFieldType
const PALETTE_TOKENS: Array<{ id: SignatureFieldType; label: string; color: string }> = [
  { id: 'client-signature', label: 'Signature',  color: '#2563eb' },  // blue
  { id: 'initials',         label: 'Initials',   color: '#7c3aed' },  // purple
  { id: 'checkbox',         label: 'Checkbox',   color: '#059669' },  // green
  { id: 'date',             label: 'Date',       color: '#d97706' },  // amber
  { id: 'text',             label: 'Text',       color: '#64748b' },  // slate
];
```

In the palette JSX, replace the single `<DraggableToken id="signature-token" />` with:
```tsx
{PALETTE_TOKENS.map((token) => (
  <DraggableToken key={token.id} id={token.id} label={token.label} color={token.color} />
))}
```

The DragOverlay currently shows a static "Signature" label. Track the active dragging token's id and label. Change `isDraggingToken` from `boolean` to `string | null` (the active token id, or null when not dragging). Update all three usages:
- `onDragStart`: `setIsDraggingToken(event.active.id as string)`
- `onDragEnd`: `setIsDraggingToken(null)` (currently `false`)
- `DragOverlay`: replace the static "Signature" text with a lookup from PALETTE_TOKENS using the active id

Update the DragOverlay to show the correct ghost label and color:
```tsx
<DragOverlay dropAnimation={null}>
  {isDraggingToken ? (() => {
    const tokenMeta = PALETTE_TOKENS.find((t) => t.id === isDraggingToken);
    const label = tokenMeta?.label ?? 'Field';
    const color = tokenMeta?.color ?? '#2563eb';
    const isCheckbox = isDraggingToken === 'checkbox';
    return (
      <div style={{
        width: isCheckbox ? 24 : 144,
        height: isCheckbox ? 24 : 36,
        border: `2px solid ${color}`,
        background: `${color}26`,
        borderRadius: '2px',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        fontSize: '11px',
        color,
        fontWeight: 600,
        pointerEvents: 'none',
      }}>
        {!isCheckbox && label}
      </div>
    );
  })() : null}
</DragOverlay>
```

Note: `isDraggingToken` type changes from `boolean` to `string | null`. Update `useState<boolean>(false)` to `useState<string | null>(null)`. The condition check `isDraggingToken ? ...` still works correctly since any non-null string is truthy.
  </action>
  <verify>TypeScript compiles without errors: `cd /Users/ccopeland/temp/red/teressa-copeland-homes && npx tsc --noEmit 2>&1 | head -30`</verify>
  <done>Five typed tokens visible in palette with distinct colors; TypeScript compiles clean</done>
</task>

<task type="auto">
  <name>Task 2: Update handleDragEnd and renderFields for typed field creation</name>
  <files>teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/FieldPlacer.tsx</files>
  <action>
Update `handleDragEnd` to write the correct `type` property and use type-appropriate dimensions for checkbox fields.

Replace the `newField` construction block (currently creates a field with no `type`) with:
```typescript
// Determine the field type from the dnd-kit active.id (token id IS the SignatureFieldType)
const validTypes = new Set<string>(['client-signature', 'initials', 'text', 'checkbox', 'date', 'agent-signature']);
const droppedType: SignatureFieldType = validTypes.has(active.id as string)
  ? (active.id as SignatureFieldType)
  : 'client-signature';

// Checkbox fields are square (24x24pt). All other types: 144x36pt.
const isCheckbox = droppedType === 'checkbox';
const fieldW = isCheckbox ? 24 : 144;
const fieldH = isCheckbox ? 24 : 36;

// Update clamping to use fieldW/fieldH instead of hardcoded 144/36
const fieldWpx = (fieldW / pageInfo.originalWidth) * renderedW;
const fieldHpx = (fieldH / pageInfo.originalHeight) * renderedH;
```

Note: the existing code calculates `fieldWpx` and `fieldHpx` from hardcoded 144/36 — replace those hardcoded values with `fieldW`/`fieldH` from above.

The `newField` object becomes:
```typescript
const newField: SignatureFieldData = {
  id: crypto.randomUUID(),
  page: currentPage,
  x: pdfX,
  y: pdfY,
  width: fieldW,
  height: fieldH,
  type: droppedType,
};
```

Update `renderFields` to display per-type labels and border colors. Replace the hardcoded `<span style={{ pointerEvents: 'none' }}>Signature</span>` with a lookup that shows the field type label and uses the matching color:

```typescript
// Inside renderFields, for each field:
const fieldType = getFieldType(field);
const tokenMeta = PALETTE_TOKENS.find((t) => t.id === fieldType);
const fieldColor = tokenMeta?.color ?? '#2563eb';
const fieldLabel = tokenMeta?.label ?? 'Signature';
```

Update the placed field div to use `fieldColor` for border and background (replacing the hardcoded `#2563eb` values), and render `{fieldLabel}` instead of `"Signature"` in the span. Keep all existing move/resize/delete behavior unchanged — only the visual colors and label text change.

For the checkbox type specifically, the placed overlay will naturally be small (24x24px in PDF units, scaled to screen) — no special rendering needed beyond the color/label update.
  </action>
  <verify>TypeScript compiles without errors: `cd /Users/ccopeland/temp/red/teressa-copeland-homes && npx tsc --noEmit 2>&1 | head -30`</verify>
  <done>Dropping a Checkbox token creates a 24x24pt field with `type: 'checkbox'`; dropping Initials creates 144x36pt with `type: 'initials'`; dropping Date creates 144x36pt with `type: 'date'`; all placed field overlays show the correct label and color; TypeScript compiles clean</done>
</task>

</tasks>

<verification>
Run TypeScript check: `cd /Users/ccopeland/temp/red/teressa-copeland-homes && npx tsc --noEmit`

Verify field type persistence in browser:
1. Open `npm run dev` and navigate to any document in the portal
2. The palette should show five tokens: Signature (blue), Initials (purple), Checkbox (green), Date (amber), Text (slate)
3. Drag a Checkbox token — ghost should be 24x24px square with green border, no text label
4. Drag an Initials token — ghost should be 144x36px with "Initials" label in purple
5. Drop each token type onto the PDF — each placed overlay should show the correct label and color
6. Refresh the page — fields should reload with their correct types (persisted via PUT /api/documents/[docId]/fields)
</verification>

<success_criteria>
- Palette renders five distinct typed tokens with matching colors
- `handleDragEnd` sets `newField.type` from `active.id` for all five types
- Checkbox drops at 24x24pt; all others drop at 144x36pt
- `renderFields` shows the correct label and border color per field type
- `DragOverlay` shows the correct ghost label and dimensions while dragging
- TypeScript compiles without errors
- Fields persist with `type` property after page reload
</success_criteria>

<output>
After completion, create `.planning/phases/10-expanded-field-types-end-to-end/10-01-SUMMARY.md` following the summary template.
</output>
