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:
@@ -2,7 +2,7 @@
|
|||||||
import { useState, useCallback, useEffect } from 'react';
|
import { useState, useCallback, useEffect } from 'react';
|
||||||
import { PdfViewerWrapper } from './PdfViewerWrapper';
|
import { PdfViewerWrapper } from './PdfViewerWrapper';
|
||||||
import { PreparePanel } from './PreparePanel';
|
import { PreparePanel } from './PreparePanel';
|
||||||
import type { DocumentSigner } from '@/lib/db/schema';
|
import type { DocumentSigner, SignatureFieldData } from '@/lib/db/schema';
|
||||||
|
|
||||||
interface DocumentPageClientProps {
|
interface DocumentPageClientProps {
|
||||||
docId: string;
|
docId: string;
|
||||||
@@ -34,6 +34,7 @@ export function DocumentPageClient({
|
|||||||
const [selectedFieldId, setSelectedFieldId] = useState<string | null>(null);
|
const [selectedFieldId, setSelectedFieldId] = useState<string | null>(null);
|
||||||
const [textFillData, setTextFillData] = useState<Record<string, string>>({});
|
const [textFillData, setTextFillData] = useState<Record<string, string>>({});
|
||||||
const [aiPlacementKey, setAiPlacementKey] = useState(0);
|
const [aiPlacementKey, setAiPlacementKey] = useState(0);
|
||||||
|
const [fields, setFields] = useState<SignatureFieldData[]>([]);
|
||||||
|
|
||||||
// Auto-seed signers from client contacts when no signers have been configured yet
|
// Auto-seed signers from client contacts when no signers have been configured yet
|
||||||
const defaultSigners: DocumentSigner[] = initialSigners.length > 0
|
const defaultSigners: DocumentSigner[] = initialSigners.length > 0
|
||||||
@@ -45,6 +46,14 @@ export function DocumentPageClient({
|
|||||||
const [signers, setSigners] = useState<DocumentSigner[]>(defaultSigners);
|
const [signers, setSigners] = useState<DocumentSigner[]>(defaultSigners);
|
||||||
const [unassignedFieldIds, setUnassignedFieldIds] = useState<Set<string>>(new Set());
|
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
|
// Persist auto-seeded signers to DB so they survive refresh
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (initialSigners.length === 0 && defaultSigners.length > 0) {
|
if (initialSigners.length === 0 && defaultSigners.length > 0) {
|
||||||
@@ -89,6 +98,10 @@ export function DocumentPageClient({
|
|||||||
setPreviewToken(null);
|
setPreviewToken(null);
|
||||||
}, [docId]);
|
}, [docId]);
|
||||||
|
|
||||||
|
const selectedFieldHint = selectedFieldId
|
||||||
|
? fields.find(f => f.id === selectedFieldId)?.hint
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||||
<div className="lg:col-span-2">
|
<div className="lg:col-span-2">
|
||||||
@@ -119,6 +132,7 @@ export function DocumentPageClient({
|
|||||||
textFillData={textFillData}
|
textFillData={textFillData}
|
||||||
selectedFieldId={selectedFieldId}
|
selectedFieldId={selectedFieldId}
|
||||||
onQuickFill={handleQuickFill}
|
onQuickFill={handleQuickFill}
|
||||||
|
selectedFieldHint={selectedFieldHint}
|
||||||
onAiAutoPlace={handleAiAutoPlace}
|
onAiAutoPlace={handleAiAutoPlace}
|
||||||
signers={signers}
|
signers={signers}
|
||||||
onSignersChange={setSigners}
|
onSignersChange={setSigners}
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ interface PreparePanelProps {
|
|||||||
textFillData: Record<string, string>;
|
textFillData: Record<string, string>;
|
||||||
selectedFieldId: string | null;
|
selectedFieldId: string | null;
|
||||||
onQuickFill: (fieldId: string, value: string) => void;
|
onQuickFill: (fieldId: string, value: string) => void;
|
||||||
|
selectedFieldHint?: string;
|
||||||
onAiAutoPlace: () => Promise<void>;
|
onAiAutoPlace: () => Promise<void>;
|
||||||
// Multi-signer props — wired in Phase 16 Plan 01, consumed here in Plan 02
|
// Multi-signer props — wired in Phase 16 Plan 01, consumed here in Plan 02
|
||||||
signers?: DocumentSigner[];
|
signers?: DocumentSigner[];
|
||||||
@@ -112,6 +113,7 @@ export function PreparePanel({
|
|||||||
agentDownloadUrl, signedAt, clientPropertyAddress,
|
agentDownloadUrl, signedAt, clientPropertyAddress,
|
||||||
previewToken, onPreviewTokenChange,
|
previewToken, onPreviewTokenChange,
|
||||||
textFillData, selectedFieldId, onQuickFill,
|
textFillData, selectedFieldId, onQuickFill,
|
||||||
|
selectedFieldHint,
|
||||||
onAiAutoPlace,
|
onAiAutoPlace,
|
||||||
signers = [],
|
signers = [],
|
||||||
onSignersChange,
|
onSignersChange,
|
||||||
@@ -346,6 +348,16 @@ export function PreparePanel({
|
|||||||
<span className="text-xs text-gray-400 block">Client Email</span>
|
<span className="text-xs text-gray-400 block">Client Email</span>
|
||||||
<span className="truncate block">{defaultEmail}</span>
|
<span className="truncate block">{defaultEmail}</span>
|
||||||
</button>
|
</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>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className="text-sm text-gray-400 italic">
|
<p className="text-sm text-gray-400 italic">
|
||||||
|
|||||||
Reference in New Issue
Block a user