From facbe60b509d0c2206a4f9cbd40e96c45579a234 Mon Sep 17 00:00:00 2001
From: Timur Ercan
Date: Mon, 6 Mar 2023 18:06:22 +0100
Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=B8validate=20emails=20using=20react?=
=?UTF-8?q?=20form=20hook?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apps/web/pages/documents/[id]/recipients.tsx | 443 +++++++++++--------
1 file changed, 247 insertions(+), 196 deletions(-)
diff --git a/apps/web/pages/documents/[id]/recipients.tsx b/apps/web/pages/documents/[id]/recipients.tsx
index 568edd4f0..40364c7da 100644
--- a/apps/web/pages/documents/[id]/recipients.tsx
+++ b/apps/web/pages/documents/[id]/recipients.tsx
@@ -12,6 +12,7 @@ import {
PencilSquareIcon,
TrashIcon,
UserPlusIcon,
+ XMarkIcon,
} from "@heroicons/react/24/outline";
import { getUserFromToken } from "@documenso/lib/server";
import { getDocument } from "@documenso/lib/query";
@@ -23,6 +24,16 @@ import {
deleteRecipient,
sendSigningRequests,
} from "@documenso/lib/api";
+import {
+ FormProvider,
+ useFieldArray,
+ useForm,
+ useWatch,
+} from "react-hook-form";
+
+type FormValues = {
+ signers: { id: number; email: string; name: string }[];
+};
const RecipientsPage: NextPageWithLayout = (props: any) => {
const title: string =
@@ -46,11 +57,28 @@ const RecipientsPage: NextPageWithLayout = (props: any) => {
},
];
- const [signers, setSigners] = useState(props?.document?.Recipient);
const [loading, setLoading] = useState(false);
const [open, setOpen] = useState(false);
-
+ const form = useForm({
+ defaultValues: { signers: props?.document?.Recipient },
+ });
+ const {
+ register,
+ trigger,
+ control,
+ formState: { errors },
+ } = form;
+ const { fields, append, remove } = useFieldArray({
+ keyName: "dieldArrayId",
+ name: "signers",
+ control,
+ });
+ const formValues = useWatch({ control, name: "signers" });
const cancelButtonRef = useRef(null);
+ const hasEmailError = (formValue: any): boolean => {
+ const index = formValues.findIndex((e) => e.id === formValue.id);
+ return !!errors?.signers?.[index]?.email;
+ };
return (
<>
@@ -93,9 +121,10 @@ const RecipientsPage: NextPageWithLayout = (props: any) => {
setOpen(true);
}}
disabled={
- (signers.length || 0) === 0 ||
- !signers.some(
- (r: any) => r.email && r.sendStatus === "NOT_SENT"
+ (formValues.length || 0) === 0 ||
+ !formValues.some(
+ (r: any) =>
+ r.email && !hasEmailError(r) && r.sendStatus === "NOT_SENT"
) ||
loading
}
@@ -113,200 +142,222 @@ const RecipientsPage: NextPageWithLayout = (props: any) => {
The people who will sign the document.
-
- {signers.map((item: any, index: number) => (
- -
-
-
-
-
- {
- const updatedSigners = [...signers];
- updatedSigners[index].name = e.target.value;
- setSigners(updatedSigners);
- }}
- onBlur={() => {
- item.documentId = props.document.id;
- createOrUpdateRecipient(item);
- }}
- onKeyDown={(event: any) => {
- if (event.key === "Enter")
- createOrUpdateRecipient(item);
- }}
- className="block w-full border-0 p-0 text-gray-900 placeholder-gray-500 sm:text-sm outline-none bg-inherit"
- placeholder="John Dorian"
- />
-
-
-
- {item.sendStatus === "NOT_SENT" ? (
-
+
+
+
+ {
+ if (!errors?.signers?.[index])
+ createOrUpdateRecipient({
+ ...formValues[index],
+ documentId: props.document.id,
+ });
+ }}
+ onKeyDown={(event: any) => {
+ if (
+ event.key === "Enter" &&
+ !errors?.signers?.[index]
+ )
+ createOrUpdateRecipient({
+ ...formValues[index],
+ documentId: props.document.id,
+ });
+ }}
+ className="block w-full border-0 p-0 text-gray-900 placeholder-gray-500 sm:text-sm outline-none bg-inherit"
+ placeholder="John Dorian"
+ />
+
+
+
+ {item.sendStatus === "NOT_SENT" ? (
+
+ Not Sent
+
+ ) : (
+ ""
+ )}
+ {item.sendStatus === "SENT" &&
+ item.readStatus !== "OPENED" ? (
+
+
+ {" "}
+ Sent
+
+
+ ) : (
+ ""
+ )}
+ {item.readStatus === "OPENED" &&
+ item.signingStatus === "NOT_SIGNED" ? (
+
+
+
+
+ Seen
+
+
+ ) : (
+ ""
+ )}
+ {item.signingStatus === "SIGNED" ? (
+
+
+
+ Signed
+
+
+ ) : (
+ ""
+ )}
+
+
+
+ {
+ if (confirm("Resend this signing request?")) {
+ setLoading(true);
+ sendSigningRequests(props.document, [
+ item.id,
+ ]).finally(() => {
+ setLoading(false);
+ });
+ }
+ }}
+ >
+ Resend
+
+ {
+ const removedItem = { ...fields }[index];
+ remove(index);
+ deleteRecipient(item)?.catch((err) => {
+ append(removedItem);
+ });
+ }}
+ className="group-hover:text-neon-dark group-hover:disabled:text-gray-400"
+ />
+
-
-
- {
- if (confirm("Resend this signing request?")) {
- setLoading(true);
- sendSigningRequests(props.document, [
- item.id,
- ]).finally(() => {
- setLoading(false);
- });
- }
- }}
- >
- Resend
-
- {
- const signersWithoutIndex = [...signers];
- const removedItem = signersWithoutIndex.splice(
- index,
- 1
- );
- setSigners(signersWithoutIndex);
- deleteRecipient(item)?.catch((err) => {
- setSigners(signersWithoutIndex.concat(removedItem));
- });
- }}
- className="group-hover:text-neon-dark group-hover:disabled:text-gray-400"
- />
-
-
-
- ))}
-
-
+
+ ))}
+
+
+
+
@@ -357,7 +408,7 @@ const RecipientsPage: NextPageWithLayout = (props: any) => {
{`"${props.document.title}" will be sent to ${
- signers.filter(
+ formValues.filter(
(s: any) => s.email && s.sendStatus != "SENT"
).length
} recipients.`}