diff --git a/apps/web/src/app/(dashboard)/dashboard/page.tsx b/apps/web/src/app/(dashboard)/dashboard/page.tsx
index a9d650eb6..8e242b2fd 100644
--- a/apps/web/src/app/(dashboard)/dashboard/page.tsx
+++ b/apps/web/src/app/(dashboard)/dashboard/page.tsx
@@ -22,14 +22,14 @@ import { LocaleDate } from '~/components/formatter/locale-date';
import { UploadDocument } from './upload-document';
export default async function DashboardPage() {
- const session = await getRequiredServerComponentSession();
+ const user = await getRequiredServerComponentSession();
const [stats, results] = await Promise.all([
getStats({
- userId: session.id,
+ user,
}),
findDocuments({
- userId: session.id,
+ userId: user.id,
perPage: 10,
}),
]);
diff --git a/apps/web/src/app/(dashboard)/inbox/page.tsx b/apps/web/src/app/(dashboard)/inbox/page.tsx
deleted file mode 100644
index badb421c9..000000000
--- a/apps/web/src/app/(dashboard)/inbox/page.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import Inbox from '~/components/(dashboard)/inbox/inbox';
-
-export default function InboxPage() {
- return (
-
-
Inbox
-
Documents which you have been requested to sign.
-
-
-
-
-
- );
-}
diff --git a/apps/web/src/components/(dashboard)/inbox/inbox-content.tsx b/apps/web/src/components/(dashboard)/inbox/inbox-content.tsx
deleted file mode 100644
index f7e263f1f..000000000
--- a/apps/web/src/components/(dashboard)/inbox/inbox-content.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import { TemplateDocumentCompleted } from '@documenso/email/template-components/template-document-completed';
-import { TemplateDocumentInvite } from '@documenso/email/template-components/template-document-invite';
-import { DocumentWithRecipientAndSender } from '@documenso/prisma/types/document';
-import { cn } from '@documenso/ui/lib/utils';
-
-import { formatInboxDate } from './inbox.utils';
-
-export type InboxContentProps = {
- document: DocumentWithRecipientAndSender;
-};
-
-export default function InboxContent({ document }: InboxContentProps) {
- const inboxDocumentStatusIndicator = (
-
-
-
- {document.recipient.signingStatus === 'SIGNED' ? 'Signed' : 'Pending'}
-
- );
-
- return (
-
-
-
-
{document.subject}
-
- {document.sender.name} <{document.sender.email}>
-
-
-
-
- {/* Todo: This needs to be updated to when the document was sent to the recipient when that value is available. */}
-
{formatInboxDate(document.created)}
-
- {inboxDocumentStatusIndicator}
-
-
-
-
- {inboxDocumentStatusIndicator}
-
-
- {/* Todo: get correct URLs */}
-
- {document.recipient.signingStatus === 'NOT_SIGNED' && (
-
- )}
-
- {document.recipient.signingStatus === 'SIGNED' && (
-
- )}
-
-
- );
-}
diff --git a/apps/web/src/components/(dashboard)/inbox/inbox.actions.ts b/apps/web/src/components/(dashboard)/inbox/inbox.actions.ts
deleted file mode 100644
index 38b50a8b3..000000000
--- a/apps/web/src/components/(dashboard)/inbox/inbox.actions.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-'use server';
-
-import { z } from 'zod';
-
-import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-session';
-import { prisma } from '@documenso/prisma';
-
-export async function updateRecipientReadStatus(recipientId: number, documentId: number) {
- z.number().parse(recipientId);
- z.number().parse(documentId);
-
- const { email } = await getRequiredServerComponentSession();
-
- await prisma.recipient.update({
- where: {
- id: recipientId,
- documentId,
- email,
- },
- data: {
- readStatus: 'OPENED',
- },
- });
-}
diff --git a/apps/web/src/components/(dashboard)/inbox/inbox.tsx b/apps/web/src/components/(dashboard)/inbox/inbox.tsx
deleted file mode 100644
index c76ba3d94..000000000
--- a/apps/web/src/components/(dashboard)/inbox/inbox.tsx
+++ /dev/null
@@ -1,352 +0,0 @@
-'use client';
-
-import { useEffect, useState } from 'react';
-
-import { usePathname, useRouter, useSearchParams } from 'next/navigation';
-
-import { Inbox as InboxIcon } from 'lucide-react';
-import { z } from 'zod';
-
-import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
-import { SigningStatus } from '@documenso/prisma/client';
-import { DocumentWithRecipientAndSender } from '@documenso/prisma/types/document';
-import { trpc } from '@documenso/trpc/react';
-import { cn } from '@documenso/ui/lib/utils';
-import { Input } from '@documenso/ui/primitives/input';
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from '@documenso/ui/primitives/select';
-import { Skeleton } from '@documenso/ui/primitives/skeleton';
-
-import { useDebouncedValue } from '~/hooks/use-debounced-value';
-
-import InboxContent from './inbox-content';
-import { updateRecipientReadStatus } from './inbox.actions';
-import { formatInboxDate } from './inbox.utils';
-
-export const ZInboxSearchParamsSchema = z.object({
- filter: z
- .union([z.literal('SIGNED'), z.literal('NOT_SIGNED'), z.undefined()])
- .catch(() => undefined),
- id: z
- .string()
- .optional()
- .catch(() => undefined),
- query: z
- .string()
- .optional()
- .catch(() => undefined),
-});
-
-export type InboxProps = {
- className?: string;
-};
-
-const numberOfSkeletons = 3;
-
-export default function Inbox(props: InboxProps) {
- const { className } = props;
-
- const pathname = usePathname();
- const searchParams = useSearchParams();
- const router = useRouter();
- const updateSearchParams = useUpdateSearchParams();
-
- const parsedSearchParams = ZInboxSearchParamsSchema.parse(Object.fromEntries(searchParams ?? []));
-
- const [searchQuery, setSearchQuery] = useState(() => parsedSearchParams.query || '');
-
- const [readStatusState, setReadStatusState] = useState<{
- [documentId: string]: 'ERROR' | 'UPDATED' | 'UPDATING';
- }>({});
-
- const [isInitialLoad, setIsInitialLoad] = useState(true);
-
- const debouncedSearchQuery = useDebouncedValue(searchQuery, 500);
-
- const {
- data,
- error,
- fetchNextPage,
- fetchPreviousPage,
- hasNextPage,
- hasPreviousPage,
- isFetching,
- isFetchingNextPage,
- isFetchingPreviousPage,
- refetch,
- } = trpc.document.searchInboxDocuments.useInfiniteQuery(
- {
- query: parsedSearchParams.query,
- filter: parsedSearchParams.filter,
- },
- {
- getPreviousPageParam: (firstPage) =>
- firstPage.currentPage > 1 ? firstPage.currentPage - 1 : undefined,
- getNextPageParam: (lastPage) =>
- lastPage.currentPage < lastPage.totalPages ? lastPage.currentPage + 1 : undefined,
- },
- );
-
- /**
- * The current documents in the inbox after filters and queries have been applied.
- */
- const inboxDocuments = (data?.pages ?? []).flatMap((page) => page.data);
-
- /**
- * The currently selected document in the inbox.
- */
- const selectedDocument: DocumentWithRecipientAndSender | null =
- inboxDocuments.find((item) => item.id.toString() === parsedSearchParams.id) ?? null;
-
- /**
- * Remove the ID from the query if it is not found in the result.
- */
- useEffect(() => {
- if (!selectedDocument && parsedSearchParams.id && data) {
- updateSearchParams({
- id: null,
- });
- }
- }, [data, selectedDocument, parsedSearchParams.id]);
-
- /**
- * Handle debouncing the seach query.
- */
- useEffect(() => {
- if (!pathname) {
- return;
- }
-
- const params = new URLSearchParams(searchParams?.toString());
-
- params.set('query', debouncedSearchQuery);
-
- if (debouncedSearchQuery === '') {
- params.delete('query');
- }
-
- router.push(`${pathname}?${params.toString()}`);
- }, [debouncedSearchQuery]);
-
- useEffect(() => {
- if (!isFetching) {
- setIsInitialLoad(false);
- }
- }, [isFetching]);
-
- const updateReadStatusState = (documentId: number, value: (typeof readStatusState)[string]) => {
- setReadStatusState({
- ...readStatusState,
- [documentId]: value,
- });
- };
-
- /**
- * Handle selecting the selected document to display and updating the read status if required.
- */
- const onSelectedDocumentChange = (value: DocumentWithRecipientAndSender) => {
- if (!pathname) {
- return;
- }
-
- // Update the read status.
- if (
- value.recipient.readStatus === 'NOT_OPENED' &&
- readStatusState[value.id] !== 'UPDATED' &&
- readStatusState[value.id] !== 'UPDATING'
- ) {
- updateReadStatusState(value.id, 'UPDATING');
-
- updateRecipientReadStatus(value.recipient.id, value.id)
- .then(() => {
- updateReadStatusState(value.id, 'UPDATED');
- })
- .catch(() => {
- updateReadStatusState(value.id, 'ERROR');
- });
- }
-
- const params = new URLSearchParams(searchParams?.toString());
-
- params.set('id', value.id.toString());
-
- router.push(`${pathname}?${params.toString()}`);
- };
-
- if (error) {
- return (
-
- Something went wrong while loading your inbox.
-
-
- );
- }
-
- return (
-
-
- {/* Header with search and filter options. */}
-
-
setSearchQuery(e.target.value)}
- />
-
-
-
-
-
-
-
- {/* Handle rendering no items found. */}
- {!isFetching && inboxDocuments.length === 0 && (
-
- )}
-
- {hasPreviousPage && !isFetchingPreviousPage && (
-
- )}
-
-
- {/* Handle rendering skeleton on first load. */}
- {isFetching &&
- isInitialLoad &&
- !data &&
- Array.from({ length: numberOfSkeletons }).map((_, i) => (
- -
-
-
-
-
- ))}
-
- {/* Handle rendering list of inbox documents. */}
- {inboxDocuments.map((item, i) => (
- -
-
-
- {/* Mobile inbox content. */}
- {selectedDocument?.id === item.id && (
-
-
-
- )}
-
- ))}
-
-
- {hasNextPage && !isFetchingNextPage && (
-
- )}
-
-
-
- {/* Desktop inbox content. */}
-
- {selectedDocument ? (
-
- ) : (
-
-
-
- )}
-
-
- );
-}
diff --git a/apps/web/src/components/(dashboard)/inbox/inbox.utils.ts b/apps/web/src/components/(dashboard)/inbox/inbox.utils.ts
deleted file mode 100644
index 9a6aff9f3..000000000
--- a/apps/web/src/components/(dashboard)/inbox/inbox.utils.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { DateTime } from 'luxon';
-
-/**
- * Format the provided date into a readable string for inboxes.
- *
- * @param dateValue The date or date string
- * @returns The date in the current locale, or the date formatted as HH:MM AM/PM if the provided date is after 12:00AM of the current date
- */
-export const formatInboxDate = (dateValue: string | Date): string => {
- const date =
- typeof dateValue === 'string' ? DateTime.fromISO(dateValue) : DateTime.fromJSDate(dateValue);
-
- const startOfTheDay = DateTime.now().startOf('day');
-
- if (date >= startOfTheDay) {
- return date.toFormat('h:mma');
- }
-
- return date.toLocaleString({
- ...DateTime.DATE_SHORT,
- year: '2-digit',
- });
-};
diff --git a/apps/web/src/components/(dashboard)/layout/desktop-nav.tsx b/apps/web/src/components/(dashboard)/layout/desktop-nav.tsx
index 6d0e629b4..2c6165a05 100644
--- a/apps/web/src/components/(dashboard)/layout/desktop-nav.tsx
+++ b/apps/web/src/components/(dashboard)/layout/desktop-nav.tsx
@@ -2,19 +2,17 @@
import { HTMLAttributes } from 'react';
-import Link from 'next/link';
-import { usePathname } from 'next/navigation';
-
import { cn } from '@documenso/ui/lib/utils';
export type DesktopNavProps = HTMLAttributes;
export const DesktopNav = ({ className, ...props }: DesktopNavProps) => {
- const pathname = usePathname();
+ // const pathname = usePathname();
return (
- {
)}
>
Documents
-
-
-
- Inbox
-
+ */}
);
};
diff --git a/apps/web/src/components/(dashboard)/layout/header.tsx b/apps/web/src/components/(dashboard)/layout/header.tsx
index c10fa9e5e..88dc5d7a4 100644
--- a/apps/web/src/components/(dashboard)/layout/header.tsx
+++ b/apps/web/src/components/(dashboard)/layout/header.tsx
@@ -4,11 +4,8 @@ import { HTMLAttributes } from 'react';
import Link from 'next/link';
-import { Menu } from 'lucide-react';
-
import { User } from '@documenso/prisma/client';
import { cn } from '@documenso/ui/lib/utils';
-import { Button } from '@documenso/ui/primitives/button';
import { Logo } from '~/components/branding/logo';
@@ -23,7 +20,7 @@ export const Header = ({ className, user, ...props }: HeaderProps) => {
return (
diff --git a/packages/lib/server-only/document/find-documents.ts b/packages/lib/server-only/document/find-documents.ts
index 5a2d695ae..c9c8eaf6c 100644
--- a/packages/lib/server-only/document/find-documents.ts
+++ b/packages/lib/server-only/document/find-documents.ts
@@ -2,7 +2,6 @@ import { match } from 'ts-pattern';
import { prisma } from '@documenso/prisma';
import { Document, Prisma, SigningStatus } from '@documenso/prisma/client';
-import { DocumentWithRecipientAndSender } from '@documenso/prisma/types/document';
import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status';
import { FindResultSet } from '../../types/find-result-set';
@@ -160,111 +159,3 @@ export const findDocuments = async ({
totalPages: Math.ceil(count / perPage),
} satisfies FindResultSet;
};
-
-export interface FindDocumentsWithRecipientAndSenderOptions {
- email: string;
- query?: string;
- signingStatus?: SigningStatus;
- page?: number;
- perPage?: number;
- orderBy?: {
- column: keyof Omit;
- direction: 'asc' | 'desc';
- };
-}
-
-export const findDocumentsWithRecipientAndSender = async ({
- email,
- query,
- signingStatus,
- page = 1,
- perPage = 20,
- orderBy,
-}: FindDocumentsWithRecipientAndSenderOptions): Promise<
- FindResultSet
-> => {
- const orderByColumn = orderBy?.column ?? 'created';
- const orderByDirection = orderBy?.direction ?? 'desc';
-
- const filters: Prisma.DocumentWhereInput = {
- Recipient: {
- some: {
- email,
- signingStatus,
- },
- },
- };
-
- if (query) {
- filters.OR = [
- {
- User: {
- email: {
- contains: query,
- mode: 'insensitive',
- },
- },
- // Todo: Add filter for `Subject`.
- },
- ];
- }
-
- const [data, count] = await Promise.all([
- prisma.document.findMany({
- select: {
- id: true,
- created: true,
- title: true,
- status: true,
- userId: true,
- User: {
- select: {
- id: true,
- name: true,
- email: true,
- },
- },
- Recipient: {
- where: {
- email,
- signingStatus,
- },
- },
- },
- where: {
- ...filters,
- },
- skip: Math.max(page - 1, 0) * perPage,
- take: perPage,
- orderBy: {
- [orderByColumn]: orderByDirection,
- },
- }),
- prisma.document.count({
- where: {
- ...filters,
- },
- }),
- ]);
-
- return {
- data: data.map((item) => {
- const { User, Recipient, ...rest } = item;
-
- const subject = undefined; // Todo.
- const description = undefined; // Todo.
-
- return {
- ...rest,
- sender: User,
- recipient: Recipient[0],
- subject: subject ?? 'Please sign this document',
- description: description ?? `${User.name} has invited you to sign "${item.title}"`,
- };
- }),
- count,
- currentPage: Math.max(page, 1),
- perPage,
- totalPages: Math.ceil(count / perPage),
- };
-};
diff --git a/packages/trpc/server/document-router/router.ts b/packages/trpc/server/document-router/router.ts
index 1f790dc24..f20643327 100644
--- a/packages/trpc/server/document-router/router.ts
+++ b/packages/trpc/server/document-router/router.ts
@@ -1,45 +1,17 @@
import { TRPCError } from '@trpc/server';
-import { findDocumentsWithRecipientAndSender } from '@documenso/lib/server-only/document/find-documents';
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
import { setFieldsForDocument } from '@documenso/lib/server-only/field/set-fields-for-document';
import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document';
import { authenticatedProcedure, router } from '../trpc';
import {
- ZSearchInboxDocumentsParamsSchema,
ZSendDocumentMutationSchema,
ZSetFieldsForDocumentMutationSchema,
ZSetRecipientsForDocumentMutationSchema,
} from './schema';
export const documentRouter = router({
- searchInboxDocuments: authenticatedProcedure
- .input(ZSearchInboxDocumentsParamsSchema)
- .query(async ({ input, ctx }) => {
- try {
- const { filter, query, cursor: page } = input;
-
- return await findDocumentsWithRecipientAndSender({
- email: ctx.session.email,
- query,
- signingStatus: filter,
- orderBy: {
- column: 'created',
- direction: 'desc',
- },
- page,
- });
- } catch (err) {
- console.error(err);
-
- throw new TRPCError({
- code: 'BAD_REQUEST',
- message: 'Something went wrong. Please try again later.',
- });
- }
- }),
-
setRecipientsForDocument: authenticatedProcedure
.input(ZSetRecipientsForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {