diff --git a/apps/web/src/app/(dashboard)/documents/[id]/edit-document.tsx b/apps/web/src/app/(dashboard)/documents/[id]/edit-document.tsx index 9c37ab7b7..e8ddb013c 100644 --- a/apps/web/src/app/(dashboard)/documents/[id]/edit-document.tsx +++ b/apps/web/src/app/(dashboard)/documents/[id]/edit-document.tsx @@ -6,6 +6,7 @@ import { useRouter, useSearchParams } from 'next/navigation'; import { msg } from '@lingui/macro'; import { useLingui } from '@lingui/react'; +import { useSession } from 'next-auth/react'; import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION, @@ -53,6 +54,7 @@ export const EditDocumentForm = ({ const router = useRouter(); const searchParams = useSearchParams(); const team = useOptionalCurrentTeam(); + const { data: session } = useSession(); const [isDocumentPdfLoaded, setIsDocumentPdfLoaded] = useState(false); @@ -138,6 +140,19 @@ export const EditDocumentForm = ({ }, }); + const { mutateAsync: selfSignDocument } = trpc.document.selfSignDocument.useMutation({ + ...DO_NOT_INVALIDATE_QUERY_ON_MUTATION, + onSuccess: (newData) => { + utils.document.getDocumentWithDetailsById.setData( + { + id: initialDocument.id, + teamId: team?.id, + }, + (oldData) => ({ ...(oldData || initialDocument), ...newData }), + ); + }, + }); + const { mutateAsync: setPasswordForDocument } = trpc.document.setPasswordForDocument.useMutation(); @@ -266,10 +281,22 @@ export const EditDocumentForm = ({ } } - // Router refresh is here to clear the router cache for when navigating to /documents. - router.refresh(); + const hasSameOwnerAsRecipient = + recipients.length === 1 && recipients[0].email === session?.user?.email; - setStep('subject'); + if (hasSameOwnerAsRecipient) { + await selfSignDocument({ + documentId: document.id, + teamId: team?.id, + }); + + router.push(`/sign/${recipients[0].token}`); + } else { + // Router refresh is here to clear the router cache for when navigating to /documents. + router.refresh(); + + setStep('subject'); + } } catch (err) { console.error(err); diff --git a/packages/trpc/server/document-router/router.ts b/packages/trpc/server/document-router/router.ts index 8dd401c04..5db61ca87 100644 --- a/packages/trpc/server/document-router/router.ts +++ b/packages/trpc/server/document-router/router.ts @@ -37,6 +37,7 @@ import { ZMoveDocumentsToTeamSchema, ZResendDocumentMutationSchema, ZSearchDocumentsMutationSchema, + ZSelfSignDocumentMutationSchema, ZSendDocumentMutationSchema, ZSetPasswordForDocumentMutationSchema, ZSetSettingsForDocumentMutationSchema, @@ -367,6 +368,29 @@ export const documentRouter = router({ } }), + selfSignDocument: authenticatedProcedure + .input(ZSelfSignDocumentMutationSchema) + .mutation(async ({ input, ctx }) => { + try { + const { documentId, teamId } = input; + + return await sendDocument({ + userId: ctx.user.id, + documentId, + teamId, + sendEmail: false, + requestMetadata: extractNextApiRequestMetadata(ctx.req), + }); + } catch (err) { + console.error(err); + + throw new TRPCError({ + code: 'BAD_REQUEST', + message: 'We were unable to self sign this document. Please try again later.', + }); + } + }), + resendDocument: authenticatedProcedure .input(ZResendDocumentMutationSchema) .mutation(async ({ input, ctx }) => { diff --git a/packages/trpc/server/document-router/schema.ts b/packages/trpc/server/document-router/schema.ts index 2b401a7d0..41b757f81 100644 --- a/packages/trpc/server/document-router/schema.ts +++ b/packages/trpc/server/document-router/schema.ts @@ -140,6 +140,11 @@ export const ZSendDocumentMutationSchema = z.object({ }), }); +export const ZSelfSignDocumentMutationSchema = z.object({ + documentId: z.number(), + teamId: z.number().optional(), +}); + export const ZSetPasswordForDocumentMutationSchema = z.object({ documentId: z.number(), password: z.string(), diff --git a/packages/ui/primitives/document-flow/add-fields.tsx b/packages/ui/primitives/document-flow/add-fields.tsx index f4a5423a2..04afdf617 100644 --- a/packages/ui/primitives/document-flow/add-fields.tsx +++ b/packages/ui/primitives/document-flow/add-fields.tsx @@ -20,6 +20,7 @@ import { Type, User, } from 'lucide-react'; +import { useSession } from 'next-auth/react'; import { useFieldArray, useForm } from 'react-hook-form'; import { useHotkeys } from 'react-hotkeys-hook'; import { prop, sortBy } from 'remeda'; @@ -99,6 +100,13 @@ export type AddFieldsFormProps = { teamId?: number; }; +// Self Sign +// If the recipient is the user and it is the only recipient, +// dont send the document, after adding the fields, skip the next step and go straight to the point +// no need for the sending section +// it will create the document +// and redirect you to the signing page. + export const AddFieldsFormPartial = ({ documentFlow, hideRecipients = false, @@ -110,6 +118,7 @@ export const AddFieldsFormPartial = ({ teamId, }: AddFieldsFormProps) => { const { toast } = useToast(); + const { data: session } = useSession(); const [isMissingSignatureDialogVisible, setIsMissingSignatureDialogVisible] = useState(false); @@ -530,6 +539,10 @@ export const AddFieldsFormPartial = ({ ); }, [recipientsByRole]); + const hasSameOwnerAsRecipient = + recipientsByRole.SIGNER.length === 1 && + recipientsByRole.SIGNER[0].email === session?.user?.email; + const handleAdvancedSettings = () => { setShowAdvancedSettings((prev) => !prev); }; @@ -1067,6 +1080,7 @@ export const AddFieldsFormPartial = ({ documentFlow.onBackStep?.(); }} goBackLabel={canRenderBackButtonAsRemove ? msg`Remove` : undefined} + goNextLabel={hasSameOwnerAsRecipient ? msg`Self Sign` : undefined} onGoNextClick={handleGoNextClick} />