diff --git a/apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx b/apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx index 14922a326..aaf529a2a 100644 --- a/apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx +++ b/apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx @@ -189,7 +189,6 @@ export const SignDirectTemplateForm = ({ field={field} recipient={directRecipient} onSignField={onSignField} - onUnsignField={onUnsignField} /> )) .with(FieldType.NAME, () => ( @@ -198,7 +197,6 @@ export const SignDirectTemplateForm = ({ field={field} recipient={directRecipient} onSignField={onSignField} - onUnsignField={onUnsignField} /> )) .with(FieldType.DATE, () => ( @@ -218,7 +216,6 @@ export const SignDirectTemplateForm = ({ field={field} recipient={directRecipient} onSignField={onSignField} - onUnsignField={onUnsignField} /> )) .with(FieldType.TEXT, () => { diff --git a/apps/web/src/app/(signing)/sign/[token]/date-field.tsx b/apps/web/src/app/(signing)/sign/[token]/date-field.tsx index b1bc52c14..e5c0194b3 100644 --- a/apps/web/src/app/(signing)/sign/[token]/date-field.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/date-field.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useTransition } from 'react'; +import { useEffect, useTransition } from 'react'; import { useRouter } from 'next/navigation'; @@ -23,6 +23,7 @@ import type { } from '@documenso/trpc/server/field-router/schema'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { useRequiredDocumentAuthContext } from './document-auth-provider'; import { SigningFieldContainer } from './signing-field-container'; export type DateFieldProps = { @@ -40,7 +41,6 @@ export const DateField = ({ dateFormat = DEFAULT_DOCUMENT_DATE_FORMAT, timezone = DEFAULT_DOCUMENT_TIME_ZONE, onSignField, - onUnsignField, }: DateFieldProps) => { const router = useRouter(); @@ -51,13 +51,13 @@ export const DateField = ({ const { mutateAsync: signFieldWithToken, isLoading: isSignFieldWithTokenLoading } = trpc.field.signFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); - const { - mutateAsync: removeSignedFieldWithToken, - isLoading: isRemoveSignedFieldWithTokenLoading, - } = trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); + const { isLoading: isRemoveSignedFieldWithTokenLoading } = + trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); const isLoading = isSignFieldWithTokenLoading || isRemoveSignedFieldWithTokenLoading || isPending; + const { executeActionAuthProcedure } = useRequiredDocumentAuthContext(); + const localDateString = convertToLocalSystemFormat(field.customText, dateFormat, timezone); const isDifferentTime = field.inserted && localDateString !== field.customText; @@ -98,37 +98,18 @@ export const DateField = ({ } }; - const onRemove = async () => { - try { - const payload: TRemovedSignedFieldWithTokenMutationSchema = { - token: recipient.token, - fieldId: field.id, - }; - - if (onUnsignField) { - await onUnsignField(payload); - return; - } - - await removeSignedFieldWithToken(payload); - - startTransition(() => router.refresh()); - } catch (err) { - console.error(err); - - toast({ - title: 'Error', - description: 'An error occurred while removing the signature.', - variant: 'destructive', + useEffect(() => { + if (!field.inserted) { + void executeActionAuthProcedure({ + onReauthFormSubmit: async (authOptions) => await onSign(authOptions), + actionTarget: field.type, }); } - }; + }, [field]); return ( diff --git a/apps/web/src/app/(signing)/sign/[token]/email-field.tsx b/apps/web/src/app/(signing)/sign/[token]/email-field.tsx index 9ff79e399..a56d88144 100644 --- a/apps/web/src/app/(signing)/sign/[token]/email-field.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/email-field.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useTransition } from 'react'; +import { useEffect, useTransition } from 'react'; import { useRouter } from 'next/navigation'; @@ -12,12 +12,10 @@ import type { TRecipientActionAuth } from '@documenso/lib/types/document-auth'; import type { Recipient } from '@documenso/prisma/client'; import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature'; import { trpc } from '@documenso/trpc/react'; -import type { - TRemovedSignedFieldWithTokenMutationSchema, - TSignFieldWithTokenMutationSchema, -} from '@documenso/trpc/server/field-router/schema'; +import type { TSignFieldWithTokenMutationSchema } from '@documenso/trpc/server/field-router/schema'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { useRequiredDocumentAuthContext } from './document-auth-provider'; import { useRequiredSigningContext } from './provider'; import { SigningFieldContainer } from './signing-field-container'; @@ -25,10 +23,9 @@ export type EmailFieldProps = { field: FieldWithSignature; recipient: Recipient; onSignField?: (value: TSignFieldWithTokenMutationSchema) => Promise | void; - onUnsignField?: (value: TRemovedSignedFieldWithTokenMutationSchema) => Promise | void; }; -export const EmailField = ({ field, recipient, onSignField, onUnsignField }: EmailFieldProps) => { +export const EmailField = ({ field, recipient, onSignField }: EmailFieldProps) => { const router = useRouter(); const { toast } = useToast(); @@ -40,13 +37,13 @@ export const EmailField = ({ field, recipient, onSignField, onUnsignField }: Ema const { mutateAsync: signFieldWithToken, isLoading: isSignFieldWithTokenLoading } = trpc.field.signFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); - const { - mutateAsync: removeSignedFieldWithToken, - isLoading: isRemoveSignedFieldWithTokenLoading, - } = trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); + const { isLoading: isRemoveSignedFieldWithTokenLoading } = + trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); const isLoading = isSignFieldWithTokenLoading || isRemoveSignedFieldWithTokenLoading || isPending; + const { executeActionAuthProcedure } = useRequiredDocumentAuthContext(); + const onSign = async (authOptions?: TRecipientActionAuth) => { try { const value = providedEmail ?? ''; @@ -84,34 +81,17 @@ export const EmailField = ({ field, recipient, onSignField, onUnsignField }: Ema } }; - const onRemove = async () => { - try { - const payload: TRemovedSignedFieldWithTokenMutationSchema = { - token: recipient.token, - fieldId: field.id, - }; - - if (onUnsignField) { - await onUnsignField(payload); - return; - } - - await removeSignedFieldWithToken(payload); - - startTransition(() => router.refresh()); - } catch (err) { - console.error(err); - - toast({ - title: 'Error', - description: 'An error occurred while removing the signature.', - variant: 'destructive', + useEffect(() => { + if (!field.inserted) { + void executeActionAuthProcedure({ + onReauthFormSubmit: async (authOptions) => await onSign(authOptions), + actionTarget: field.type, }); } - }; + }, [field]); return ( - + {isLoading && (
diff --git a/apps/web/src/app/(signing)/sign/[token]/initials-field.tsx b/apps/web/src/app/(signing)/sign/[token]/initials-field.tsx index 326b1ec48..e1bd92b18 100644 --- a/apps/web/src/app/(signing)/sign/[token]/initials-field.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/initials-field.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useTransition } from 'react'; +import { useEffect, useTransition } from 'react'; import { useRouter } from 'next/navigation'; @@ -13,12 +13,10 @@ import { extractInitials } from '@documenso/lib/utils/recipient-formatter'; import type { Recipient } from '@documenso/prisma/client'; import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature'; import { trpc } from '@documenso/trpc/react'; -import type { - TRemovedSignedFieldWithTokenMutationSchema, - TSignFieldWithTokenMutationSchema, -} from '@documenso/trpc/server/field-router/schema'; +import type { TSignFieldWithTokenMutationSchema } from '@documenso/trpc/server/field-router/schema'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { useRequiredDocumentAuthContext } from './document-auth-provider'; import { useRequiredSigningContext } from './provider'; import { SigningFieldContainer } from './signing-field-container'; @@ -26,15 +24,9 @@ export type InitialsFieldProps = { field: FieldWithSignature; recipient: Recipient; onSignField?: (value: TSignFieldWithTokenMutationSchema) => Promise | void; - onUnsignField?: (value: TRemovedSignedFieldWithTokenMutationSchema) => Promise | void; }; -export const InitialsField = ({ - field, - recipient, - onSignField, - onUnsignField, -}: InitialsFieldProps) => { +export const InitialsField = ({ field, recipient, onSignField }: InitialsFieldProps) => { const router = useRouter(); const { toast } = useToast(); @@ -46,13 +38,13 @@ export const InitialsField = ({ const { mutateAsync: signFieldWithToken, isLoading: isSignFieldWithTokenLoading } = trpc.field.signFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); - const { - mutateAsync: removeSignedFieldWithToken, - isLoading: isRemoveSignedFieldWithTokenLoading, - } = trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); + const { isLoading: isRemoveSignedFieldWithTokenLoading } = + trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); const isLoading = isSignFieldWithTokenLoading || isRemoveSignedFieldWithTokenLoading || isPending; + const { executeActionAuthProcedure } = useRequiredDocumentAuthContext(); + const onSign = async (authOptions?: TRecipientActionAuth) => { try { const value = initials ?? ''; @@ -90,34 +82,17 @@ export const InitialsField = ({ } }; - const onRemove = async () => { - try { - const payload: TRemovedSignedFieldWithTokenMutationSchema = { - token: recipient.token, - fieldId: field.id, - }; - - if (onUnsignField) { - await onUnsignField(payload); - return; - } - - await removeSignedFieldWithToken(payload); - - startTransition(() => router.refresh()); - } catch (err) { - console.error(err); - - toast({ - title: 'Error', - description: 'An error occurred while removing the signature.', - variant: 'destructive', + useEffect(() => { + if (!field.inserted) { + void executeActionAuthProcedure({ + onReauthFormSubmit: async (authOptions) => await onSign(authOptions), + actionTarget: field.type, }); } - }; + }, [field]); return ( - + {isLoading && (
diff --git a/apps/web/src/app/(signing)/sign/[token]/name-field.tsx b/apps/web/src/app/(signing)/sign/[token]/name-field.tsx index e4d13a603..06a3dfc5e 100644 --- a/apps/web/src/app/(signing)/sign/[token]/name-field.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/name-field.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState, useTransition } from 'react'; +import { useEffect, useTransition } from 'react'; import { useRouter } from 'next/navigation'; @@ -12,14 +12,7 @@ import type { TRecipientActionAuth } from '@documenso/lib/types/document-auth'; import { type Recipient } from '@documenso/prisma/client'; import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature'; import { trpc } from '@documenso/trpc/react'; -import type { - TRemovedSignedFieldWithTokenMutationSchema, - TSignFieldWithTokenMutationSchema, -} from '@documenso/trpc/server/field-router/schema'; -import { Button } from '@documenso/ui/primitives/button'; -import { Dialog, DialogContent, DialogFooter, DialogTitle } from '@documenso/ui/primitives/dialog'; -import { Input } from '@documenso/ui/primitives/input'; -import { Label } from '@documenso/ui/primitives/label'; +import type { TSignFieldWithTokenMutationSchema } from '@documenso/trpc/server/field-router/schema'; import { useToast } from '@documenso/ui/primitives/use-toast'; import { useRequiredDocumentAuthContext } from './document-auth-provider'; @@ -30,16 +23,14 @@ export type NameFieldProps = { field: FieldWithSignature; recipient: Recipient; onSignField?: (value: TSignFieldWithTokenMutationSchema) => Promise | void; - onUnsignField?: (value: TRemovedSignedFieldWithTokenMutationSchema) => Promise | void; }; -export const NameField = ({ field, recipient, onSignField, onUnsignField }: NameFieldProps) => { +export const NameField = ({ field, recipient, onSignField }: NameFieldProps) => { const router = useRouter(); const { toast } = useToast(); - const { fullName: providedFullName, setFullName: setProvidedFullName } = - useRequiredSigningContext(); + const { fullName: providedFullName } = useRequiredSigningContext(); const { executeActionAuthProcedure } = useRequiredDocumentAuthContext(); @@ -48,47 +39,15 @@ export const NameField = ({ field, recipient, onSignField, onUnsignField }: Name const { mutateAsync: signFieldWithToken, isLoading: isSignFieldWithTokenLoading } = trpc.field.signFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); - const { - mutateAsync: removeSignedFieldWithToken, - isLoading: isRemoveSignedFieldWithTokenLoading, - } = trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); + const { isLoading: isRemoveSignedFieldWithTokenLoading } = + trpc.field.removeSignedFieldWithToken.useMutation(DO_NOT_INVALIDATE_QUERY_ON_MUTATION); const isLoading = isSignFieldWithTokenLoading || isRemoveSignedFieldWithTokenLoading || isPending; - const [showFullNameModal, setShowFullNameModal] = useState(false); - const [localFullName, setLocalFullName] = useState(''); - - const onPreSign = () => { - if (!providedFullName) { - setShowFullNameModal(true); - return false; - } - - return true; - }; - - /** - * When the user clicks the sign button in the dialog where they enter their full name. - */ - const onDialogSignClick = () => { - setShowFullNameModal(false); - setProvidedFullName(localFullName); - - void executeActionAuthProcedure({ - onReauthFormSubmit: async (authOptions) => await onSign(authOptions, localFullName), - actionTarget: field.type, - }); - }; - const onSign = async (authOptions?: TRecipientActionAuth, name?: string) => { try { const value = name || providedFullName; - if (!value) { - setShowFullNameModal(true); - return; - } - const payload: TSignFieldWithTokenMutationSchema = { token: recipient.token, fieldId: field.id, @@ -122,40 +81,17 @@ export const NameField = ({ field, recipient, onSignField, onUnsignField }: Name } }; - const onRemove = async () => { - try { - const payload: TRemovedSignedFieldWithTokenMutationSchema = { - token: recipient.token, - fieldId: field.id, - }; - - if (onUnsignField) { - await onUnsignField(payload); - return; - } - - await removeSignedFieldWithToken(payload); - - startTransition(() => router.refresh()); - } catch (err) { - console.error(err); - - toast({ - title: 'Error', - description: 'An error occurred while removing the signature.', - variant: 'destructive', + useEffect(() => { + if (!field.inserted) { + void executeActionAuthProcedure({ + onReauthFormSubmit: async (authOptions) => await onSign(authOptions), + actionTarget: field.type, }); } - }; + }, [field]); return ( - + {isLoading && (
@@ -173,51 +109,6 @@ export const NameField = ({ field, recipient, onSignField, onUnsignField }: Name {field.customText}

)} - - - - - Sign as {recipient.name}{' '} -
({recipient.email})
-
- -
- - - setLocalFullName(e.target.value.trimStart())} - /> -
- - -
- - - -
-
-
-
); }; diff --git a/apps/web/src/app/(signing)/sign/[token]/signing-field-container.tsx b/apps/web/src/app/(signing)/sign/[token]/signing-field-container.tsx index 103c5f9e5..43f4c26b4 100644 --- a/apps/web/src/app/(signing)/sign/[token]/signing-field-container.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/signing-field-container.tsx @@ -67,6 +67,8 @@ export const SigningFieldContainer = ({ const parsedFieldMeta = field.fieldMeta ? ZFieldMetaSchema.parse(field.fieldMeta) : undefined; const readOnlyField = parsedFieldMeta?.readOnly || false; + const automatedFields = ['Initials', 'Email', 'Name', 'Date'].includes(type ?? ''); + const handleInsertField = async () => { if (field.inserted || !onSign) { return; @@ -171,14 +173,18 @@ export const SigningFieldContainer = ({ )} - {type !== 'Date' && type !== 'Checkbox' && field.inserted && !loading && !readOnlyField && ( - - )} + {type !== 'Checkbox' && + !automatedFields && + field.inserted && + !loading && + !readOnlyField && ( + + )} {children}