diff --git a/apps/web/package.json b/apps/web/package.json index 22d4f2189..83230463d 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -36,6 +36,7 @@ "react-dom": "18.2.0", "react-hook-form": "^7.41.5", "react-pdf": "^6.2.2", + "react-tooltip": "^5.7.2", "sass": "^1.57.1", "short-uuid": "^4.2.2", "typescript": "4.8.4" diff --git a/apps/web/pages/_app.tsx b/apps/web/pages/_app.tsx index caddfd592..85504bcaa 100644 --- a/apps/web/pages/_app.tsx +++ b/apps/web/pages/_app.tsx @@ -1,5 +1,6 @@ import "../styles/tailwind.css"; import "../../../node_modules/placeholder-loading/src/scss/placeholder-loading.scss"; +import "react-tooltip/dist/react-tooltip.css"; import { ReactElement, ReactNode } from "react"; import type { AppProps } from "next/app"; import { NextPage } from "next"; diff --git a/apps/web/pages/documents.tsx b/apps/web/pages/documents.tsx index f3224c17a..6b5a9eacb 100644 --- a/apps/web/pages/documents.tsx +++ b/apps/web/pages/documents.tsx @@ -3,11 +3,18 @@ import { ReactElement, useEffect, useState } from "react"; import Layout from "../components/layout"; import type { NextPageWithLayout } from "./_app"; import Head from "next/head"; -import { PlusIcon, TrashIcon } from "@heroicons/react/24/outline"; +import { + CheckBadgeIcon, + EnvelopeIcon, + EyeIcon, + PlusIcon, + TrashIcon, +} from "@heroicons/react/24/outline"; import Link from "next/link"; import { useRouter } from "next/router"; import { uploadDocument } from "@documenso/features"; import { DocumentStatus } from "@prisma/client"; +import { Tooltip as ReactTooltip } from "react-tooltip"; const DocumentsPage: NextPageWithLayout = (req, res) => { const router = useRouter(); @@ -129,13 +136,62 @@ const DocumentsPage: NextPageWithLayout = (req, res) => { {document.title || "#" + document.id} - {document.recipients || "-"} + {document.Recipient.map((item: any) => ( +
+ {item.sendStatus === "SENT" && + item.readStatus !== "OPENED" && + item.signingStatus !== "SIGNED" ? ( + + + {item.email} + + ) : ( + "" + )} + {item.sendStatus === "SENT" && + item.readStatus === "OPENED" ? ( + + {" "} + {item.email} + + ) : ( + "" + )} + {item.sendStatus === "SENT" && + item.readStatus === "OPENED" && + item.signingStatus === "SIGNED" ? ( + + {" "} + {item.email} + + ) : ( + "" + )} +
+ ))} + {document.Recipient.length === 0 ? "-" : null} + + + {formatDocumentStatus(document.status)}

- {document.recipients || 0}/{document.signed || 0} + {document.signed || 0}/ + {document.Recipient.length || 0}

diff --git a/apps/web/pages/documents/[id]/index.tsx b/apps/web/pages/documents/[id]/index.tsx index 3bdb71e24..69a466bf8 100644 --- a/apps/web/pages/documents/[id]/index.tsx +++ b/apps/web/pages/documents/[id]/index.tsx @@ -5,23 +5,69 @@ import { Document, Page, pdfjs } from "react-pdf"; import dynamic from "next/dynamic"; import { useRouter } from "next/router"; import { NEXT_PUBLIC_WEBAPP_URL } from "@documenso/lib"; +import prisma from "@documenso/prisma"; +import { getUserFromToken } from "@documenso/lib/server"; +import Logo from "../../../components/logo"; +import Link from "next/link"; const PDFViewer = dynamic(() => import("../../../components/pdf-viewer"), { ssr: false, }); -const DocumentsDetailPage: NextPageWithLayout = () => { +const DocumentsDetailPage: NextPageWithLayout = (props: any) => { const router = useRouter(); return ( -
- +
+
+
+

+ {props.document.title} +

+ + Add Signers + +
+
+
+ +
); }; +export async function getServerSideProps(context: any) { + const user = await getUserFromToken(context.req, context.res); + if (!user) return; + + const { id: documentId } = context.query; + const document = await prisma.document.findFirstOrThrow({ + where: { + id: +documentId, + }, + }); + + // todo optimize querys + // todo no intersection groups + + return { + props: { + document: document, + }, + }; +} + DocumentsDetailPage.getLayout = function getLayout(page: ReactElement) { return {page}; }; diff --git a/apps/web/pages/documents/[id]/recipients.tsx b/apps/web/pages/documents/[id]/recipients.tsx new file mode 100644 index 000000000..ed8e50f97 --- /dev/null +++ b/apps/web/pages/documents/[id]/recipients.tsx @@ -0,0 +1,48 @@ +import prisma from "@documenso/prisma"; +import Head from "next/head"; +import { ReactElement } from "react"; +import Layout from "../../../components/layout"; +import { NextPageWithLayout } from "../../_app"; +import { Fragment } from "react"; +import { Menu, Transition } from "@headlessui/react"; +import { + ArchiveBoxIcon, + ArrowRightCircleIcon, + ChevronDownIcon, + DocumentDuplicateIcon, + HeartIcon, + PencilSquareIcon, + TrashIcon, + UserPlusIcon, +} from "@heroicons/react/20/solid"; +import { classNames } from "@documenso/lib"; +import { + UserGroupIcon, + UserIcon, + UsersIcon, +} from "@heroicons/react/24/outline"; + +const RecipientsPage: NextPageWithLayout = () => { + return ( + <> + + Documenttitle - Recipients | Documenso + + -todo add signers ui -todo add breadcrumps -todo who will sign this + dropdown + + ); +}; + +RecipientsPage.getLayout = function getLayout(page: ReactElement) { + return {page}; +}; + +export async function getServerSideProps(context: any) { + // todo get current document + return { + props: {}, + }; +} + +export default RecipientsPage; diff --git a/package-lock.json b/package-lock.json index 7067174a9..594823866 100644 --- a/package-lock.json +++ b/package-lock.json @@ -69,6 +69,7 @@ "react-dom": "18.2.0", "react-hook-form": "^7.41.5", "react-pdf": "^6.2.2", + "react-tooltip": "^5.7.2", "sass": "^1.57.1", "short-uuid": "^4.2.2", "typescript": "4.8.4" @@ -183,6 +184,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@floating-ui/core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.1.1.tgz", + "integrity": "sha512-PL7g3dhA4dHgZfujkuD8Q+tfJJynEtnNQSPzmucCnxMvkxf4cLBJw/ZYqZUn4HCh33U3WHrAfv2R2tbi9UCSmw==" + }, + "node_modules/@floating-ui/dom": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.1.tgz", + "integrity": "sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==", + "dependencies": { + "@floating-ui/core": "^1.1.0" + } + }, "node_modules/@headlessui/react": { "version": "1.7.7", "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.7.tgz", @@ -1636,6 +1650,11 @@ "node": ">=6.0" } }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -7175,6 +7194,19 @@ } } }, + "node_modules/react-tooltip": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.7.2.tgz", + "integrity": "sha512-Lv6SCgDCejnjs8EKEFW0f+5V0KXbgZYAQvbhMNleF2AJfcXsLn1EbL9XeCoCDeMziHCaC/HxOBnsw+xbMmZ3Og==", + "dependencies": { + "@floating-ui/dom": "^1.0.4", + "classnames": "^2.3.2" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -8482,6 +8514,7 @@ "react-dom": "18.2.0", "react-hook-form": "^7.41.5", "react-pdf": "^6.2.2", + "react-tooltip": "*", "sass": "^1.57.1", "short-uuid": "^4.2.2", "tailwindcss": "^3.2.4", @@ -8523,6 +8556,19 @@ "strip-json-comments": "^3.1.1" } }, + "@floating-ui/core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.1.1.tgz", + "integrity": "sha512-PL7g3dhA4dHgZfujkuD8Q+tfJJynEtnNQSPzmucCnxMvkxf4cLBJw/ZYqZUn4HCh33U3WHrAfv2R2tbi9UCSmw==" + }, + "@floating-ui/dom": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.1.tgz", + "integrity": "sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==", + "requires": { + "@floating-ui/core": "^1.1.0" + } + }, "@headlessui/react": { "version": "1.7.7", "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.7.tgz", @@ -9578,6 +9624,11 @@ "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "peer": true }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -13362,6 +13413,15 @@ "tiny-warning": "^1.0.0" } }, + "react-tooltip": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.7.2.tgz", + "integrity": "sha512-Lv6SCgDCejnjs8EKEFW0f+5V0KXbgZYAQvbhMNleF2AJfcXsLn1EbL9XeCoCDeMziHCaC/HxOBnsw+xbMmZ3Og==", + "requires": { + "@floating-ui/dom": "^1.0.4", + "classnames": "^2.3.2" + } + }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",