import Head from "next/head"; import { Fragment, ReactElement, useRef, useState } from "react"; import Layout from "../../../components/layout"; import { NextPageWithLayout } from "../../_app"; import { classNames, NEXT_PUBLIC_WEBAPP_URL } from "@documenso/lib"; import { ArrowDownTrayIcon, CheckBadgeIcon, CheckIcon, EnvelopeIcon, PaperAirplaneIcon, PencilSquareIcon, TrashIcon, UserPlusIcon, } from "@heroicons/react/24/outline"; import { getUserFromToken } from "@documenso/lib/server"; import { getDocument } from "@documenso/lib/query"; import { Document as PrismaDocument } from "@prisma/client"; import { Breadcrumb, Button, IconButton } from "@documenso/ui"; import toast from "react-hot-toast"; import { Dialog, Transition } from "@headlessui/react"; const RecipientsPage: NextPageWithLayout = (props: any) => { const title: string = `"` + props?.document?.title + `"` + "Recipients | Documenso"; const breadcrumbItems = [ { title: "Documents", href: "/documents", }, { title: props.document.title, href: NEXT_PUBLIC_WEBAPP_URL + "/documents/" + props.document.id, }, { title: "Recipients", href: NEXT_PUBLIC_WEBAPP_URL + "/documents/" + props.document.id + "/recipients", }, ]; const [signers, setSigners] = useState(props?.document?.Recipient); const [loading, setLoading] = useState(false); const [open, setOpen] = useState(false); const cancelButtonRef = useRef(null); return ( <> {title}

{props.document.title}

Signers

The people who will sign the document.

Ready to send

{`"${props.document.title}" will be sent to ${ signers.filter((s: any) => s.sendStatus != "SENT") .length } recipients.`}

); }; // todo encapsulate async function deleteRecipient(recipient: any) { if (!recipient.id) { return; } return toast.promise( fetch( "/api/documents/" + recipient.documentId + "/recipients/" + recipient.id, { method: "DELETE", headers: { "Content-Type": "application/json", }, body: JSON.stringify(recipient), } ), { loading: "Deleting...", success: "Deleted.", error: "Could not delete :/", }, { id: "delete", style: { minWidth: "200px", }, } ); } // todo encapsulate async function upsertRecipient(recipient: any): Promise { try { const created = await toast.promise( fetch("/api/documents/" + recipient.documentId + "/recipients", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(recipient), }).then((res) => { if (!res.ok) { throw new Error(res.status.toString()); } return res.json(); }), { loading: "Saving...", success: "Saved.", error: "Could not save :/", }, { id: "saving", style: { minWidth: "200px", }, } ); return created; } catch (error) {} } RecipientsPage.getLayout = function getLayout(page: ReactElement) { return {page}; }; export async function getServerSideProps(context: any) { const user = await getUserFromToken(context.req, context.res); if (!user) return; const { id: documentId } = context.query; const document: PrismaDocument = await getDocument( +documentId, context.req, context.res ); return { props: { document: JSON.parse(JSON.stringify({ ...document, document: "" })), }, }; } // todo encapsulate async function send(document: any, resendTo: number[] = []) { if (!document || !document.id) return; try { const sent = await toast.promise( fetch(`/api/documents/${document.id}/send`, { body: JSON.stringify({ resendTo: resendTo }), headers: { "Content-Type": "application/json" }, method: "POST", }) .then((res: any) => { if (!res.ok) { throw new Error(res.status.toString()); } }) .finally(() => { location.reload(); }), { loading: "Sending...", success: `Sent!`, error: "Could not send :/", } ); } catch (err) { console.log(err); } } export default RecipientsPage;