fix(signers): show invalid email error, persist signers immediately via PATCH, add PATCH /api/documents/[id]
This commit is contained in:
36
teressa-copeland-homes/src/app/api/documents/[id]/route.ts
Normal file
36
teressa-copeland-homes/src/app/api/documents/[id]/route.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { auth } from '@/lib/auth';
|
||||
import { db } from '@/lib/db';
|
||||
import { documents } from '@/lib/db/schema';
|
||||
import type { DocumentSigner } from '@/lib/db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
|
||||
// PATCH /api/documents/[id] — partial update (signers, name, etc.)
|
||||
export async function PATCH(
|
||||
req: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const session = await auth();
|
||||
if (!session) return new Response('Unauthorized', { status: 401 });
|
||||
|
||||
const { id } = await params;
|
||||
const body = await req.json() as { signers?: DocumentSigner[] };
|
||||
|
||||
const doc = await db.query.documents.findFirst({ where: eq(documents.id, id) });
|
||||
if (!doc) return NextResponse.json({ error: 'Not found' }, { status: 404 });
|
||||
|
||||
const updates: Partial<typeof documents.$inferInsert> = {};
|
||||
if (body.signers !== undefined) updates.signers = body.signers;
|
||||
|
||||
if (Object.keys(updates).length === 0) {
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
|
||||
const [updated] = await db
|
||||
.update(documents)
|
||||
.set(updates)
|
||||
.where(eq(documents.id, id))
|
||||
.returning();
|
||||
|
||||
return NextResponse.json(updated);
|
||||
}
|
||||
@@ -67,6 +67,16 @@ export function PreparePanel({
|
||||
const [signerInput, setSignerInput] = useState('');
|
||||
const [signerInputError, setSignerInputError] = useState<string | null>(null);
|
||||
|
||||
async function saveSigners(updated: DocumentSigner[]) {
|
||||
onSignersChange?.(updated);
|
||||
// Persist immediately so signers survive page refresh
|
||||
await fetch(`/api/documents/${docId}`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ signers: updated }),
|
||||
});
|
||||
}
|
||||
|
||||
function handleAddSigner() {
|
||||
const email = signerInput.trim().toLowerCase();
|
||||
if (!email || !isValidEmail(email)) {
|
||||
@@ -78,14 +88,14 @@ export function PreparePanel({
|
||||
return;
|
||||
}
|
||||
const color = SIGNER_COLORS[signers.length % SIGNER_COLORS.length];
|
||||
onSignersChange?.([...signers, { email, color }]);
|
||||
saveSigners([...signers, { email, color }]);
|
||||
setSignerInput('');
|
||||
setSignerInputError(null);
|
||||
}
|
||||
|
||||
function handleRemoveSigner(email: string) {
|
||||
onSignersChange?.(signers.filter(s => s.email !== email));
|
||||
// Clear validation state since signer count changed
|
||||
const updated = signers.filter(s => s.email !== email);
|
||||
saveSigners(updated);
|
||||
onUnassignedFieldIdsChange?.(new Set());
|
||||
}
|
||||
|
||||
@@ -329,6 +339,9 @@ export function PreparePanel({
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-xs text-gray-400 mt-1">Each signer receives their own signing link.</p>
|
||||
{signerInputError === 'invalid' && (
|
||||
<p className="text-sm text-red-600 mt-1">Please enter a valid email address.</p>
|
||||
)}
|
||||
{signerInputError === 'duplicate' && (
|
||||
<p className="text-sm text-red-600 mt-1">That email is already in the signer list.</p>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user