import { useMemo } from 'react'; import type { CommunicationRequest } from 'fhir/r4'; import { isPoolThreadRequest, threadBelongsInInbox } from '../utils/messaging/poolThread'; import { isEncounterRoomThreadRequest } from '../utils/messaging/roomThread'; interface InboxThreadsDeps { getMessagesForRequest: (request: CommunicationRequest) => unknown[]; getUnreadCountForRequest: (id: string) => number; } const latestTimestamp = (request: CommunicationRequest): number => { const value = request.authoredOn || request.meta?.lastUpdated; return value ? new Date(value).getTime() : 0; }; // Direct threads deduplicate by counterparty; listed office and visit rooms retain their own identity. export const useInboxThreads = ( requests: CommunicationRequest[], getCounterpartyId: (request: CommunicationRequest) => string | undefined, { getMessagesForRequest, getUnreadCountForRequest }: InboxThreadsDeps, ) => { const dedupedThreads = useMemo(() => { const map = new Map(); requests.forEach((request) => { // A room and a direct conversation can share a patient without sharing a thread. const id = isPoolThreadRequest(request) || isEncounterRoomThreadRequest(request) ? (request.id as string) : getCounterpartyId(request) || (request.id as string); if (!id) return; const existing = map.get(id); if (!existing || latestTimestamp(request) >= latestTimestamp(existing)) map.set(id, request); }); return Array.from(map.values()).sort((a, b) => latestTimestamp(b) - latestTimestamp(a)); }, [requests, getCounterpartyId]); const inboxThreads = useMemo(() => { return dedupedThreads .filter((request) => threadBelongsInInbox(request, getMessagesForRequest(request).length)) .sort((a, b) => { const aUnread = getUnreadCountForRequest(a.id as string) > 0 ? 1 : 0; const bUnread = getUnreadCountForRequest(b.id as string) > 0 ? 1 : 0; return bUnread - aUnread; }); }, [dedupedThreads, getMessagesForRequest, getUnreadCountForRequest]); return { dedupedThreads, inboxThreads }; };