259 lines
11 KiB
Markdown
259 lines
11 KiB
Markdown
---
|
|
phase: 20-apply-template-and-portal-nav
|
|
plan: 02
|
|
type: execute
|
|
wave: 2
|
|
depends_on: [20-01]
|
|
files_modified:
|
|
- teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/DocumentPageClient.tsx
|
|
- teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/PreparePanel.tsx
|
|
autonomous: false
|
|
requirements: [TMPL-13, TMPL-15, TMPL-16]
|
|
|
|
must_haves:
|
|
truths:
|
|
- "When agent selects a text field that has a hint (from template), a 'Template Hint' chip appears in the Quick Fill section of PreparePanel"
|
|
- "Clicking the hint chip fills the selected field with the hint text (same behavior as existing quick-fill)"
|
|
- "Fields without hints show no extra chip — existing quick-fill behavior unchanged"
|
|
- "Templates nav link exists in portal navigation (Phase 19, already done)"
|
|
- "Templates list page shows all templates with form name, field count, last-updated (Phase 19, already done)"
|
|
artifacts:
|
|
- path: "teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/DocumentPageClient.tsx"
|
|
provides: "Fields state fetch + selectedFieldHint derivation"
|
|
contains: "selectedFieldHint"
|
|
- path: "teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/PreparePanel.tsx"
|
|
provides: "Template Hint chip in Quick Fill section"
|
|
contains: "selectedFieldHint"
|
|
key_links:
|
|
- from: "DocumentPageClient.tsx"
|
|
to: "GET /api/documents/:docId/fields"
|
|
via: "fetch on mount + aiPlacementKey change"
|
|
pattern: "api/documents.*fields"
|
|
- from: "DocumentPageClient.tsx"
|
|
to: "PreparePanel"
|
|
via: "selectedFieldHint prop"
|
|
pattern: "selectedFieldHint="
|
|
- from: "PreparePanel.tsx"
|
|
to: "onQuickFill callback"
|
|
via: "hint chip onClick"
|
|
pattern: "Template Hint"
|
|
---
|
|
|
|
<objective>
|
|
Surface template text hints as quick-fill suggestions in PreparePanel and verify the complete Phase 20 feature set with human testing.
|
|
|
|
Purpose: When a document is created from a template, text fields with hints (e.g., "Property Address", "Purchase Price") show those hints as one-click quick-fill chips, saving the agent from remembering what each blank field is for.
|
|
Output: Modified DocumentPageClient.tsx (fields state + hint derivation), modified PreparePanel.tsx (hint chip), human verification of the full template-to-document flow.
|
|
</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/STATE.md
|
|
@.planning/phases/20-apply-template-and-portal-nav/20-CONTEXT.md
|
|
@.planning/phases/20-apply-template-and-portal-nav/20-RESEARCH.md
|
|
@.planning/phases/20-apply-template-and-portal-nav/20-01-SUMMARY.md
|
|
|
|
<interfaces>
|
|
<!-- Key types and contracts from codebase. -->
|
|
|
|
From src/app/portal/(protected)/documents/[docId]/_components/DocumentPageClient.tsx:
|
|
```typescript
|
|
interface DocumentPageClientProps {
|
|
docId: string;
|
|
docStatus: string;
|
|
defaultEmail: string;
|
|
clientName: string;
|
|
agentDownloadUrl?: string | null;
|
|
signedAt?: Date | null;
|
|
clientPropertyAddress?: string | null;
|
|
initialSigners: DocumentSigner[];
|
|
clientContacts?: { name: string; email: string }[];
|
|
}
|
|
|
|
// Existing state:
|
|
// selectedFieldId: string | null
|
|
// textFillData: Record<string, string>
|
|
// aiPlacementKey: number
|
|
// signers: DocumentSigner[]
|
|
```
|
|
|
|
From src/app/portal/(protected)/documents/[docId]/_components/PreparePanel.tsx:
|
|
```typescript
|
|
interface PreparePanelProps {
|
|
docId: string;
|
|
defaultEmail: string;
|
|
clientName: string;
|
|
currentStatus: string;
|
|
agentDownloadUrl?: string | null;
|
|
signedAt?: Date | null;
|
|
clientPropertyAddress?: string | null;
|
|
previewToken: string | null;
|
|
onPreviewTokenChange: (token: string | null) => void;
|
|
textFillData: Record<string, string>;
|
|
selectedFieldId: string | null;
|
|
onQuickFill: (fieldId: string, value: string) => void;
|
|
onAiAutoPlace: () => Promise<void>;
|
|
signers?: DocumentSigner[];
|
|
onSignersChange?: (signers: DocumentSigner[]) => void;
|
|
unassignedFieldIds?: Set<string>;
|
|
onUnassignedFieldIdsChange?: (ids: Set<string>) => void;
|
|
}
|
|
```
|
|
|
|
Quick Fill section pattern (PreparePanel lines 313-355):
|
|
```typescript
|
|
{/* Quick-fill panel — only shown when a text field is selected */}
|
|
{selectedFieldId ? (
|
|
<div className="space-y-1.5">
|
|
<p className="text-xs text-gray-400">Click a suggestion to fill the selected field.</p>
|
|
{clientName && ( <button onClick={() => onQuickFill(selectedFieldId, clientName)}>...</button> )}
|
|
{clientPropertyAddress && ( <button onClick={() => onQuickFill(selectedFieldId, clientPropertyAddress)}>...</button> )}
|
|
<button onClick={() => onQuickFill(selectedFieldId, defaultEmail)}>Client Email chip</button>
|
|
</div>
|
|
) : (
|
|
<p>Click a text field on the document...</p>
|
|
)}
|
|
```
|
|
</interfaces>
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Add fields state to DocumentPageClient and pass selectedFieldHint to PreparePanel</name>
|
|
<files>
|
|
teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/DocumentPageClient.tsx
|
|
teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/PreparePanel.tsx
|
|
</files>
|
|
<read_first>
|
|
teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/DocumentPageClient.tsx
|
|
teressa-copeland-homes/src/app/portal/(protected)/documents/[docId]/_components/PreparePanel.tsx
|
|
teressa-copeland-homes/src/lib/db/schema.ts
|
|
</read_first>
|
|
<action>
|
|
**In DocumentPageClient.tsx:**
|
|
|
|
1. Add import: `import type { SignatureFieldData } from '@/lib/db/schema';` (DocumentSigner is already imported).
|
|
|
|
2. Add state for fields:
|
|
```typescript
|
|
const [fields, setFields] = useState<SignatureFieldData[]>([]);
|
|
```
|
|
|
|
3. Add useEffect to fetch fields on mount and when aiPlacementKey changes:
|
|
```typescript
|
|
useEffect(() => {
|
|
fetch(`/api/documents/${docId}/fields`)
|
|
.then(r => r.json())
|
|
.then((data: SignatureFieldData[]) => setFields(Array.isArray(data) ? data : []))
|
|
.catch(() => {});
|
|
}, [docId, aiPlacementKey]);
|
|
```
|
|
|
|
4. Derive the hint for the selected field:
|
|
```typescript
|
|
const selectedFieldHint = selectedFieldId
|
|
? fields.find(f => f.id === selectedFieldId)?.hint
|
|
: undefined;
|
|
```
|
|
|
|
5. Pass new prop to PreparePanel:
|
|
```typescript
|
|
<PreparePanel
|
|
// ... all existing props unchanged ...
|
|
selectedFieldHint={selectedFieldHint}
|
|
/>
|
|
```
|
|
|
|
**In PreparePanel.tsx:**
|
|
|
|
1. Add `selectedFieldHint?: string;` to the `PreparePanelProps` interface (after `onQuickFill`).
|
|
|
|
2. Destructure it in the function signature: add `selectedFieldHint,` to the destructured props.
|
|
|
|
3. In the Quick Fill section (inside the `{selectedFieldId ? (` branch), add a new chip AFTER the existing Client Email chip button (before the closing `</div>` of `space-y-1.5`):
|
|
|
|
```tsx
|
|
{selectedFieldHint && (
|
|
<button
|
|
type="button"
|
|
onClick={() => onQuickFill(selectedFieldId, selectedFieldHint)}
|
|
className="w-full text-left px-3 py-2 text-sm border rounded bg-white hover:bg-blue-50 hover:border-blue-300 transition-colors"
|
|
>
|
|
<span className="text-xs text-gray-400 block">Template Hint</span>
|
|
<span className="truncate block">{selectedFieldHint}</span>
|
|
</button>
|
|
)}
|
|
```
|
|
|
|
This follows the exact same markup pattern as the existing Client Name / Property Address / Client Email chips. The prop is optional with no default — existing callers (DocumentPageClient without template-sourced documents) simply don't pass it, and `undefined` means no chip renders.
|
|
</action>
|
|
<verify>
|
|
<automated>cd teressa-copeland-homes && npx tsc --noEmit</automated>
|
|
</verify>
|
|
<acceptance_criteria>
|
|
- grep "selectedFieldHint" src/app/portal/\(protected\)/documents/\[docId\]/_components/DocumentPageClient.tsx returns at least 2 matches (derivation + prop pass)
|
|
- grep "selectedFieldHint" src/app/portal/\(protected\)/documents/\[docId\]/_components/PreparePanel.tsx returns at least 3 matches (interface + destructure + render)
|
|
- grep "Template Hint" src/app/portal/\(protected\)/documents/\[docId\]/_components/PreparePanel.tsx returns 1 match
|
|
- grep "api/documents.*fields" src/app/portal/\(protected\)/documents/\[docId\]/_components/DocumentPageClient.tsx returns at least 1 match
|
|
- grep "SignatureFieldData" src/app/portal/\(protected\)/documents/\[docId\]/_components/DocumentPageClient.tsx returns at least 1 match (import)
|
|
- npx tsc --noEmit exits 0
|
|
</acceptance_criteria>
|
|
<done>DocumentPageClient fetches fields on mount, derives selectedFieldHint from selected field, passes it to PreparePanel. PreparePanel renders a "Template Hint" quick-fill chip when the hint exists.</done>
|
|
</task>
|
|
|
|
<task type="checkpoint:human-verify" gate="blocking">
|
|
<name>Task 2: Human verification of full template-to-document flow</name>
|
|
<what-built>
|
|
Complete "Start from template" feature:
|
|
- My Templates tab in Add Document modal (Plan 01)
|
|
- Template apply with fresh field UUIDs and role mapping (Plan 01)
|
|
- Text hint quick-fill chips in PreparePanel (Plan 02 Task 1)
|
|
- Templates nav + list page (Phase 19, already live)
|
|
</what-built>
|
|
<how-to-verify>
|
|
Prerequisites: At least one saved template with fields and text hints must exist (created in Phase 19 testing).
|
|
|
|
1. Navigate to /portal/templates — verify the list page shows saved templates with form name, field count, and updated date (TMPL-16)
|
|
2. Verify "Templates" appears in the portal top nav (TMPL-15)
|
|
3. Go to a client profile page → click "Add Document"
|
|
4. Verify the modal shows two tabs: "Forms Library" and "My Templates" (TMPL-10)
|
|
5. Click "My Templates" tab → verify saved templates appear with name, form name, and field count
|
|
6. Select a template → verify the document name auto-fills with the template name
|
|
7. Click "Add Document" → verify the document is created and you're returned to the client page
|
|
8. Open the newly created document → verify fields are pre-loaded at the correct positions on the PDF (TMPL-11)
|
|
9. In PreparePanel, click a text field that has a hint → verify a "Template Hint" chip appears in the Quick Fill section alongside Client Name/Address/Email (TMPL-13)
|
|
10. Click the hint chip → verify the field is filled with the hint text
|
|
11. Click the "Forms Library" tab back in a new Add Document modal → verify the existing form library still works exactly as before (D-04)
|
|
12. (TMPL-14 — snapshot independence): Go to /portal/templates → edit the template (change a field position) → go back to the document created in step 7 → verify the document's fields are unchanged (still at original positions)
|
|
</how-to-verify>
|
|
<resume-signal>Type "approved" or describe any issues found</resume-signal>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
1. `cd teressa-copeland-homes && npx tsc --noEmit` — zero type errors
|
|
2. `cd teressa-copeland-homes && npm run build` — production build succeeds
|
|
3. Human verification confirms all 12 steps pass
|
|
4. TMPL-10 through TMPL-16 all satisfied (TMPL-14/15/16 by design or Phase 19)
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- Template Hint chip appears in Quick Fill when a text field with a hint is selected
|
|
- Chip click fills the field (same behavior as existing quick-fill chips)
|
|
- Fields without hints show no extra chip
|
|
- Human confirms full template-to-document flow works end-to-end
|
|
- All 7 TMPL requirements (TMPL-10 through TMPL-16) are satisfied
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/20-apply-template-and-portal-nav/20-02-SUMMARY.md`
|
|
</output>
|