feat(05-04): lock field placer to read-only when document is Sent
- Add readOnly prop to FieldPlacer; when true: hide palette, disable all pointer
events on field boxes, show fields at 60% opacity, suppress delete button and
all four resize handles
- PdfViewer accepts docStatus prop and derives readOnly={docStatus==='Sent'||'Signed'}
- PdfViewerWrapper forwards docStatus prop to PdfViewer
- page.tsx passes docStatus={doc.status} to PdfViewerWrapper
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,12 +19,14 @@ interface PageInfo {
|
|||||||
scale: number;
|
scale: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PdfViewer({ docId }: { docId: string }) {
|
export function PdfViewer({ docId, docStatus }: { docId: string; docStatus?: string }) {
|
||||||
const [numPages, setNumPages] = useState(0);
|
const [numPages, setNumPages] = useState(0);
|
||||||
const [pageNumber, setPageNumber] = useState(1);
|
const [pageNumber, setPageNumber] = useState(1);
|
||||||
const [scale, setScale] = useState(1.0);
|
const [scale, setScale] = useState(1.0);
|
||||||
const [pageInfo, setPageInfo] = useState<PageInfo | null>(null);
|
const [pageInfo, setPageInfo] = useState<PageInfo | null>(null);
|
||||||
|
|
||||||
|
const readOnly = docStatus === 'Sent' || docStatus === 'Signed';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center gap-4">
|
<div className="flex flex-col items-center gap-4">
|
||||||
<div className="flex items-center gap-3 text-sm">
|
<div className="flex items-center gap-3 text-sm">
|
||||||
@@ -65,7 +67,7 @@ export function PdfViewer({ docId }: { docId: string }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* PDF canvas wrapped in FieldPlacer for drag-and-drop field placement */}
|
{/* PDF canvas wrapped in FieldPlacer for drag-and-drop field placement */}
|
||||||
<FieldPlacer docId={docId} pageInfo={pageInfo} currentPage={pageNumber}>
|
<FieldPlacer docId={docId} pageInfo={pageInfo} currentPage={pageNumber} readOnly={readOnly}>
|
||||||
<Document
|
<Document
|
||||||
file={`/api/documents/${docId}/file`}
|
file={`/api/documents/${docId}/file`}
|
||||||
onLoadSuccess={({ numPages }) => setNumPages(numPages)}
|
onLoadSuccess={({ numPages }) => setNumPages(numPages)}
|
||||||
|
|||||||
@@ -3,6 +3,6 @@ import dynamic from 'next/dynamic';
|
|||||||
|
|
||||||
const PdfViewer = dynamic(() => import('./PdfViewer').then(m => m.PdfViewer), { ssr: false });
|
const PdfViewer = dynamic(() => import('./PdfViewer').then(m => m.PdfViewer), { ssr: false });
|
||||||
|
|
||||||
export function PdfViewerWrapper({ docId }: { docId: string }) {
|
export function PdfViewerWrapper({ docId, docStatus }: { docId: string; docStatus?: string }) {
|
||||||
return <PdfViewer docId={docId} />;
|
return <PdfViewer docId={docId} docStatus={docStatus} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export default async function DocumentPage({
|
|||||||
|
|
||||||
<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">
|
||||||
<PdfViewerWrapper docId={docId} />
|
<PdfViewerWrapper docId={docId} docStatus={doc.status} />
|
||||||
</div>
|
</div>
|
||||||
<div className="lg:col-span-1">
|
<div className="lg:col-span-1">
|
||||||
<PreparePanel
|
<PreparePanel
|
||||||
|
|||||||
Reference in New Issue
Block a user