From 9bfaa08d3829364c5073ad9a590983e6e7bc6442 Mon Sep 17 00:00:00 2001
From: Ephraim Duncan <55143799+ephraimduncan@users.noreply.github.com>
Date: Tue, 7 Apr 2026 20:10:38 +0000
Subject: [PATCH] fix: documents table team email recipient lookup (#2578)
---
.../tables/documents-table-action-button.tsx | 7 ++++++-
.../tables/documents-table-action-dropdown.tsx | 7 ++++++-
.../tables/documents-table-title.tsx | 10 +++++++++-
.../app/components/tables/documents-table.tsx | 18 +++++++++++++++---
.../routes/embed+/v2+/authoring+/_layout.tsx | 1 +
packages/lib/utils/recipients.ts | 10 ++++++++++
.../get-organisation-session.ts | 1 +
.../get-organisation-session.types.ts | 2 ++
8 files changed, 50 insertions(+), 6 deletions(-)
diff --git a/apps/remix/app/components/tables/documents-table-action-button.tsx b/apps/remix/app/components/tables/documents-table-action-button.tsx
index 237524c76..506c6afa0 100644
--- a/apps/remix/app/components/tables/documents-table-action-button.tsx
+++ b/apps/remix/app/components/tables/documents-table-action-button.tsx
@@ -7,6 +7,7 @@ import { match } from 'ts-pattern';
import { useSession } from '@documenso/lib/client-only/providers/session';
import type { TDocumentMany as TDocumentRow } from '@documenso/lib/types/document';
import { isDocumentCompleted } from '@documenso/lib/utils/document';
+import { findRecipientByEmail } from '@documenso/lib/utils/recipients';
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
import { Button } from '@documenso/ui/primitives/button';
@@ -23,7 +24,11 @@ export const DocumentsTableActionButton = ({ row }: DocumentsTableActionButtonPr
const team = useCurrentTeam();
- const recipient = row.recipients.find((recipient) => recipient.email === user.email);
+ const recipient = findRecipientByEmail({
+ recipients: row.recipients,
+ userEmail: user.email,
+ teamEmail: team.teamEmail?.email,
+ });
const isOwner = row.user.id === user.id;
const isRecipient = !!recipient;
diff --git a/apps/remix/app/components/tables/documents-table-action-dropdown.tsx b/apps/remix/app/components/tables/documents-table-action-dropdown.tsx
index da500a615..295f6bba2 100644
--- a/apps/remix/app/components/tables/documents-table-action-dropdown.tsx
+++ b/apps/remix/app/components/tables/documents-table-action-dropdown.tsx
@@ -24,6 +24,7 @@ import { useSession } from '@documenso/lib/client-only/providers/session';
import type { TDocumentMany as TDocumentRow } from '@documenso/lib/types/document';
import { isDocumentCompleted } from '@documenso/lib/utils/document';
import { getEnvelopeItemPermissions } from '@documenso/lib/utils/envelope';
+import { findRecipientByEmail } from '@documenso/lib/utils/recipients';
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
import { trpc as trpcReact } from '@documenso/trpc/react';
import { DocumentShareButton } from '@documenso/ui/components/document/document-share-button';
@@ -64,7 +65,11 @@ export const DocumentsTableActionDropdown = ({
const [isDuplicateDialogOpen, setDuplicateDialogOpen] = useState(false);
const [isRenameDialogOpen, setRenameDialogOpen] = useState(false);
- const recipient = row.recipients.find((recipient) => recipient.email === user.email);
+ const recipient = findRecipientByEmail({
+ recipients: row.recipients,
+ userEmail: user.email,
+ teamEmail: team.teamEmail?.email,
+ });
const isOwner = row.user.id === user.id;
// const isRecipient = !!recipient;
diff --git a/apps/remix/app/components/tables/documents-table-title.tsx b/apps/remix/app/components/tables/documents-table-title.tsx
index 42ea9983e..914a59625 100644
--- a/apps/remix/app/components/tables/documents-table-title.tsx
+++ b/apps/remix/app/components/tables/documents-table-title.tsx
@@ -3,8 +3,11 @@ import { match } from 'ts-pattern';
import { useSession } from '@documenso/lib/client-only/providers/session';
import type { TDocumentMany as TDocumentRow } from '@documenso/lib/types/document';
+import { findRecipientByEmail } from '@documenso/lib/utils/recipients';
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
+import { useCurrentTeam } from '~/providers/team';
+
export type DataTableTitleProps = {
row: TDocumentRow;
teamUrl: string;
@@ -12,8 +15,13 @@ export type DataTableTitleProps = {
export const DataTableTitle = ({ row, teamUrl }: DataTableTitleProps) => {
const { user } = useSession();
+ const team = useCurrentTeam();
- const recipient = row.recipients.find((recipient) => recipient.email === user.email);
+ const recipient = findRecipientByEmail({
+ recipients: row.recipients,
+ userEmail: user.email,
+ teamEmail: team.teamEmail?.email,
+ });
const isOwner = row.user.id === user.id;
const isRecipient = !!recipient;
diff --git a/apps/remix/app/components/tables/documents-table.tsx b/apps/remix/app/components/tables/documents-table.tsx
index a9da6ac2d..7f1d104dd 100644
--- a/apps/remix/app/components/tables/documents-table.tsx
+++ b/apps/remix/app/components/tables/documents-table.tsx
@@ -10,6 +10,7 @@ import { match } from 'ts-pattern';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { useSession } from '@documenso/lib/client-only/providers/session';
import { isDocumentCompleted } from '@documenso/lib/utils/document';
+import { findRecipientByEmail } from '@documenso/lib/utils/recipients';
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
import type { TFindDocumentsResponse } from '@documenso/trpc/server/document-router/find-documents.types';
import { Checkbox } from '@documenso/ui/primitives/checkbox';
@@ -91,7 +92,13 @@ export const DocumentsTable = ({
},
{
header: _(msg`Title`),
- cell: ({ row }) => ,
+ cell: ({ row }) => (
+
+ ),
},
{
id: 'sender',
@@ -213,12 +220,17 @@ export const DocumentsTable = ({
type DataTableTitleProps = {
row: DocumentsTableRow;
teamUrl: string;
+ teamEmail?: string;
};
-const DataTableTitle = ({ row, teamUrl }: DataTableTitleProps) => {
+const DataTableTitle = ({ row, teamUrl, teamEmail }: DataTableTitleProps) => {
const { user } = useSession();
- const recipient = row.recipients.find((recipient) => recipient.email === user.email);
+ const recipient = findRecipientByEmail({
+ recipients: row.recipients,
+ userEmail: user.email,
+ teamEmail,
+ });
const isOwner = row.user.id === user.id;
const isRecipient = !!recipient;
diff --git a/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx b/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx
index 17c1c98c3..b5e8a1a5a 100644
--- a/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx
+++ b/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx
@@ -114,6 +114,7 @@ export default function AuthoringLayout() {
createdAt: new Date(),
avatarImageId: null,
organisationId: '',
+ teamEmail: null,
currentTeamRole: TeamMemberRole.MEMBER,
preferences: {
aiFeaturesEnabled: preferences.aiFeaturesEnabled,
diff --git a/packages/lib/utils/recipients.ts b/packages/lib/utils/recipients.ts
index d5cf3d902..a8a4c574f 100644
--- a/packages/lib/utils/recipients.ts
+++ b/packages/lib/utils/recipients.ts
@@ -92,6 +92,16 @@ export const mapRecipientToLegacyRecipient = (
};
};
+export const findRecipientByEmail = ({
+ recipients,
+ userEmail,
+ teamEmail,
+}: {
+ recipients: T[];
+ userEmail: string;
+ teamEmail?: string | null;
+}) => recipients.find((r) => r.email === userEmail || (teamEmail && r.email === teamEmail));
+
export const isRecipientEmailValidForSending = (recipient: Pick) => {
return zEmail().safeParse(recipient.email).success;
};
diff --git a/packages/trpc/server/organisation-router/get-organisation-session.ts b/packages/trpc/server/organisation-router/get-organisation-session.ts
index 1d87945f1..8ae4b7ab3 100644
--- a/packages/trpc/server/organisation-router/get-organisation-session.ts
+++ b/packages/trpc/server/organisation-router/get-organisation-session.ts
@@ -51,6 +51,7 @@ export const getOrganisationSession = async ({
where: buildTeamWhereQuery({ teamId: undefined, userId }),
include: {
teamGlobalSettings: true,
+ teamEmail: { select: { email: true } },
teamGroups: {
where: {
organisationGroup: {
diff --git a/packages/trpc/server/organisation-router/get-organisation-session.types.ts b/packages/trpc/server/organisation-router/get-organisation-session.types.ts
index 48713770d..1bf7ba05a 100644
--- a/packages/trpc/server/organisation-router/get-organisation-session.types.ts
+++ b/packages/trpc/server/organisation-router/get-organisation-session.types.ts
@@ -3,6 +3,7 @@ import { z } from 'zod';
import { ZOrganisationSchema } from '@documenso/lib/types/organisation';
import { OrganisationMemberRole, TeamMemberRole } from '@documenso/prisma/generated/types';
import SubscriptionSchema from '@documenso/prisma/generated/zod/modelSchema/SubscriptionSchema';
+import { TeamEmailSchema } from '@documenso/prisma/generated/zod/modelSchema/TeamEmailSchema';
import TeamSchema from '@documenso/prisma/generated/zod/modelSchema/TeamSchema';
export const ZGetOrganisationSessionResponseSchema = ZOrganisationSchema.extend({
@@ -16,6 +17,7 @@ export const ZGetOrganisationSessionResponseSchema = ZOrganisationSchema.extend(
organisationId: true,
}).extend({
currentTeamRole: z.nativeEnum(TeamMemberRole),
+ teamEmail: TeamEmailSchema.pick({ email: true }).nullable(),
preferences: z.object({
aiFeaturesEnabled: z.boolean(),
}),