feat(20-02): add template hint quick-fill chip to PreparePanel

- DocumentPageClient fetches /api/documents/:docId/fields on mount and aiPlacementKey change
- Derives selectedFieldHint from selected field's hint property
- Passes selectedFieldHint prop to PreparePanel
- PreparePanel renders Template Hint chip in Quick Fill section when hint exists
This commit is contained in:
Chandler Copeland
2026-04-06 14:54:09 -06:00
parent 78d579f965
commit eec0bd91c9
2 changed files with 27 additions and 1 deletions

View File

@@ -2,7 +2,7 @@
import { useState, useCallback, useEffect } from 'react';
import { PdfViewerWrapper } from './PdfViewerWrapper';
import { PreparePanel } from './PreparePanel';
import type { DocumentSigner } from '@/lib/db/schema';
import type { DocumentSigner, SignatureFieldData } from '@/lib/db/schema';
interface DocumentPageClientProps {
docId: string;
@@ -34,6 +34,7 @@ export function DocumentPageClient({
const [selectedFieldId, setSelectedFieldId] = useState<string | null>(null);
const [textFillData, setTextFillData] = useState<Record<string, string>>({});
const [aiPlacementKey, setAiPlacementKey] = useState(0);
const [fields, setFields] = useState<SignatureFieldData[]>([]);
// Auto-seed signers from client contacts when no signers have been configured yet
const defaultSigners: DocumentSigner[] = initialSigners.length > 0
@@ -45,6 +46,14 @@ export function DocumentPageClient({
const [signers, setSigners] = useState<DocumentSigner[]>(defaultSigners);
const [unassignedFieldIds, setUnassignedFieldIds] = useState<Set<string>>(new Set());
// Fetch fields so we can derive hint for the selected field
useEffect(() => {
fetch(`/api/documents/${docId}/fields`)
.then(r => r.json())
.then((data: SignatureFieldData[]) => setFields(Array.isArray(data) ? data : []))
.catch(() => {});
}, [docId, aiPlacementKey]);
// Persist auto-seeded signers to DB so they survive refresh
useEffect(() => {
if (initialSigners.length === 0 && defaultSigners.length > 0) {
@@ -89,6 +98,10 @@ export function DocumentPageClient({
setPreviewToken(null);
}, [docId]);
const selectedFieldHint = selectedFieldId
? fields.find(f => f.id === selectedFieldId)?.hint
: undefined;
return (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2">
@@ -119,6 +132,7 @@ export function DocumentPageClient({
textFillData={textFillData}
selectedFieldId={selectedFieldId}
onQuickFill={handleQuickFill}
selectedFieldHint={selectedFieldHint}
onAiAutoPlace={handleAiAutoPlace}
signers={signers}
onSignersChange={setSigners}

View File

@@ -95,6 +95,7 @@ interface PreparePanelProps {
textFillData: Record<string, string>;
selectedFieldId: string | null;
onQuickFill: (fieldId: string, value: string) => void;
selectedFieldHint?: string;
onAiAutoPlace: () => Promise<void>;
// Multi-signer props — wired in Phase 16 Plan 01, consumed here in Plan 02
signers?: DocumentSigner[];
@@ -112,6 +113,7 @@ export function PreparePanel({
agentDownloadUrl, signedAt, clientPropertyAddress,
previewToken, onPreviewTokenChange,
textFillData, selectedFieldId, onQuickFill,
selectedFieldHint,
onAiAutoPlace,
signers = [],
onSignersChange,
@@ -346,6 +348,16 @@ export function PreparePanel({
<span className="text-xs text-gray-400 block">Client Email</span>
<span className="truncate block">{defaultEmail}</span>
</button>
{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>
)}
</div>
) : (
<p className="text-sm text-gray-400 italic">