diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3471f4f88..790c1ab0b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -10,13 +10,7 @@ "ghcr.io/devcontainers/features/node:1": {} }, "onCreateCommand": "./.devcontainer/on-create.sh", - "forwardPorts": [ - 3000, - 54320, - 9000, - 2500, - 1100 - ], + "forwardPorts": [3000, 54320, 9000, 2500, 1100], "customizations": { "vscode": { "extensions": [ @@ -35,4 +29,4 @@ ] } } -} \ No newline at end of file +} diff --git a/apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx b/apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx index f05d148f7..ddc49b1cf 100644 --- a/apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx +++ b/apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx @@ -221,7 +221,7 @@ export const DocumentPageView = async ({ params, team }: DocumentPageViewProps) -

+

{match(document.status) .with(DocumentStatus.COMPLETED, () => ( This document has been signed by all recipients 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 bf9b671c4..f39863f43 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 @@ -1,7 +1,6 @@ import { useMemo, useState } from 'react'; import { Trans } from '@lingui/macro'; -import { useLingui } from '@lingui/react'; import { DateTime } from 'luxon'; import { match } from 'ts-pattern'; @@ -72,9 +71,8 @@ export const SignDirectTemplateForm = ({ template, onSubmit, }: SignDirectTemplateFormProps) => { - const { _ } = useLingui(); - - const { fullName, signature, setFullName, setSignature } = useRequiredSigningContext(); + const { fullName, signature, signatureValid, setFullName, setSignature } = + useRequiredSigningContext(); const [localFields, setLocalFields] = useState(directRecipientFields); const [validateUninsertedFields, setValidateUninsertedFields] = useState(false); @@ -135,6 +133,8 @@ export const SignDirectTemplateForm = ({ ); }; + const hasSignatureField = localFields.some((field) => field.type === FieldType.SIGNATURE); + const uninsertedFields = useMemo(() => { return sortFieldsByPosition(localFields.filter((field) => !field.inserted)); }, [localFields]); @@ -147,6 +147,10 @@ export const SignDirectTemplateForm = ({ const handleSubmit = async () => { setValidateUninsertedFields(true); + if (hasSignatureField && !signatureValid) { + return; + } + const isFieldsValid = validateFieldsInserted(localFields); if (!isFieldsValid) { diff --git a/apps/web/src/app/(signing)/sign/[token]/form.tsx b/apps/web/src/app/(signing)/sign/[token]/form.tsx index 8085234db..17a33dff3 100644 --- a/apps/web/src/app/(signing)/sign/[token]/form.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/form.tsx @@ -12,7 +12,7 @@ import { useAnalytics } from '@documenso/lib/client-only/hooks/use-analytics'; import type { DocumentAndSender } from '@documenso/lib/server-only/document/get-document-by-token'; import type { TRecipientActionAuth } from '@documenso/lib/types/document-auth'; import { sortFieldsByPosition, validateFieldsInserted } from '@documenso/lib/utils/fields'; -import { type Field, type Recipient, RecipientRole } from '@documenso/prisma/client'; +import { type Field, FieldType, type Recipient, RecipientRole } from '@documenso/prisma/client'; import { trpc } from '@documenso/trpc/react'; import { FieldToolTip } from '@documenso/ui/components/field/field-tooltip'; import { cn } from '@documenso/ui/lib/utils'; @@ -44,7 +44,8 @@ export const SigningForm = ({ const analytics = useAnalytics(); const { data: session } = useSession(); - const { fullName, signature, setFullName, setSignature } = useRequiredSigningContext(); + const { fullName, signature, setFullName, setSignature, signatureValid, setSignatureValid } = + useRequiredSigningContext(); const [validateUninsertedFields, setValidateUninsertedFields] = useState(false); @@ -56,6 +57,8 @@ export const SigningForm = ({ // Keep the loading state going if successful since the redirect may take some time. const isSubmitting = formState.isSubmitting || formState.isSubmitSuccessful; + const hasSignatureField = fields.some((field) => field.type === FieldType.SIGNATURE); + const uninsertedFields = useMemo(() => { return sortFieldsByPosition(fields.filter((field) => !field.inserted)); }, [fields]); @@ -68,6 +71,10 @@ export const SigningForm = ({ const onFormSubmit = async () => { setValidateUninsertedFields(true); + if (hasSignatureField && !signatureValid) { + return; + } + const isFieldsValid = validateFieldsInserted(fields); if (!isFieldsValid) { @@ -142,7 +149,7 @@ export const SigningForm = ({

@@ -307,7 +322,7 @@ export const SignatureField = ({