diff --git a/apps/web/src/app/(dashboard)/documents/documents-page-view.tsx b/apps/web/src/app/(dashboard)/documents/documents-page-view.tsx index 3420fc0be..8decdf128 100644 --- a/apps/web/src/app/(dashboard)/documents/documents-page-view.tsx +++ b/apps/web/src/app/(dashboard)/documents/documents-page-view.tsx @@ -115,6 +115,7 @@ export const DocumentsPageView = async ({ searchParams = {}, team }: DocumentsPa ExtendedDocumentStatus.PENDING, ExtendedDocumentStatus.COMPLETED, ExtendedDocumentStatus.DRAFT, + ExtendedDocumentStatus.BIN, ExtendedDocumentStatus.ALL, ].map((value) => ( { 'You have not yet created or received any documents. To create a document please upload one.', icon: Bird, })) + .with(ExtendedDocumentStatus.BIN, () => ({ + title: 'No documents in the bin', + message: "There are no documents in the bin. You can't restore any documents.", + icon: Trash, + })) .otherwise(() => ({ title: 'Nothing to do', message: diff --git a/apps/web/src/components/formatter/document-status.tsx b/apps/web/src/components/formatter/document-status.tsx index f8a8ef98b..5264bcfeb 100644 --- a/apps/web/src/components/formatter/document-status.tsx +++ b/apps/web/src/components/formatter/document-status.tsx @@ -1,6 +1,6 @@ import type { HTMLAttributes } from 'react'; -import { CheckCircle2, Clock, File } from 'lucide-react'; +import { CheckCircle2, Clock, File, TrashIcon } from 'lucide-react'; import type { LucideIcon } from 'lucide-react/dist/lucide-react'; import type { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status'; @@ -38,6 +38,11 @@ export const FRIENDLY_STATUS_MAP: Record label: 'All', color: 'text-muted-foreground', }, + BIN: { + label: 'Bin', + icon: TrashIcon, + color: 'text-red-500 dark:text-red-200', + }, }; export type DocumentStatusProps = HTMLAttributes & { diff --git a/packages/lib/server-only/document/find-documents.ts b/packages/lib/server-only/document/find-documents.ts index c8b06236b..91ff0ae08 100644 --- a/packages/lib/server-only/document/find-documents.ts +++ b/packages/lib/server-only/document/find-documents.ts @@ -94,57 +94,61 @@ export const findDocuments = async ({ }; } - let deletedFilter: Prisma.DocumentWhereInput = { - AND: { - OR: [ - { - userId: user.id, - deletedAt: null, - }, - { - Recipient: { - some: { - email: user.email, - documentDeletedAt: null, - }, - }, - }, - ], - }, - }; + let deletedFilter: Prisma.DocumentWhereInput | undefined; - if (team) { + if (status !== ExtendedDocumentStatus.BIN) { deletedFilter = { AND: { - OR: team.teamEmail - ? [ - { - teamId: team.id, - deletedAt: null, + OR: [ + { + userId: user.id, + deletedAt: null, + }, + { + Recipient: { + some: { + email: user.email, + documentDeletedAt: null, }, - { - User: { - email: team.teamEmail.email, - }, - deletedAt: null, - }, - { - Recipient: { - some: { - email: team.teamEmail.email, - documentDeletedAt: null, - }, - }, - }, - ] - : [ - { - teamId: team.id, - deletedAt: null, - }, - ], + }, + }, + ], }, }; + + if (team) { + deletedFilter = { + AND: { + OR: team.teamEmail + ? [ + { + teamId: team.id, + deletedAt: null, + }, + { + User: { + email: team.teamEmail.email, + }, + deletedAt: null, + }, + { + Recipient: { + some: { + email: team.teamEmail.email, + documentDeletedAt: null, + }, + }, + }, + ] + : [ + { + teamId: team.id, + deletedAt: null, + }, + ], + }, + }; + } } const whereClause: Prisma.DocumentWhereInput = { @@ -298,6 +302,29 @@ const findDocumentsFilter = (status: ExtendedDocumentStatus, user: User) => { }, ], })) + .with(ExtendedDocumentStatus.BIN, () => ({ + OR: [ + { + userId: user.id, + teamId: null, + status: ExtendedDocumentStatus.COMPLETED, + deletedAt: { + gte: DateTime.now().minus({ days: 30 }).startOf('day').toJSDate(), + }, + }, + { + status: ExtendedDocumentStatus.COMPLETED, + Recipient: { + some: { + email: user.email, + documentDeletedAt: { + gte: DateTime.now().minus({ days: 30 }).startOf('day').toJSDate(), + }, + }, + }, + }, + ], + })) .exhaustive(); }; @@ -477,5 +504,43 @@ const findTeamDocumentsFilter = ( return filter; }) + .with(ExtendedDocumentStatus.BIN, () => { + const filter: Prisma.DocumentWhereInput = { + OR: [ + { + teamId: team.id, + deletedAt: { + gte: DateTime.now().minus({ days: 30 }).startOf('day').toJSDate(), + }, + }, + ], + }; + + if (teamEmail && filter.OR) { + filter.OR.push( + { + User: { + email: teamEmail, + }, + deletedAt: { + gte: DateTime.now().minus({ days: 30 }).startOf('day').toJSDate(), + }, + }, + { + Recipient: { + some: { + email: teamEmail, + documentDeletedAt: { + gte: DateTime.now().minus({ days: 30 }).startOf('day').toJSDate(), + }, + }, + }, + }, + ); + } + + return filter; + }) + .exhaustive(); }; diff --git a/packages/lib/server-only/document/get-stats.ts b/packages/lib/server-only/document/get-stats.ts index 1afdbcbf2..326807649 100644 --- a/packages/lib/server-only/document/get-stats.ts +++ b/packages/lib/server-only/document/get-stats.ts @@ -36,6 +36,7 @@ export const getStats = async ({ user, period, ...options }: GetStatsInput) => { [ExtendedDocumentStatus.COMPLETED]: 0, [ExtendedDocumentStatus.INBOX]: 0, [ExtendedDocumentStatus.ALL]: 0, + [ExtendedDocumentStatus.BIN]: 0, }; ownerCounts.forEach((stat) => { diff --git a/packages/prisma/types/extended-document-status.ts b/packages/prisma/types/extended-document-status.ts index a3576750d..4089dd2d9 100644 --- a/packages/prisma/types/extended-document-status.ts +++ b/packages/prisma/types/extended-document-status.ts @@ -4,6 +4,7 @@ export const ExtendedDocumentStatus = { ...DocumentStatus, INBOX: 'INBOX', ALL: 'ALL', + BIN: 'BIN', } as const; export type ExtendedDocumentStatus =