diff --git a/frontend/server/graphql/schema.ts b/frontend/server/graphql/schema.ts index 807308f..7ede8e1 100644 --- a/frontend/server/graphql/schema.ts +++ b/frontend/server/graphql/schema.ts @@ -434,13 +434,13 @@ async function getContacts(auth: AuthContext | null) { const messageWhere = visibleMessageWhere(hiddenInboxIds); const hiddenInboxIdSet = new Set(hiddenInboxIds); - const [contactsRaw, contactInboxesRaw, communicationsRaw, threadReadsRaw] = await Promise.all([ + const [contactsRaw, contactInboxesRaw, communicationsRaw, threadReadsRaw, latestInboundAtByContactIdRaw] = await Promise.all([ prisma.contact.findMany({ where: { teamId: ctx.teamId }, include: { note: { select: { content: true } }, messages: { - where: { direction: "IN", ...(messageWhere ?? {}) }, + where: messageWhere, select: { content: true, channel: true, occurredAt: true }, orderBy: { occurredAt: "desc" as const }, take: 1, @@ -468,9 +468,23 @@ async function getContacts(auth: AuthContext | null) { where: { teamId: ctx.teamId, userId: ctx.userId }, select: { contactId: true, readAt: true }, }), + prisma.contactMessage.groupBy({ + by: ["contactId"], + where: { + contact: { teamId: ctx.teamId }, + direction: "IN", + ...(messageWhere ?? {}), + }, + _max: { occurredAt: true }, + }), ]); const readAtByContactId = new Map(threadReadsRaw.map((r) => [r.contactId, r.readAt])); + const latestInboundAtByContactId = new Map( + latestInboundAtByContactIdRaw + .map((row) => [row.contactId, row._max.occurredAt] as const) + .filter((entry): entry is readonly [string, Date] => entry[1] instanceof Date), + ); const channelsByContactId = new Map>(); const totalInboxesByContactId = new Map(); @@ -497,6 +511,7 @@ async function getContacts(auth: AuthContext | null) { }) .map((c) => { const channels = Array.from(channelsByContactId.get(c.id) ?? []); + const lastInboundAt = latestInboundAtByContactId.get(c.id); return { id: c.id, name: c.name, @@ -505,8 +520,8 @@ async function getContacts(auth: AuthContext | null) { lastContactAt: c.messages[0]?.occurredAt?.toISOString?.() ?? c.updatedAt.toISOString(), lastMessageText: c.messages[0]?.content ?? "", lastMessageChannel: c.messages[0]?.channel ? mapChannel(c.messages[0].channel) : "", - hasUnread: c.messages[0]?.occurredAt - ? (!readAtByContactId.has(c.id) || c.messages[0].occurredAt > readAtByContactId.get(c.id)!) + hasUnread: lastInboundAt + ? (!readAtByContactId.has(c.id) || lastInboundAt > readAtByContactId.get(c.id)!) : false, description: c.note?.content ?? "", };