import Link from 'next/link'; import { redirect } from 'next/navigation'; import { ChevronLeft, Clock9, Users2 } from 'lucide-react'; import { match } from 'ts-pattern'; import { DOCUMENSO_ENCRYPTION_KEY } from '@documenso/lib/constants/crypto'; import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session'; import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id'; import { getServerComponentFlag } from '@documenso/lib/server-only/feature-flags/get-server-component-feature-flag'; import { getRecipientsForDocument } from '@documenso/lib/server-only/recipient/get-recipients-for-document'; import { symmetricDecrypt } from '@documenso/lib/universal/crypto'; import { formatDocumentsPath } from '@documenso/lib/utils/teams'; import { DocumentStatus } from '@documenso/prisma/client'; import type { Team } from '@documenso/prisma/client'; import { Button } from '@documenso/ui/primitives/button'; import { Card, CardContent } from '@documenso/ui/primitives/card'; import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { StackAvatarsWithTooltip } from '~/components/(dashboard)/avatar/stack-avatars-with-tooltip'; import { DocumentHistorySheet } from '~/components/document/document-history-sheet'; import { DocumentStatus as DocumentStatusComponent, FRIENDLY_STATUS_MAP, } from '~/components/formatter/document-status'; import { DocumentPageViewButton } from './document-page-view-button'; import { DocumentPageViewDropdown } from './document-page-view-dropdown'; import { DocumentPageViewInformation } from './document-page-view-information'; import { DocumentPageViewRecentActivity } from './document-page-view-recent-activity'; import { DocumentPageViewRecipients } from './document-page-view-recipients'; export type DocumentPageViewProps = { params: { id: string; }; team?: Team; }; export const DocumentPageView = async ({ params, team }: DocumentPageViewProps) => { const { id } = params; const documentId = Number(id); const documentRootPath = formatDocumentsPath(team?.url); if (!documentId || Number.isNaN(documentId)) { redirect(documentRootPath); } const { user } = await getRequiredServerComponentSession(); const document = await getDocumentById({ id: documentId, userId: user.id, teamId: team?.id, }).catch(() => null); const isDocumentHistoryEnabled = await getServerComponentFlag( 'app_document_page_view_history_sheet', ); if (!document || !document.documentData) { redirect(documentRootPath); } const { documentData, documentMeta } = document; if (documentMeta?.password) { const key = DOCUMENSO_ENCRYPTION_KEY; if (!key) { throw new Error('Missing DOCUMENSO_ENCRYPTION_KEY'); } const securePassword = Buffer.from( symmetricDecrypt({ key, data: documentMeta.password, }), ).toString('utf-8'); documentMeta.password = securePassword; } const recipients = await getRecipientsForDocument({ documentId, teamId: team?.id, userId: user.id, }); const documentWithRecipients = { ...document, Recipient: recipients, }; return (
{match(document.status) .with( DocumentStatus.COMPLETED, () => 'This document has been signed by all recipients', ) .with( DocumentStatus.DRAFT, () => 'This document is currently a draft and has not been sent', ) .with(DocumentStatus.PENDING, () => { const pendingRecipients = recipients.filter( (recipient) => recipient.signingStatus === 'NOT_SIGNED', ); return `Waiting on ${pendingRecipients.length} recipient${ pendingRecipients.length > 1 ? 's' : '' }`; }) .exhaustive()}