feat(08-02): add type-branching guards to SigningPageClient

- Import getFieldType from @/lib/db/schema
- handleFieldClick returns early for non-client-signature fields (defense-in-depth)
- handleSubmit counts only client-signature fields for completeness check
- SigningProgressBar total reflects client-signature count only
- signatureFields added to handleFieldClick and handleSubmit dependency arrays
This commit is contained in:
Chandler Copeland
2026-03-21 11:52:09 -06:00
parent ea3365feb4
commit 06e477b455

View File

@@ -8,6 +8,7 @@ import 'react-pdf/dist/Page/TextLayer.css';
import { SigningProgressBar } from './SigningProgressBar';
import { SignatureModal } from './SignatureModal';
import type { SignatureFieldData } from '@/lib/db/schema';
import { getFieldType } from '@/lib/db/schema';
// Worker setup — reuse same pattern as PdfViewerWrapper (no CDN, works in local/Docker)
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
@@ -84,11 +85,16 @@ export function SigningPageClient({
const handleFieldClick = useCallback(
(fieldId: string) => {
const field = signatureFields.find((f) => f.id === fieldId);
if (!field) return;
// Defense-in-depth: primary protection is the server filter in GET /api/sign/[token]
// Only client-signature fields open the modal; Phase 10 will expand this for initials
if (getFieldType(field) !== 'client-signature') return;
if (signedFields.has(fieldId)) return;
setActiveFieldId(fieldId);
setModalOpen(true);
},
[signedFields]
[signatureFields, signedFields]
);
const handleModalConfirm = useCallback(
@@ -126,7 +132,10 @@ export function SigningPageClient({
}, [signatureFields, signedFields]);
const handleSubmit = useCallback(async () => {
if (signedFields.size < signatureFields.length || submitting) return;
const clientSigFields = signatureFields.filter(
(f) => getFieldType(f) === 'client-signature'
);
if (signedFields.size < clientSigFields.length || submitting) return;
setSubmitting(true);
try {
const res = await fetch(`/api/sign/${token}`, {
@@ -148,7 +157,7 @@ export function SigningPageClient({
alert('Network error. Please check your connection and try again.');
setSubmitting(false);
}
}, [signedFields.size, signatureFields.length, submitting, token]);
}, [signedFields.size, signatureFields, submitting, token]);
/**
* Convert PDF user-space coordinates (bottom-left origin) to screen overlay position.
@@ -325,7 +334,7 @@ export function SigningPageClient({
{/* Sticky progress bar */}
<SigningProgressBar
total={signatureFields.length}
total={signatureFields.filter((f) => getFieldType(f) === 'client-signature').length}
signed={signedFields.size}
onJumpToNext={handleJumpToNext}
onSubmit={handleSubmit}