import type { Communication } from 'fhir/r4'; import { READ_RECEIPT_EXTENSION_URLS } from './messageStatus'; export const hasReadReceiptForReference = ( message: Communication, recipientReference: string, ): boolean => { const readReceiptExtensions = (message.extension || []).filter( (extension) => !!extension?.url && READ_RECEIPT_EXTENSION_URLS.includes(extension.url), ); return readReceiptExtensions.some((extension) => { const childExtensions = extension.extension || []; const receiptRecipient = childExtensions.find( (child) => child.url === "recipient", )?.valueReference?.reference; const readAt = childExtensions.find((child) => child.url === "readAt")?.valueInstant || childExtensions.find((child) => child.url === "readAt")?.valueDateTime || childExtensions.find((child) => child.url === "readAt")?.valueString; return receiptRecipient === recipientReference && !!readAt; }); }; export const addReadReceiptForReference = ( message: Communication, recipientReference: string, readAt: string, ): Communication => { if (hasReadReceiptForReference(message, recipientReference)) { return message; } return { ...message, extension: [ ...(message.extension || []), { url: READ_RECEIPT_EXTENSION_URLS[0], extension: [ { url: "recipient", valueReference: { reference: recipientReference }, }, { url: "readAt", valueInstant: readAt, }, ], }, ], }; }; const unreadBy = (messages: Communication[], reader: string): Communication[] => messages.filter((message) => message.sender?.reference !== reader && !hasReadReceiptForReference(message, reader)); /** Messages from someone else with no receipt for this reader. Undefined when the reader is unknown, since no count is then readable. */ export const threadUnreadCount = (messages: Communication[], reader: string | null | undefined): number | undefined => reader ? unreadBy(messages, reader).length : undefined; /** The unread messages, each carrying this reader's receipt, ready to save. */ export const withReadReceipts = (messages: Communication[], reader: string, readAt: string): Communication[] => unreadBy(messages, reader).map((message) => addReadReceiptForReference(message, reader, readAt));