From b444d5c928765aa0aee55b25c881042f2811cebe Mon Sep 17 00:00:00 2001 From: Mythie Date: Wed, 19 Apr 2023 22:48:26 +1000 Subject: [PATCH] feat: add name field Adds support for a name field which will be prefilled with the recipients name if they haven't signed a form on Documenso before. --- .../components/editor/field-type-selector.tsx | 11 ++- apps/web/components/editor/name-dialog.tsx | 95 +++++++++++++++++++ apps/web/components/editor/pdf-signer.tsx | 33 +++++-- apps/web/components/editor/signable-field.tsx | 12 ++- apps/web/pages/api/documents/[id]/sign.ts | 6 +- packages/pdf/insertTextInPDF.ts | 5 +- .../migration.sql | 2 + packages/prisma/schema.prisma | 1 + 8 files changed, 151 insertions(+), 14 deletions(-) create mode 100644 apps/web/components/editor/name-dialog.tsx create mode 100644 packages/prisma/migrations/20230419055523_doc_170_add_name_field_type/migration.sql diff --git a/apps/web/components/editor/field-type-selector.tsx b/apps/web/components/editor/field-type-selector.tsx index c8a6ff454..b98faabdf 100644 --- a/apps/web/components/editor/field-type-selector.tsx +++ b/apps/web/components/editor/field-type-selector.tsx @@ -8,10 +8,17 @@ const stc = require("string-to-color"); export default function FieldTypeSelector(props: any) { const fieldTypes = [ { - name: "Signature", id: FieldType.SIGNATURE, + name: "Signature", + }, + { + id: FieldType.NAME, + name: "Name", + }, + { + id: FieldType.DATE, + name: "Date", }, - { name: "Date", id: FieldType.DATE }, ]; const [selectedFieldType, setSelectedFieldType] = useState(fieldTypes[0].id); diff --git a/apps/web/components/editor/name-dialog.tsx b/apps/web/components/editor/name-dialog.tsx new file mode 100644 index 000000000..31f64731d --- /dev/null +++ b/apps/web/components/editor/name-dialog.tsx @@ -0,0 +1,95 @@ +import { Fragment, useEffect, useState } from "react"; +import { classNames, localStorage } from "@documenso/lib"; +import { Button } from "@documenso/ui"; +import { Dialog, Transition } from "@headlessui/react"; + +export default function NameDialog(props: any) { + const [name, setName] = useState(props.defaultName); + + useEffect(() => { + const nameFromStorage = localStorage.getItem("typedName"); + + if (nameFromStorage) { + setName(nameFromStorage); + } + }, []); + + return ( + + { + props.setOpen(false); + }}> + +
+ + +
+
+ + +
+

+ Enter your name in the input below! +

+ +
+ { + setName(e.target.value); + }} + className={classNames( + "focus:border-neon focus:ring-neon mt-14 block h-10 w-full text-center align-bottom font-sans text-2xl leading-none" + )} + placeholder="Kindly type your name" + /> +
+ +
+ + +
+
+
+
+
+
+
+
+ ); +} diff --git a/apps/web/components/editor/pdf-signer.tsx b/apps/web/components/editor/pdf-signer.tsx index 797745a4c..d45784fb7 100644 --- a/apps/web/components/editor/pdf-signer.tsx +++ b/apps/web/components/editor/pdf-signer.tsx @@ -6,6 +6,7 @@ import { createOrUpdateField, deleteField, signDocument } from "@documenso/lib/a import { NEXT_PUBLIC_WEBAPP_URL } from "@documenso/lib/constants"; import { Button } from "@documenso/ui"; import Logo from "../logo"; +import NameDialog from "./name-dialog"; import SignatureDialog from "./signature-dialog"; import { CheckBadgeIcon, InformationCircleIcon } from "@heroicons/react/24/outline"; import { FieldType } from "@prisma/client"; @@ -16,11 +17,12 @@ const PDFViewer = dynamic(() => import("./pdf-viewer"), { export default function PDFSigner(props: any) { const router = useRouter(); - const [open, setOpen] = useState(false); + const [signatureDialogOpen, setSignatureDialogOpen] = useState(false); + const [nameDialogOpen, setNameDialogOpen] = useState(false); const [signingDone, setSigningDone] = useState(false); const [localSignatures, setLocalSignatures] = useState([]); const [fields, setFields] = useState(props.fields); - const signatureFields = fields.filter((field) => field.type === FieldType.SIGNATURE); + const signatureFields = fields.filter((field) => [FieldType.SIGNATURE].includes(field.type)); const [dialogField, setDialogField] = useState(); useEffect(() => { @@ -28,9 +30,14 @@ export default function PDFSigner(props: any) { }, [fields]); function onClick(item: any) { - if (item.type === "SIGNATURE") { + if (item.type === FieldType.SIGNATURE) { setDialogField(item); - setOpen(true); + setSignatureDialogOpen(true); + } + + if (item.type === FieldType.NAME) { + setDialogField(item); + setNameDialogOpen(true); } } @@ -61,13 +68,25 @@ export default function PDFSigner(props: any) { const signedField = { ...dialogField }; signedField.signature = signature; setFields((prevState) => [...prevState, signedField]); - setOpen(false); + setSignatureDialogOpen(false); + setNameDialogOpen(false); setDialogField(null); } return ( <> - + + +
@@ -153,7 +172,7 @@ export default function PDFSigner(props: any) { createOrUpdateField(props.document, freeSignatureField, recipient.token).then((res) => { setFields((prevState) => [...prevState, res]); setDialogField(res); - setOpen(true); + setSignatureDialogOpen(true); }); return freeSignatureField; diff --git a/apps/web/components/editor/signable-field.tsx b/apps/web/components/editor/signable-field.tsx index 29a8559e9..c685837af 100644 --- a/apps/web/components/editor/signable-field.tsx +++ b/apps/web/components/editor/signable-field.tsx @@ -2,6 +2,7 @@ import React, { useState } from "react"; import { classNames } from "@documenso/lib"; import { IconButton } from "@documenso/ui"; import { XCircleIcon } from "@heroicons/react/20/solid"; +import { FieldType } from "@prisma/client"; import Draggable from "react-draggable"; const stc = require("string-to-color"); @@ -46,7 +47,9 @@ export default function SignableField(props: FieldPropsType) { ref={nodeRef} className={classNames( "absolute top-0 left-0 m-auto h-16 w-48 select-none flex-row-reverse text-center text-lg font-bold opacity-80", - field.type === "SIGNATURE" ? "cursor-pointer hover:brightness-50" : "cursor-not-allowed" + [FieldType.SIGNATURE, FieldType.NAME].includes(field.type) + ? "cursor-pointer hover:brightness-50" + : "cursor-not-allowed" )} style={{ background: stc(props.field.Recipient.email), @@ -54,10 +57,15 @@ export default function SignableField(props: FieldPropsType) {