From 1e90ca45a62814392490a35a097e4e4b76827bb0 Mon Sep 17 00:00:00 2001 From: Ephraim Atta-Duncan Date: Fri, 14 Feb 2025 12:18:19 +0000 Subject: [PATCH] chore: disable form on last signer --- .../src/app/(signing)/sign/[token]/form.tsx | 8 +++- .../src/app/(signing)/sign/[token]/page.tsx | 5 +- .../(signing)/sign/[token]/sign-dialog.tsx | 34 +++----------- .../sign/[token]/signing-page-view.tsx | 3 ++ .../recipient/get-is-last-recipient.ts | 46 +++++++++++++++++++ 5 files changed, 66 insertions(+), 30 deletions(-) create mode 100644 packages/lib/server-only/recipient/get-is-last-recipient.ts diff --git a/apps/web/src/app/(signing)/sign/[token]/form.tsx b/apps/web/src/app/(signing)/sign/[token]/form.tsx index 6d102d98d..df5e61856 100644 --- a/apps/web/src/app/(signing)/sign/[token]/form.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/form.tsx @@ -45,6 +45,7 @@ export type SigningFormProps = { isRecipientsTurn: boolean; allRecipients?: RecipientWithFields[]; setSelectedSignerId?: (id: number | null) => void; + isLastRecipient: boolean; }; type SigningFormData = { @@ -60,6 +61,7 @@ export const SigningForm = ({ isRecipientsTurn, allRecipients = [], setSelectedSignerId, + isLastRecipient, }: SigningFormProps) => { const { _ } = useLingui(); const { toast } = useToast(); @@ -252,7 +254,8 @@ export const SigningForm = ({ disabled={!isRecipientsTurn} canModifyNextSigner={ document.documentMeta?.modifyNextSigner && - document.documentMeta?.signingOrder === DocumentSigningOrder.SEQUENTIAL + document.documentMeta?.signingOrder === DocumentSigningOrder.SEQUENTIAL && + !isLastRecipient } /> @@ -435,7 +438,8 @@ export const SigningForm = ({ disabled={!isRecipientsTurn} canModifyNextSigner={ document.documentMeta?.modifyNextSigner && - document.documentMeta?.signingOrder === DocumentSigningOrder.SEQUENTIAL + document.documentMeta?.signingOrder === DocumentSigningOrder.SEQUENTIAL && + !isLastRecipient } /> diff --git a/apps/web/src/app/(signing)/sign/[token]/page.tsx b/apps/web/src/app/(signing)/sign/[token]/page.tsx index df559123d..575adcbcc 100644 --- a/apps/web/src/app/(signing)/sign/[token]/page.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/page.tsx @@ -9,6 +9,7 @@ import { isRecipientAuthorized } from '@documenso/lib/server-only/document/is-re import { viewedDocument } from '@documenso/lib/server-only/document/viewed-document'; import { getCompletedFieldsForToken } from '@documenso/lib/server-only/field/get-completed-fields-for-token'; import { getFieldsForToken } from '@documenso/lib/server-only/field/get-fields-for-token'; +import { getIsLastRecipient } from '@documenso/lib/server-only/recipient/get-is-last-recipient'; import { getIsRecipientsTurnToSign } from '@documenso/lib/server-only/recipient/get-is-recipient-turn'; import { getRecipientByToken } from '@documenso/lib/server-only/recipient/get-recipient-by-token'; import { getRecipientSignatures } from '@documenso/lib/server-only/recipient/get-recipient-signatures'; @@ -44,7 +45,7 @@ export default async function SigningPage({ params: { token } }: SigningPageProp const requestMetadata = extractNextHeaderRequestMetadata(requestHeaders); - const [document, recipient, fields, completedFields] = await Promise.all([ + const [document, recipient, fields, completedFields, isLastRecipient] = await Promise.all([ getDocumentAndSenderByToken({ token, userId: user?.id, @@ -53,6 +54,7 @@ export default async function SigningPage({ params: { token } }: SigningPageProp getRecipientByToken({ token }).catch(() => null), getFieldsForToken({ token }), getCompletedFieldsForToken({ token }), + getIsLastRecipient({ token }), ]); if ( @@ -169,6 +171,7 @@ export default async function SigningPage({ params: { token } }: SigningPageProp completedFields={completedFields} isRecipientsTurn={isRecipientsTurn} allRecipients={allRecipients} + isLastRecipient={isLastRecipient} /> diff --git a/apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx b/apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx index c3029210e..5e44003fe 100644 --- a/apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx @@ -38,7 +38,7 @@ export type SignDialogProps = { documentTitle: string; fields: Field[]; fieldsValidated: () => void | Promise; - onSignatureComplete: (nextSigner?: { email: string; name: string }) => void | Promise; + onSignatureComplete: (nextSigner?: { email?: string; name?: string }) => void | Promise; role: RecipientRole; disabled?: boolean; canModifyNextSigner?: boolean; @@ -48,20 +48,10 @@ const formSchema = z.object({ nextSigner: z .object({ email: z.string().email({ message: 'Please enter a valid email address' }).optional(), - name: z.string().min(1, { message: 'Name is required' }).optional(), + name: z.string().optional(), }) - .refine( - (data) => { - if (data.name) { - return !!data.email; - } - return true; - }, - { - message: 'Email is required when name is provided', - path: ['email'], - }, - ), + .optional() + .default({}), }); type TFormSchema = z.infer; @@ -99,26 +89,15 @@ export function SignDialog({ const form = useForm({ resolver: zodResolver(formSchema), - defaultValues: { - nextSigner: { - email: '', - name: '', - }, - }, }); const onFormSubmit = async (data: TFormSchema) => { try { await fieldsValidated(); - if (!canModifyNextSigner || !data.nextSigner.email) { - await onSignatureComplete(); - return; - } - await onSignatureComplete({ - email: data.nextSigner.email.trim().toLowerCase(), - name: data.nextSigner.name?.trim() ?? '', + email: data.nextSigner.email?.trim().toLowerCase(), + name: data.nextSigner.name?.trim(), }); setShowDialog(false); @@ -378,6 +357,7 @@ export function SignDialog({ Cancel + {step === 1 && (