feat(16-01): thread signers state through DocumentPageClient

- Server page passes doc.signers as initialSigners to DocumentPageClient
- DocumentPageClient adds signers + unassignedFieldIds state (initialized from server)
- Props threaded to PdfViewerWrapper (signers, unassignedFieldIds) and PreparePanel (signers, onSignersChange, unassignedFieldIds, onUnassignedFieldIdsChange)
- PreparePanel interface extended to accept new optional multi-signer props

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chandler Copeland
2026-04-03 16:21:13 -06:00
parent 0ca698925f
commit ac1f1d6cec
3 changed files with 18 additions and 0 deletions

View File

@@ -2,6 +2,7 @@
import { useState, useCallback } from 'react'; import { useState, useCallback } 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';
interface DocumentPageClientProps { interface DocumentPageClientProps {
docId: string; docId: string;
@@ -11,6 +12,7 @@ interface DocumentPageClientProps {
agentDownloadUrl?: string | null; agentDownloadUrl?: string | null;
signedAt?: Date | null; signedAt?: Date | null;
clientPropertyAddress?: string | null; clientPropertyAddress?: string | null;
initialSigners: DocumentSigner[];
} }
export function DocumentPageClient({ export function DocumentPageClient({
@@ -21,11 +23,14 @@ export function DocumentPageClient({
agentDownloadUrl, agentDownloadUrl,
signedAt, signedAt,
clientPropertyAddress, clientPropertyAddress,
initialSigners,
}: DocumentPageClientProps) { }: DocumentPageClientProps) {
const [previewToken, setPreviewToken] = useState<string | null>(null); const [previewToken, setPreviewToken] = useState<string | null>(null);
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 [signers, setSigners] = useState<DocumentSigner[]>(initialSigners);
const [unassignedFieldIds, setUnassignedFieldIds] = useState<Set<string>>(new Set());
const handleFieldsChanged = useCallback(() => { const handleFieldsChanged = useCallback(() => {
setPreviewToken(null); setPreviewToken(null);
@@ -71,6 +76,8 @@ export function DocumentPageClient({
onFieldSelect={setSelectedFieldId} onFieldSelect={setSelectedFieldId}
onFieldValueChange={handleFieldValueChange} onFieldValueChange={handleFieldValueChange}
aiPlacementKey={aiPlacementKey} aiPlacementKey={aiPlacementKey}
signers={signers}
unassignedFieldIds={unassignedFieldIds}
/> />
</div> </div>
<div className="lg:col-span-1 lg:sticky lg:top-6 lg:self-start lg:max-h-[calc(100vh-6rem)] lg:overflow-y-auto"> <div className="lg:col-span-1 lg:sticky lg:top-6 lg:self-start lg:max-h-[calc(100vh-6rem)] lg:overflow-y-auto">
@@ -88,6 +95,10 @@ export function DocumentPageClient({
selectedFieldId={selectedFieldId} selectedFieldId={selectedFieldId}
onQuickFill={handleQuickFill} onQuickFill={handleQuickFill}
onAiAutoPlace={handleAiAutoPlace} onAiAutoPlace={handleAiAutoPlace}
signers={signers}
onSignersChange={setSigners}
unassignedFieldIds={unassignedFieldIds}
onUnassignedFieldIdsChange={setUnassignedFieldIds}
/> />
</div> </div>
</div> </div>

View File

@@ -2,6 +2,7 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import type { DocumentSigner } from '@/lib/db/schema';
// PreviewModal imports react-pdf which calls new DOMMatrix() at module level — // PreviewModal imports react-pdf which calls new DOMMatrix() at module level —
// must be loaded client-only to avoid SSR crash, same pattern as PdfViewer. // must be loaded client-only to avoid SSR crash, same pattern as PdfViewer.
@@ -21,6 +22,11 @@ interface PreparePanelProps {
selectedFieldId: string | null; selectedFieldId: string | null;
onQuickFill: (fieldId: string, value: string) => void; onQuickFill: (fieldId: string, value: string) => void;
onAiAutoPlace: () => Promise<void>; onAiAutoPlace: () => Promise<void>;
// Multi-signer props — wired in Phase 16, consumed in Wave 2
signers?: DocumentSigner[];
onSignersChange?: (signers: DocumentSigner[]) => void;
unassignedFieldIds?: Set<string>;
onUnassignedFieldIdsChange?: (ids: Set<string>) => void;
} }
function parseEmails(raw: string | undefined): string[] { function parseEmails(raw: string | undefined): string[] {

View File

@@ -60,6 +60,7 @@ export default async function DocumentPage({
agentDownloadUrl={agentDownloadUrl} agentDownloadUrl={agentDownloadUrl}
signedAt={doc.signedAt ?? null} signedAt={doc.signedAt ?? null}
clientPropertyAddress={docClient?.propertyAddress ?? null} clientPropertyAddress={docClient?.propertyAddress ?? null}
initialSigners={doc.signers ?? []}
/> />
</div> </div>
); );