@natoe/colab 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/constants.ts","../src/core/caseConvert.ts","../src/core/socket.ts","../src/context/CollabProvider.tsx","../src/core/channelName.ts","../src/hooks/useConversation.ts","../src/hooks/useChannelSettings.ts","../src/hooks/useDeepLinks.ts","../src/components/PatientHeader.tsx","../src/components/ReplyQuoteBlock.tsx","../src/components/SeenByIndicator.tsx","../src/components/MessageActionsMenu.tsx","../src/components/MessageBubble.tsx","../src/core/dateLabels.ts","../src/components/MessageList.tsx","../src/components/ReplyPreview.tsx","../src/components/MessageInput.tsx","../src/components/ParticipantsList.tsx","../src/components/ChannelSettings.tsx","../src/components/PinnedMessagesBar.tsx","../src/components/CollabPanel.tsx","../src/components/CollabPopup.tsx","../src/hooks/useInlineCollab.ts","../src/components/CollabInline.tsx","../src/hooks/useConversationList.ts","../src/components/ConversationListItem.tsx","../src/components/ConversationList.tsx","../src/components/CollabInbox.tsx","../src/hooks/useMessages.ts","../src/hooks/useAudioRecorder.ts","../src/hooks/useUnreadCount.ts","../src/hooks/usePinnedMessages.ts"],"names":["useState","useRef","useCallback","useEffect","jsx","jsxs","styles","escapeRegex","MessageList","React","RoleBadge","formatDuration"],"mappings":"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","file":"index.mjs","sourcesContent":["/** Phoenix channel event names — must match backend channel implementation */\nexport const EVENTS = {\n MESSAGE_NEW: 'message:new',\n MESSAGE_READ: 'message:read',\n MESSAGE_PINNED: 'message:pinned',\n MESSAGE_UNPINNED: 'message:unpinned',\n USER_TYPING: 'user:typing',\n USER_JOINED: 'user:joined',\n USER_LEFT: 'user:left',\n CHANNEL_UPDATED: 'channel:updated',\n CHANNEL_DELETED: 'channel:deleted',\n PRESENCE_STATE: 'presence_state',\n PRESENCE_DIFF: 'presence_diff',\n} as const;\n\n/** Maximum number of pinned messages allowed per conversation */\nexport const MAX_PINNED_MESSAGES = 3;\n\n/** Message types */\nexport const MESSAGE_TYPES = {\n TEXT: 'text',\n AUDIO: 'audio',\n IMAGE: 'image',\n FILE: 'file',\n SYSTEM: 'system',\n DEEP_LINK: 'deep_link',\n} as const;\n\n/** Deep link protocol prefix */\nexport const DEEP_LINK_PREFIX = 'natoe://';\n\n/** Typing indicator debounce in ms */\nexport const TYPING_DEBOUNCE_MS = 2000;\n\n/** Messages to load per page when scrolling back */\nexport const MESSAGES_PAGE_SIZE = 30;\n\n/** Supported audio MIME type for recording */\nexport const AUDIO_MIME_TYPE = 'audio/webm;codecs=opus';\n\n/** Supported image types for attachments */\nexport const SUPPORTED_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];\n\n/** Max file size in bytes (20MB) */\nexport const MAX_FILE_SIZE = 20 * 1024 * 1024;\n","/**\n * Recursively converts object keys from snake_case to camelCase.\n *\n * Used at every backend boundary (REST responses, socket events) to bridge\n * the Phoenix (snake_case) → TypeScript (camelCase) gap.\n *\n * Idempotent — keys already in camelCase stay unchanged (no underscores to\n * convert). Arrays and primitives pass through untouched.\n */\nexport function snakeToCamel<T = unknown>(input: unknown): T {\n if (Array.isArray(input)) {\n return input.map((item) => snakeToCamel(item)) as unknown as T;\n }\n\n if (input !== null && typeof input === 'object') {\n const source = input as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(source)) {\n const camelKey = toCamelKey(key);\n out[camelKey] = snakeToCamel(source[key]);\n }\n return out as T;\n }\n\n return input as T;\n}\n\nfunction toCamelKey(key: string): string {\n if (!key.includes('_')) return key;\n return key.replace(/_([a-zA-Z0-9])/g, (_, c: string) => c.toUpperCase());\n}\n","import { Socket, Channel, Presence } from 'phoenix';\nimport type {\n CollabConfig,\n Message,\n Conversation,\n Participant,\n SendMessagePayload,\n TypingEvent,\n ChannelUpdatePayload,\n InviteUserPayload,\n} from './types';\nimport { EVENTS } from './constants';\nimport { snakeToCamel } from './caseConvert';\n\ntype MessageCallback = (message: Message) => void;\ntype TypingCallback = (event: TypingEvent) => void;\ntype ParticipantCallback = (participant: Participant) => void;\ntype ChannelUpdateCallback = (conversation: Partial<Conversation>) => void;\ntype PresenceCallback = (presences: Record<string, { userId: string; isOnline: boolean }>) => void;\n\ninterface ConversationCallbacks {\n onMessage?: MessageCallback;\n onTyping?: TypingCallback;\n onUserJoined?: ParticipantCallback;\n onUserLeft?: ParticipantCallback;\n onChannelUpdated?: ChannelUpdateCallback;\n onChannelDeleted?: () => void;\n onPresence?: PresenceCallback;\n onMessageRead?: (data: { messageId: string; userId: string }) => void;\n onMessagePinned?: (message: Message) => void;\n onMessageUnpinned?: (data: { messageId: string }) => void;\n}\n\n/**\n * Manages Phoenix WebSocket connection and channel subscriptions.\n * One instance per authenticated user session.\n */\nexport class CollabSocket {\n private socket: Socket | null = null;\n private channels: Map<string, Channel> = new Map();\n private presences: Map<string, Presence> = new Map();\n private userChannel: Channel | null = null;\n private config: CollabConfig | null = null;\n private onUnreadUpdate: ((counts: Record<string, number>) => void) | null = null;\n\n /** Connect to Phoenix WebSocket server. Idempotent — safe to call when\n * the token becomes available later (e.g. after async login) without\n * stacking up multiple open sockets. */\n connect(config: CollabConfig): void {\n this.config = config;\n\n // No token means the host hasn't finished login yet. Skip the connect\n // so we don't churn through reconnect attempts that the server would\n // reject with 1006 anyway. The host re-calls connect() once auth lands.\n if (!config.getToken()) {\n return;\n }\n\n // If a prior (live or half-dead) socket exists, retire it before\n // creating a new one. Otherwise the old heartbeat / channels leak.\n if (this.socket) {\n if (this.socket.isConnected()) return;\n try {\n this.socket.disconnect();\n } catch {\n // best-effort; we're about to replace it anyway\n }\n this.channels.clear();\n this.presences.clear();\n this.userChannel = null;\n }\n\n this.socket = new Socket(config.socketUrl, {\n params: () => ({ token: config.getToken() }),\n });\n\n // Phoenix's onError hands us the native WebSocket error/close event. We\n // forward whatever useful fields the browser gave us so failures like a\n // 403 handshake (bad token / missing Redis session) can be distinguished\n // from transport drops instead of all showing as \"error undefined\".\n this.socket.onError((err) => {\n const closeEvent = err as unknown as CloseEvent | undefined;\n config.onError?.({\n code: 'SOCKET_ERROR',\n message: 'WebSocket connection error',\n details: closeEvent\n ? {\n type: closeEvent.type,\n code: closeEvent.code,\n reason: closeEvent.reason,\n wasClean: closeEvent.wasClean,\n }\n : err,\n });\n });\n\n this.socket.onClose((event) => {\n // Code 1006 = abnormal closure (no close frame — usually means the\n // server rejected the upgrade, e.g. auth failed before handshake).\n // Code 1000 = normal; code 1011 = server error.\n config.onError?.({\n code: 'SOCKET_CLOSED',\n message: `Socket closed (code ${event?.code ?? 'unknown'})`,\n details: event\n ? { code: event.code, reason: event.reason, wasClean: event.wasClean }\n : undefined,\n });\n });\n\n this.socket.connect();\n this.joinUserChannel();\n }\n\n /** Subscribe to user-level events (unread counts, notifications) */\n private joinUserChannel(): void {\n if (!this.socket || !this.config) return;\n\n // Topic has no user_id suffix — backend derives it from the authenticated socket.\n // This avoids any mismatch between client-side stored IDs and the token's claims.\n this.userChannel = this.socket.channel('user_notifications', {});\n\n this.userChannel.on('unread_update', (payload: Record<string, number>) => {\n this.onUnreadUpdate?.(payload);\n });\n\n this.userChannel\n .join()\n .receive('ok', () => {\n // connected to user channel\n })\n .receive('error', (reason) => {\n this.config?.onError?.({\n code: 'USER_CHANNEL_ERROR',\n message: 'Failed to join user channel',\n details: reason,\n });\n });\n }\n\n /** Register callback for unread count changes */\n onUnreadCountUpdate(callback: (counts: Record<string, number>) => void): void {\n this.onUnreadUpdate = callback;\n }\n\n /** Join a conversation channel and subscribe to events */\n joinConversation(conversationId: string, callbacks: ConversationCallbacks): Channel | null {\n if (!this.socket) return null;\n\n // Don't rejoin if already in this channel\n if (this.channels.has(conversationId)) {\n return this.channels.get(conversationId)!;\n }\n\n const channel = this.socket.channel(`conversation:${conversationId}`, {});\n\n // Real-time message delivery\n if (callbacks.onMessage) {\n channel.on(EVENTS.MESSAGE_NEW, (payload: unknown) => {\n callbacks.onMessage!(snakeToCamel<Message>(payload));\n });\n }\n\n // Typing indicators\n if (callbacks.onTyping) {\n channel.on(EVENTS.USER_TYPING, (payload: unknown) => {\n callbacks.onTyping!(snakeToCamel<TypingEvent>(payload));\n });\n }\n\n // Participant events\n if (callbacks.onUserJoined) {\n channel.on(EVENTS.USER_JOINED, (payload: unknown) => {\n callbacks.onUserJoined!(snakeToCamel<Participant>(payload));\n });\n }\n\n if (callbacks.onUserLeft) {\n channel.on(EVENTS.USER_LEFT, (payload: unknown) => {\n callbacks.onUserLeft!(snakeToCamel<Participant>(payload));\n });\n }\n\n // Channel metadata changes\n if (callbacks.onChannelUpdated) {\n channel.on(EVENTS.CHANNEL_UPDATED, (payload: unknown) => {\n callbacks.onChannelUpdated!(snakeToCamel<Partial<Conversation>>(payload));\n });\n }\n\n if (callbacks.onChannelDeleted) {\n channel.on(EVENTS.CHANNEL_DELETED, () => {\n callbacks.onChannelDeleted!();\n });\n }\n\n // Read receipts\n if (callbacks.onMessageRead) {\n channel.on(EVENTS.MESSAGE_READ, (payload: unknown) => {\n callbacks.onMessageRead!(snakeToCamel<{ messageId: string; userId: string }>(payload));\n });\n }\n\n // Pin events\n if (callbacks.onMessagePinned) {\n channel.on(EVENTS.MESSAGE_PINNED, (payload: unknown) => {\n callbacks.onMessagePinned!(snakeToCamel<Message>(payload));\n });\n }\n\n if (callbacks.onMessageUnpinned) {\n channel.on(EVENTS.MESSAGE_UNPINNED, (payload: unknown) => {\n callbacks.onMessageUnpinned!(snakeToCamel<{ messageId: string }>(payload));\n });\n }\n\n // Presence tracking (online/offline)\n if (callbacks.onPresence) {\n const presence = new Presence(channel);\n\n presence.onSync(() => {\n const online: Record<string, { userId: string; isOnline: boolean }> = {};\n presence.list((id: string) => {\n online[id] = { userId: id, isOnline: true };\n });\n callbacks.onPresence!(online);\n });\n\n this.presences.set(conversationId, presence);\n }\n\n channel\n .join()\n .receive('ok', () => {\n // successfully joined conversation channel\n })\n .receive('error', (reason) => {\n this.config?.onError?.({\n code: 'CHANNEL_JOIN_ERROR',\n message: `Failed to join conversation ${conversationId}`,\n details: reason,\n });\n });\n\n this.channels.set(conversationId, channel);\n return channel;\n }\n\n /** Leave a conversation channel */\n leaveConversation(conversationId: string): void {\n const channel = this.channels.get(conversationId);\n if (channel) {\n channel.leave();\n this.channels.delete(conversationId);\n this.presences.delete(conversationId);\n }\n }\n\n /** Send a message to a conversation.\n *\n * Phoenix buffers pushes fired while a channel is still joining and\n * replays them on successful join. The default per-push timeout is 10s,\n * which is tight on slow dev backends — we bump to 30s so a late join\n * doesn't surface as a \"timed out\" error to a message that ultimately\n * persists. The caller still gets 'ok' once the server acks.\n */\n sendMessage(conversationId: string, payload: SendMessagePayload): Promise<Message> {\n return new Promise((resolve, reject) => {\n const channel = this.channels.get(conversationId);\n if (!channel) {\n reject({ code: 'NOT_JOINED', message: 'Not joined to this conversation' });\n return;\n }\n\n // If the underlying socket is down (token cleared, server restarted\n // mid-session, etc.) Phoenix will silently buffer the push until the\n // per-push timeout fires 30s later. Fail fast instead — the caller\n // can remove the optimistic row and the user can retry once we're\n // back online.\n if (!this.socket?.isConnected()) {\n reject({\n code: 'SOCKET_DISCONNECTED',\n message: 'Cannot send — chat server not connected',\n });\n return;\n }\n\n channel\n .push(EVENTS.MESSAGE_NEW, payload, 30_000)\n .receive('ok', (response: Message) => resolve(response))\n .receive('error', (reason) =>\n reject({ code: 'SEND_ERROR', message: 'Failed to send message', details: reason })\n )\n .receive('timeout', () =>\n reject({ code: 'TIMEOUT', message: 'Message send timed out' })\n );\n });\n }\n\n /** Broadcast typing indicator */\n sendTyping(conversationId: string, isTyping: boolean): void {\n const channel = this.channels.get(conversationId);\n channel?.push(EVENTS.USER_TYPING, {\n userId: this.config?.userId,\n userName: this.config?.userName,\n isTyping,\n });\n }\n\n /** Mark messages as read */\n markAsRead(conversationId: string, messageId: string): void {\n const channel = this.channels.get(conversationId);\n channel?.push(EVENTS.MESSAGE_READ, {\n messageId,\n userId: this.config?.userId,\n });\n }\n\n // ── Channel Management ──\n\n /** Add a user to the conversation */\n inviteUser(conversationId: string, payload: InviteUserPayload): Promise<Participant> {\n return this.channelPush(conversationId, 'invite_user', payload);\n }\n\n /** Remove a user from the conversation */\n removeUser(conversationId: string, userId: string): Promise<void> {\n return this.channelPush(conversationId, 'remove_user', { userId });\n }\n\n /** Update channel name/picture */\n updateChannel(conversationId: string, payload: ChannelUpdatePayload): Promise<Conversation> {\n return this.channelPush(conversationId, 'update_channel', payload);\n }\n\n /** Delete channel (admin only) */\n deleteChannel(conversationId: string): Promise<void> {\n return this.channelPush(conversationId, 'delete_channel', {});\n }\n\n /** Pin a message in the conversation (max MAX_PINNED_MESSAGES) */\n pinMessage(conversationId: string, messageId: string): Promise<Message> {\n return this.channelPush(conversationId, 'pin_message', { messageId });\n }\n\n /** Unpin a message in the conversation */\n unpinMessage(conversationId: string, messageId: string): Promise<void> {\n return this.channelPush(conversationId, 'unpin_message', { messageId });\n }\n\n /** Generic push with promise wrapper */\n private channelPush<T>(conversationId: string, event: string, payload: object): Promise<T> {\n return new Promise((resolve, reject) => {\n const channel = this.channels.get(conversationId);\n if (!channel) {\n reject({ code: 'NOT_JOINED', message: 'Not joined to this conversation' });\n return;\n }\n\n channel\n .push(event, payload)\n .receive('ok', (response: T) => resolve(response))\n .receive('error', (reason) =>\n reject({ code: 'CHANNEL_ERROR', message: `Failed: ${event}`, details: reason })\n );\n });\n }\n\n /** Check if connected */\n isConnected(): boolean {\n return this.socket?.isConnected() ?? false;\n }\n\n /** Disconnect socket and leave all channels */\n disconnect(): void {\n this.channels.forEach((channel) => channel.leave());\n this.channels.clear();\n this.presences.clear();\n this.userChannel?.leave();\n this.socket?.disconnect();\n this.socket = null;\n this.config = null;\n }\n}\n","import React, { createContext, useContext, useEffect, useRef, useState, useCallback } from 'react';\nimport { CollabSocket } from '../core/socket';\nimport type {\n CollabConfig,\n ConversationListItem,\n ConversationPreview,\n CreateConversationResponse,\n Message,\n PreviewBatchResponse,\n SendMessagePayload,\n} from '../core/types';\nimport { MESSAGES_PAGE_SIZE } from '../core/constants';\nimport { snakeToCamel } from '../core/caseConvert';\n\ninterface FetchMessagesOptions {\n before?: string;\n limit?: number;\n}\n\ninterface CreateConversationOptions {\n name: string;\n participantIds?: string[];\n}\n\ninterface CollabContextValue {\n socket: CollabSocket;\n config: CollabConfig;\n apiBaseUrl: string;\n totalUnread: number;\n /** Batched preview lookup — coalesces calls within a microtask */\n requestPreview: (orderId: string) => Promise<ConversationPreview | null>;\n /** Invalidate a cached preview (e.g. when a new message arrives) */\n invalidatePreview: (orderId: string) => void;\n /** Fetch paginated message history */\n fetchMessages: (conversationId: string, options?: FetchMessagesOptions) => Promise<Message[]>;\n /** Atomic create-or-send — creates conversation if missing, then stores the first message */\n createConversationWithMessage: (\n orderId: string,\n message: SendMessagePayload,\n options: CreateConversationOptions\n ) => Promise<CreateConversationResponse>;\n /** Add a user to an existing conversation (e.g. when radiologist is assigned later) */\n addParticipant: (conversationId: string, userId: string) => Promise<void>;\n /** Remove a user from a conversation */\n removeParticipant: (conversationId: string, userId: string) => Promise<void>;\n /** Fetch the current user's full conversation list — feeds the CollabInbox sidebar */\n fetchConversationList: () => Promise<ConversationListItem[]>;\n /** Pin a message (max MAX_PINNED_MESSAGES per conversation — backend enforces) */\n pinMessage: (conversationId: string, messageId: string) => Promise<void>;\n /** Unpin a message */\n unpinMessage: (conversationId: string, messageId: string) => Promise<void>;\n /** Fetch current pinned messages for a conversation */\n fetchPinnedMessages: (conversationId: string) => Promise<Message[]>;\n}\n\nexport const CollabContext = createContext<CollabContextValue | null>(null);\nexport type { CollabContextValue };\n\nexport function useCollab(): CollabContextValue {\n const context = useContext(CollabContext);\n if (!context) {\n throw new Error('useCollab must be used within a <CollabProvider>');\n }\n return context;\n}\n\ninterface CollabProviderProps {\n config: CollabConfig;\n children: React.ReactNode;\n /** REST API base URL for the Phoenix backend (e.g. https://backend.natoe.ai) */\n apiBaseUrl: string;\n}\n\nexport function CollabProvider({ config, apiBaseUrl, children }: CollabProviderProps) {\n // Using useState (not useRef) so children re-render once the socket is ready.\n // Instantiated synchronously on first render so children have a non-null\n // socket reference immediately; the ACTUAL connect() happens in the\n // effect below, after the unread-count handler is wired in — otherwise\n // the backend's initial :after_join push races the handler registration\n // and the first unread_update is dropped silently.\n const [socket, setSocket] = useState<CollabSocket | null>(() => {\n if (typeof window === 'undefined') return null;\n return new CollabSocket();\n });\n const [unreadCounts, setUnreadCounts] = useState<Record<string, number>>({});\n\n // Preview batching state\n const pendingOrderIds = useRef<Set<string>>(new Set());\n const pendingResolvers = useRef<Map<string, Array<(preview: ConversationPreview | null) => void>>>(new Map());\n const previewCache = useRef<Map<string, ConversationPreview | null>>(new Map());\n const batchScheduled = useRef(false);\n\n // Wire unread-count listener + reconnect when identity changes.\n // The socket instance (wrapper) is created lazily in useState above, but\n // the underlying Phoenix Socket is only created if getToken() returned\n // something at that first render. When the token arrives later (post-login),\n // this effect re-fires and asks the wrapper to connect for real.\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n // Create the wrapper if it wasn't created during the useState init\n // (e.g. SSR branch that short-circuited).\n let s = socket;\n if (!s) {\n s = new CollabSocket();\n setSocket(s);\n }\n\n // Register the unread handler BEFORE connect() so the backend's\n // :after_join push (initial counts, fires immediately on channel join)\n // is never dropped because the handler was still unset. Push-driven\n // updates also clear the preview cache so the next popup open fetches\n // fresh server truth.\n s.onUnreadCountUpdate((counts) => {\n setUnreadCounts(counts);\n previewCache.current.clear();\n });\n\n // connect() is idempotent — no-op when already connected, retries when\n // the prior init saw an empty token.\n if (!s.isConnected()) {\n s.connect(config);\n }\n\n // Intentionally no cleanup disconnect here — identity changes should\n // reconnect in place rather than tearing down the whole session.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [config.socketUrl, config.userId]);\n\n const authHeaders = useCallback(\n (): HeadersInit => ({\n Authorization: `Bearer ${config.getToken()}`,\n 'Content-Type': 'application/json',\n }),\n [config]\n );\n\n // ── Batch preview fetching ──────────────────────────────────────────\n\n const flushPreviewBatch = useCallback(async () => {\n const orderIds = Array.from(pendingOrderIds.current);\n const resolvers = new Map(pendingResolvers.current);\n pendingOrderIds.current.clear();\n pendingResolvers.current.clear();\n batchScheduled.current = false;\n\n if (orderIds.length === 0) return;\n\n try {\n const query = orderIds.map((id) => `order_ids[]=${encodeURIComponent(id)}`).join('&');\n const response = await fetch(`${apiBaseUrl}/api/natoe-colab/conversations/previews?${query}`, {\n headers: authHeaders(),\n });\n\n if (!response.ok) throw new Error(`Preview batch failed: ${response.status}`);\n\n const data: PreviewBatchResponse = snakeToCamel(await response.json());\n\n orderIds.forEach((orderId) => {\n const preview = data.previews[orderId] ?? null;\n previewCache.current.set(orderId, preview);\n resolvers.get(orderId)?.forEach((resolve) => resolve(preview));\n });\n } catch (error) {\n config.onError?.({\n code: 'PREVIEW_BATCH_ERROR',\n message: 'Failed to fetch conversation previews',\n details: error,\n });\n orderIds.forEach((orderId) => {\n resolvers.get(orderId)?.forEach((resolve) => resolve(null));\n });\n }\n }, [apiBaseUrl, authHeaders, config]);\n\n const requestPreview = useCallback(\n (orderId: string): Promise<ConversationPreview | null> => {\n // Return cached if available\n if (previewCache.current.has(orderId)) {\n return Promise.resolve(previewCache.current.get(orderId) ?? null);\n }\n\n return new Promise((resolve) => {\n pendingOrderIds.current.add(orderId);\n const existing = pendingResolvers.current.get(orderId) || [];\n existing.push(resolve);\n pendingResolvers.current.set(orderId, existing);\n\n if (!batchScheduled.current) {\n batchScheduled.current = true;\n queueMicrotask(flushPreviewBatch);\n }\n });\n },\n [flushPreviewBatch]\n );\n\n const invalidatePreview = useCallback((orderId: string) => {\n previewCache.current.delete(orderId);\n }, []);\n\n // ── Message history ──────────────────────────────────────────\n\n const fetchMessages = useCallback(\n async (conversationId: string, options: FetchMessagesOptions = {}): Promise<Message[]> => {\n const limit = options.limit ?? MESSAGES_PAGE_SIZE;\n const params = new URLSearchParams({ limit: String(limit) });\n if (options.before) params.set('before', options.before);\n\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/messages?${params.toString()}`,\n { headers: authHeaders() }\n );\n\n if (!response.ok) {\n throw { code: 'FETCH_ERROR', message: 'Failed to fetch messages', status: response.status };\n }\n\n return snakeToCamel(await response.json());\n },\n [apiBaseUrl, authHeaders]\n );\n\n // ── Atomic create-or-send ──────────────────────────────────────────\n\n const createConversationWithMessage = useCallback(\n async (\n orderId: string,\n message: SendMessagePayload,\n options: CreateConversationOptions\n ): Promise<CreateConversationResponse> => {\n if (!orderId || !orderId.trim()) {\n throw {\n code: 'INVALID_ORDER_ID',\n message:\n 'Cannot create conversation: orderId is empty. Host app passed an order with no orderId/mainOrderId set.',\n };\n }\n const response = await fetch(`${apiBaseUrl}/api/natoe-colab/orders/${orderId}/messages`, {\n method: 'POST',\n headers: authHeaders(),\n body: JSON.stringify({\n message,\n conversation: {\n name: options.name,\n participant_ids: options.participantIds ?? [],\n },\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw { code: 'CREATE_ERROR', message: 'Failed to create conversation', details: error };\n }\n\n const data: CreateConversationResponse = snakeToCamel(await response.json());\n\n // The backend may have appended this message to an EXISTING\n // study-scoped conversation that already has plenty of history.\n // Drop the cached preview so the next requestPreview fetches truth\n // instead of reading a stale snapshot from before the new message.\n previewCache.current.delete(orderId);\n\n return data;\n },\n [apiBaseUrl, authHeaders]\n );\n\n // ── Participant management ──────────────────────────────────────────\n\n const addParticipant = useCallback(\n async (conversationId: string, userId: string): Promise<void> => {\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/participants`,\n {\n method: 'POST',\n headers: authHeaders(),\n body: JSON.stringify({ user_id: userId }),\n }\n );\n\n if (!response.ok) {\n throw { code: 'ADD_PARTICIPANT_ERROR', message: 'Failed to add participant' };\n }\n },\n [apiBaseUrl, authHeaders]\n );\n\n const removeParticipant = useCallback(\n async (conversationId: string, userId: string): Promise<void> => {\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/participants/${userId}`,\n {\n method: 'DELETE',\n headers: authHeaders(),\n }\n );\n\n if (!response.ok) {\n throw { code: 'REMOVE_PARTICIPANT_ERROR', message: 'Failed to remove participant' };\n }\n },\n [apiBaseUrl, authHeaders]\n );\n\n // ── Conversation list (Inbox) ──────────────────────────────────────────\n\n const fetchConversationList = useCallback(async (): Promise<ConversationListItem[]> => {\n const response = await fetch(`${apiBaseUrl}/api/natoe-colab/conversations`, {\n headers: authHeaders(),\n });\n\n if (!response.ok) {\n throw { code: 'LIST_ERROR', message: 'Failed to fetch conversation list' };\n }\n\n return snakeToCamel(await response.json());\n }, [apiBaseUrl, authHeaders]);\n\n // ── Pin management ──────────────────────────────────────────\n\n const pinMessage = useCallback(\n async (conversationId: string, messageId: string): Promise<void> => {\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/messages/${messageId}/pin`,\n {\n method: 'POST',\n headers: authHeaders(),\n }\n );\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw { code: 'PIN_ERROR', message: 'Failed to pin message', details: error };\n }\n },\n [apiBaseUrl, authHeaders]\n );\n\n const unpinMessage = useCallback(\n async (conversationId: string, messageId: string): Promise<void> => {\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/messages/${messageId}/pin`,\n {\n method: 'DELETE',\n headers: authHeaders(),\n }\n );\n\n if (!response.ok) {\n throw { code: 'UNPIN_ERROR', message: 'Failed to unpin message' };\n }\n },\n [apiBaseUrl, authHeaders]\n );\n\n const fetchPinnedMessages = useCallback(\n async (conversationId: string): Promise<Message[]> => {\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/pinned`,\n { headers: authHeaders() }\n );\n\n if (!response.ok) {\n throw { code: 'FETCH_PINNED_ERROR', message: 'Failed to fetch pinned messages' };\n }\n\n return snakeToCamel(await response.json());\n },\n [apiBaseUrl, authHeaders]\n );\n\n const totalUnread = Object.values(unreadCounts).reduce((sum, count) => sum + count, 0);\n\n if (!socket) return null;\n\n return (\n <CollabContext.Provider\n value={{\n socket,\n config,\n apiBaseUrl,\n totalUnread,\n requestPreview,\n invalidatePreview,\n fetchMessages,\n createConversationWithMessage,\n addParticipant,\n removeParticipant,\n fetchConversationList,\n pinMessage,\n unpinMessage,\n fetchPinnedMessages,\n }}\n >\n {children}\n </CollabContext.Provider>\n );\n}\n","import type { PatientData } from './types';\n\n/**\n * Canonical channel name format, used both when creating conversations\n * and wherever a channel needs to be labeled in the UI.\n *\n * Format: `<patient> - <lab> - <last 4 of order id>`\n * Example: \"John Doe - Beachside Lab - 1189\"\n */\nexport function buildChannelName(patientData: PatientData): string {\n const patientPart = patientData.patientName?.trim() || 'Unknown';\n const labPart = patientData.labName?.trim()?.slice(0, 24) || '';\n const last4 = (patientData.displayOrderId ?? '').trim().slice(-4) || '0000';\n return `${patientPart} - ${labPart} - ${last4}`;\n}\n","import { useEffect, useRef, useState, useCallback } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type {\n Message,\n Participant,\n Conversation,\n SendMessagePayload,\n TypingEvent,\n PatientData,\n} from '../core/types';\nimport { buildChannelName } from '../core/channelName';\n\ninterface UseConversationOptions {\n orderId: string;\n patientData: PatientData;\n /** Participant user IDs used only when creating a brand-new conversation */\n participantIds?: string[];\n /** Load full history on mount (default true) */\n loadHistory?: boolean;\n}\n\ninterface UseConversationReturn {\n conversation: Conversation | null;\n messages: Message[];\n pinnedMessages: Message[];\n participants: Participant[];\n typingUsers: TypingEvent[];\n isLoading: boolean;\n hasMore: boolean;\n error: string | null;\n isConnected: boolean;\n /** Message currently being replied to (null if not replying) */\n replyTo: Message | null;\n /** Set/clear the active reply target */\n setReplyTo: (message: Message | null) => void;\n sendMessage: (body: string) => Promise<void>;\n sendAudioMessage: (audioBlob: Blob, duration: number) => Promise<void>;\n sendFileMessage: (file: File) => Promise<void>;\n sendDeepLink: (path: string, label: string) => Promise<void>;\n sendTyping: (isTyping: boolean) => void;\n markAsRead: (messageId: string) => void;\n loadMoreMessages: () => Promise<void>;\n pinMessage: (messageId: string) => Promise<void>;\n unpinMessage: (messageId: string) => Promise<void>;\n}\n\n/**\n * Full conversation hook used by CollabPanel / CollabPopup.\n *\n * Lazy creation: the conversation is NOT created on mount. It's only created\n * when the user sends the first message. If a conversation already exists for\n * the given orderId, it's loaded and joined automatically.\n */\nexport function useConversation({\n orderId,\n patientData,\n participantIds = [],\n loadHistory = true,\n}: UseConversationOptions): UseConversationReturn {\n const {\n socket,\n config,\n requestPreview,\n invalidatePreview,\n fetchMessages,\n createConversationWithMessage,\n pinMessage: pinMessageApi,\n unpinMessage: unpinMessageApi,\n } = useCollab();\n\n const [conversation, setConversation] = useState<Conversation | null>(null);\n const [messages, setMessages] = useState<Message[]>([]);\n const [pinnedMessages, setPinnedMessages] = useState<Message[]>([]);\n const [participants, setParticipants] = useState<Participant[]>([]);\n const [typingUsers, setTypingUsers] = useState<TypingEvent[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [hasMore, setHasMore] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [replyTo, setReplyTo] = useState<Message | null>(null);\n\n const joinedConversationId = useRef<string | null>(null);\n const typingTimers = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());\n // In-flight promise for the lazy-create call. Two sends hitting before\n // state updates would each see `conversation: null` and POST twice; with\n // this guard, the second caller awaits the first's result instead.\n const ensureConversationInFlight = useRef<Promise<Conversation> | null>(null);\n // Messages we've already sent a `message:read` push for, in this session.\n // The MessageList's IntersectionObserver refires on every messages[] state\n // change; without this dedupe, every broadcast-driven readBy update\n // retriggers mark-read on every visible row, causing a runaway loop.\n const markedReadIdsRef = useRef<Set<string>>(new Set());\n\n const buildName = useCallback(\n (): string => buildChannelName(patientData),\n [patientData]\n );\n\n const joinChannel = useCallback(\n (conv: Conversation) => {\n if (joinedConversationId.current === conv.id) return;\n\n socket.joinConversation(conv.id, {\n // Dedupe by id so an optimistic message (added client-side on send)\n // doesn't double up when the server's broadcast arrives.\n onMessage: (msg) =>\n setMessages((prev) => {\n if (prev.some((m) => m.id === msg.id)) return prev;\n // Replace any optimistic twin (same sender, same body, still pending).\n const optimisticIdx = prev.findIndex(\n (m) =>\n m.id.startsWith('pending-') &&\n m.senderId === msg.senderId &&\n m.body === msg.body\n );\n if (optimisticIdx >= 0) {\n const next = prev.slice();\n next[optimisticIdx] = msg;\n return next;\n }\n return [...prev, msg];\n }),\n onTyping: (event) => {\n if (event.userId === config.userId) return;\n\n if (event.isTyping) {\n setTypingUsers((prev) => {\n const exists = prev.some((t) => t.userId === event.userId);\n return exists ? prev : [...prev, event];\n });\n const existingTimer = typingTimers.current.get(event.userId);\n if (existingTimer) clearTimeout(existingTimer);\n const timer = setTimeout(() => {\n setTypingUsers((prev) => prev.filter((t) => t.userId !== event.userId));\n typingTimers.current.delete(event.userId);\n }, 3000);\n typingTimers.current.set(event.userId, timer);\n } else {\n setTypingUsers((prev) => prev.filter((t) => t.userId !== event.userId));\n const timer = typingTimers.current.get(event.userId);\n if (timer) clearTimeout(timer);\n typingTimers.current.delete(event.userId);\n }\n },\n onUserJoined: (participant) => {\n setParticipants((prev) =>\n prev.some((p) => p.userId === participant.userId) ? prev : [...prev, participant]\n );\n },\n onUserLeft: (participant) => {\n setParticipants((prev) => prev.filter((p) => p.userId !== participant.userId));\n },\n onChannelUpdated: (updates) => {\n setConversation((prev) => (prev ? { ...prev, ...updates } : prev));\n },\n onChannelDeleted: () => {\n setConversation(null);\n setMessages([]);\n joinedConversationId.current = null;\n setIsConnected(false);\n },\n onMessageRead: ({ messageId, userId }) => {\n setMessages((prev) =>\n prev.map((msg) =>\n msg.id === messageId && !(msg.readBy ?? []).includes(userId)\n ? { ...msg, readBy: [...(msg.readBy ?? []), userId] }\n : msg\n )\n );\n },\n onMessagePinned: (message) => {\n setPinnedMessages((prev) =>\n prev.some((m) => m.id === message.id) ? prev : [...prev, message]\n );\n setMessages((prev) =>\n prev.map((m) => (m.id === message.id ? { ...m, isPinned: true } : m))\n );\n },\n onMessageUnpinned: ({ messageId }) => {\n setPinnedMessages((prev) => prev.filter((m) => m.id !== messageId));\n setMessages((prev) =>\n prev.map((m) => (m.id === messageId ? { ...m, isPinned: false } : m))\n );\n },\n });\n\n joinedConversationId.current = conv.id;\n setIsConnected(true);\n },\n [socket, config.userId]\n );\n\n // Initial load: check for existing conversation via preview\n useEffect(() => {\n let cancelled = false;\n\n const init = async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n const preview = await requestPreview(orderId);\n\n if (cancelled) return;\n\n if (!preview) {\n // No conversation exists yet — stay in \"new\" mode\n setConversation(null);\n setMessages([]);\n setParticipants([]);\n setHasMore(false);\n setIsLoading(false);\n return;\n }\n\n const existingConv: Conversation = {\n id: preview.conversationId,\n orderId: preview.orderId,\n name: preview.name,\n participants: preview.participants,\n unreadCount: preview.unreadCount,\n createdAt: '',\n updatedAt: '',\n };\n\n setConversation(existingConv);\n setParticipants(preview.participants);\n // Channel join kicks off synchronously (Phoenix push handles the\n // async part). Renders can proceed while the join completes.\n joinChannel(existingConv);\n\n // Paint the panel immediately with the last-N messages from the\n // preview — no wait. Unblock the user from typing while full\n // history loads in the background.\n setMessages(preview.lastMessages);\n setHasMore(preview.messageCount > preview.lastMessages.length);\n setPinnedMessages(preview.lastMessages.filter((m) => m.isPinned));\n setIsLoading(false);\n\n if (loadHistory) {\n // Always pull authoritative history from the server, even when the\n // preview looks \"complete\" by count — the preview cache can be\n // stale (messages may have arrived after it was populated but\n // before the user reopened the popup). Dedupe by id on merge so\n // we don't duplicate the ones already painted.\n fetchMessages(preview.conversationId)\n .then((history) => {\n if (cancelled) return;\n setMessages((prev) => {\n const seen = new Set(prev.map((m) => m.id));\n const older = history.filter((m) => !seen.has(m.id));\n return [...older, ...prev];\n });\n setHasMore(history.length > 0);\n setPinnedMessages((prev) => {\n const fromHistory = history.filter((m) => m.isPinned);\n const seen = new Set(prev.map((m) => m.id));\n return [...fromHistory.filter((m) => !seen.has(m.id)), ...prev];\n });\n })\n .catch(() => {\n // Non-fatal — user can still see the preview slice and scroll\n // up will retry. onError is already surfaced by fetchMessages.\n });\n }\n } catch (err) {\n if (cancelled) return;\n const msg = err instanceof Error ? err.message : 'Failed to load conversation';\n setError(msg);\n setIsLoading(false);\n }\n };\n\n init();\n\n return () => {\n cancelled = true;\n if (joinedConversationId.current) {\n socket.leaveConversation(joinedConversationId.current);\n joinedConversationId.current = null;\n }\n typingTimers.current.forEach((timer) => clearTimeout(timer));\n typingTimers.current.clear();\n markedReadIdsRef.current.clear();\n setIsConnected(false);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [orderId]);\n\n // ── Send helpers ──\n\n // `persistedByCreate` tells the caller whether THEIR payload was written\n // by the REST create (true = don't also send via socket, that would dup).\n // - conversation already existed → false\n // - piggy-backed on someone else's in-flight create → false (their payload\n // needs a socket send)\n // - this caller kicked off the create → true (their payload was in the POST)\n const ensureConversation = useCallback(\n async (\n payload: SendMessagePayload\n ): Promise<{ conv: Conversation; persistedByCreate: boolean }> => {\n if (conversation) return { conv: conversation, persistedByCreate: false };\n\n if (ensureConversationInFlight.current) {\n const conv = await ensureConversationInFlight.current;\n return { conv, persistedByCreate: false };\n }\n\n const inflight = (async () => {\n const result = await createConversationWithMessage(orderId, payload, {\n name: buildName(),\n participantIds,\n });\n\n setConversation(result.conversation);\n setParticipants(result.conversation.participants);\n setMessages([result.message]);\n joinChannel(result.conversation);\n invalidatePreview(orderId);\n\n // Create-or-send may have appended our message to an EXISTING\n // study-scoped conversation with prior history — the init effect's\n // preview-backed load doesn't cover that case because `conversation`\n // was null when it ran. Pull authoritative history now and merge\n // (dedupe by id so the just-inserted message isn't duplicated).\n if (loadHistory) {\n fetchMessages(result.conversation.id)\n .then((history) => {\n setMessages((prev) => {\n const seen = new Set(prev.map((m) => m.id));\n const older = history.filter((m) => !seen.has(m.id));\n return [...older, ...prev];\n });\n setPinnedMessages((prev) => {\n const fromHistory = history.filter((m) => m.isPinned);\n const seen = new Set(prev.map((m) => m.id));\n return [...fromHistory.filter((m) => !seen.has(m.id)), ...prev];\n });\n })\n .catch(() => {\n // Non-fatal — fetchMessages already surfaces via onError.\n });\n }\n\n return result.conversation;\n })();\n\n ensureConversationInFlight.current = inflight;\n\n try {\n const conv = await inflight;\n return { conv, persistedByCreate: true };\n } finally {\n ensureConversationInFlight.current = null;\n }\n },\n [\n conversation,\n createConversationWithMessage,\n orderId,\n buildName,\n participantIds,\n joinChannel,\n invalidatePreview,\n loadHistory,\n fetchMessages,\n ]\n );\n\n const sendMessage = useCallback(\n async (body: string) => {\n const payload: SendMessagePayload = {\n body,\n type: 'text',\n ...(replyTo ? { replyToId: replyTo.id } : {}),\n };\n const { conv, persistedByCreate } = await ensureConversation(payload);\n setReplyTo(null);\n\n // Our message was already written by the REST create — skip the socket\n // push, otherwise we'd persist the same message twice.\n if (persistedByCreate) return;\n\n // Optimistic insert so the user sees their text instantly, regardless\n // of socket roundtrip. The server broadcast (via onMessage above) will\n // swap this in for the real, persisted message.\n const optimistic: Message = {\n id: `pending-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n conversationId: conv.id,\n senderId: config.userId,\n senderName: config.userName,\n senderRole: config.userRole,\n body,\n type: 'text',\n insertedAt: new Date().toISOString(),\n ...(replyTo\n ? {\n replyToId: replyTo.id,\n replyToSnapshot: {\n messageId: replyTo.id,\n senderId: replyTo.senderId,\n senderName: replyTo.senderName,\n body: replyTo.body,\n type: replyTo.type,\n },\n }\n : {}),\n };\n setMessages((prev) => [...prev, optimistic]);\n\n try {\n await socket.sendMessage(conv.id, payload);\n } catch (err) {\n // Surface the failure and drop the optimistic row so the user can retry.\n setMessages((prev) => prev.filter((m) => m.id !== optimistic.id));\n config.onError?.({\n code: 'SEND_FAILED',\n message: 'Failed to send message',\n details: err,\n });\n }\n },\n [ensureConversation, socket, replyTo, config]\n );\n\n const sendAudioMessage = useCallback(\n async (audioBlob: Blob, duration: number) => {\n if (!config.onUploadFile) return;\n const url = await config.onUploadFile(audioBlob, 'voice-message.webm');\n const payload: SendMessagePayload = {\n body: 'Voice message',\n type: 'audio',\n mediaUrl: url,\n mediaDuration: duration,\n };\n const { conv, persistedByCreate } = await ensureConversation(payload);\n if (persistedByCreate) return;\n await socket.sendMessage(conv.id, payload);\n },\n [config, ensureConversation, socket]\n );\n\n const sendFileMessage = useCallback(\n async (file: File) => {\n if (!config.onUploadFile) return;\n const url = await config.onUploadFile(file, file.name);\n const isImage = file.type.startsWith('image/');\n const payload: SendMessagePayload = {\n body: file.name,\n type: isImage ? 'image' : 'file',\n mediaUrl: url,\n fileName: file.name,\n };\n const { conv, persistedByCreate } = await ensureConversation(payload);\n if (persistedByCreate) return;\n await socket.sendMessage(conv.id, payload);\n },\n [config, ensureConversation, socket]\n );\n\n const sendDeepLink = useCallback(\n async (path: string, label: string) => {\n const payload: SendMessagePayload = {\n body: label,\n type: 'deep_link',\n metadata: { path },\n };\n const { conv, persistedByCreate } = await ensureConversation(payload);\n if (persistedByCreate) return;\n await socket.sendMessage(conv.id, payload);\n },\n [ensureConversation, socket]\n );\n\n const sendTypingIndicator = useCallback(\n (isTyping: boolean) => {\n if (!conversation || !isConnected) return;\n socket.sendTyping(conversation.id, isTyping);\n },\n [conversation, isConnected, socket]\n );\n\n const markAsRead = useCallback(\n (messageId: string) => {\n if (!conversation || !isConnected) return;\n if (markedReadIdsRef.current.has(messageId)) return;\n markedReadIdsRef.current.add(messageId);\n socket.markAsRead(conversation.id, messageId);\n },\n [conversation, isConnected, socket]\n );\n\n const loadMoreMessages = useCallback(async () => {\n if (!conversation || !hasMore || isLoading) return;\n\n const oldestMessage = messages[0];\n const before = oldestMessage?.id;\n\n setIsLoading(true);\n try {\n const older = await fetchMessages(conversation.id, { before });\n setMessages((prev) => [...older, ...prev]);\n setHasMore(older.length > 0);\n } catch (err) {\n config.onError?.({\n code: 'LOAD_ERROR',\n message: 'Failed to load older messages',\n details: err,\n });\n } finally {\n setIsLoading(false);\n }\n }, [conversation, hasMore, isLoading, messages, fetchMessages, config]);\n\n const pinMessage = useCallback(\n async (messageId: string) => {\n if (!conversation) return;\n try {\n await pinMessageApi(conversation.id, messageId);\n } catch (err) {\n config.onError?.({\n code: 'PIN_ERROR',\n message: 'Failed to pin message',\n details: err,\n });\n }\n },\n [conversation, pinMessageApi, config]\n );\n\n const unpinMessage = useCallback(\n async (messageId: string) => {\n if (!conversation) return;\n try {\n await unpinMessageApi(conversation.id, messageId);\n } catch (err) {\n config.onError?.({\n code: 'UNPIN_ERROR',\n message: 'Failed to unpin message',\n details: err,\n });\n }\n },\n [conversation, unpinMessageApi, config]\n );\n\n return {\n conversation,\n messages,\n pinnedMessages,\n participants,\n typingUsers,\n isLoading,\n hasMore,\n error,\n isConnected,\n replyTo,\n setReplyTo,\n sendMessage,\n sendAudioMessage,\n sendFileMessage,\n sendDeepLink,\n sendTyping: sendTypingIndicator,\n markAsRead,\n loadMoreMessages,\n pinMessage,\n unpinMessage,\n };\n}\n","import { useCallback, useState } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type {\n ChannelUpdatePayload,\n InviteUserPayload,\n CollabError,\n} from '../core/types';\n\ninterface UseChannelSettingsOptions {\n conversationId: string | null;\n}\n\ninterface UseChannelSettingsReturn {\n /** Invite a user to the conversation */\n inviteUser: (payload: InviteUserPayload) => Promise<void>;\n /** Remove a user from the conversation (admin/creator only) */\n removeUser: (userId: string) => Promise<void>;\n /** Current user leaves the conversation */\n leaveChannel: () => Promise<void>;\n /** Delete the conversation entirely (admin only) */\n deleteChannel: () => Promise<void>;\n /** Update channel name and/or picture */\n updateChannel: (payload: ChannelUpdatePayload) => Promise<void>;\n /** Whether an operation is in progress */\n isUpdating: boolean;\n /** Last error from any operation */\n error: CollabError | null;\n /** Whether current user can perform admin actions */\n isAdmin: boolean;\n}\n\nexport function useChannelSettings({ conversationId }: UseChannelSettingsOptions): UseChannelSettingsReturn {\n const { socket, config } = useCollab();\n const [isUpdating, setIsUpdating] = useState(false);\n const [error, setError] = useState<CollabError | null>(null);\n\n const isAdmin = config.userRole === 'admin';\n\n const withLoading = useCallback(\n async <T>(operation: () => Promise<T>): Promise<T | undefined> => {\n if (!conversationId) return;\n setIsUpdating(true);\n setError(null);\n try {\n const result = await operation();\n setIsUpdating(false);\n return result;\n } catch (err) {\n const collabError: CollabError =\n typeof err === 'object' && err !== null && 'code' in err\n ? (err as CollabError)\n : { code: 'UNKNOWN', message: 'Operation failed' };\n\n setError(collabError);\n setIsUpdating(false);\n config.onError?.(collabError);\n return undefined;\n }\n },\n [conversationId, config]\n );\n\n const inviteUser = useCallback(\n async (payload: InviteUserPayload) => {\n await withLoading(() => socket.inviteUser(conversationId!, payload));\n },\n [conversationId, socket, withLoading]\n );\n\n const removeUser = useCallback(\n async (userId: string) => {\n await withLoading(() => socket.removeUser(conversationId!, userId));\n },\n [conversationId, socket, withLoading]\n );\n\n const leaveChannel = useCallback(async () => {\n await withLoading(async () => {\n await socket.removeUser(conversationId!, config.userId);\n socket.leaveConversation(conversationId!);\n });\n }, [conversationId, socket, config.userId, withLoading]);\n\n const deleteChannel = useCallback(async () => {\n if (!isAdmin) {\n const err: CollabError = {\n code: 'FORBIDDEN',\n message: 'Only admins can delete channels',\n };\n setError(err);\n config.onError?.(err);\n return;\n }\n await withLoading(() => socket.deleteChannel(conversationId!));\n }, [conversationId, socket, isAdmin, config, withLoading]);\n\n const updateChannel = useCallback(\n async (payload: ChannelUpdatePayload) => {\n await withLoading(() => socket.updateChannel(conversationId!, payload));\n },\n [conversationId, socket, withLoading]\n );\n\n return {\n inviteUser,\n removeUser,\n leaveChannel,\n deleteChannel,\n updateChannel,\n isUpdating,\n error,\n isAdmin,\n };\n}\n","import { useCallback } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport { DEEP_LINK_PREFIX } from '../core/constants';\n\ninterface ParsedDeepLink {\n /** Full original link string */\n raw: string;\n /** The path after natoe:// (e.g. \"order/4521\") */\n path: string;\n /** The resource type (e.g. \"order\", \"report\", \"dicom\", \"study\") */\n resource: string;\n /** The resource ID */\n id: string;\n}\n\ninterface UseDeepLinksReturn {\n /** Parse a deep link string into structured data */\n parseDeepLink: (link: string) => ParsedDeepLink | null;\n /** Handle a deep link click — calls config.onDeepLink or config.onOpenDicom */\n handleDeepLink: (link: string) => void;\n /** Check if a string contains deep links */\n containsDeepLink: (text: string) => boolean;\n /** Extract all deep links from a message body */\n extractDeepLinks: (text: string) => ParsedDeepLink[];\n}\n\n/**\n * Parses and handles natoe:// deep links in messages.\n *\n * Supported formats:\n * natoe://order/4521 → opens order detail\n * natoe://report/4521 → opens report\n * natoe://dicom/4521 → opens DICOM viewer (uses onOpenDicom callback)\n * natoe://study/4521 → opens study detail\n */\nexport function useDeepLinks(): UseDeepLinksReturn {\n const { config } = useCollab();\n\n const parseDeepLink = useCallback((link: string): ParsedDeepLink | null => {\n if (!link.startsWith(DEEP_LINK_PREFIX)) return null;\n\n const path = link.slice(DEEP_LINK_PREFIX.length);\n const parts = path.split('/').filter(Boolean);\n\n if (parts.length < 2) return null;\n\n return {\n raw: link,\n path,\n resource: parts[0],\n id: parts[1],\n };\n }, []);\n\n const handleDeepLink = useCallback(\n (link: string) => {\n const parsed = parseDeepLink(link);\n if (!parsed) return;\n\n // DICOM links use the dedicated callback\n if (parsed.resource === 'dicom' && config.onOpenDicom) {\n config.onOpenDicom(parsed.id, '');\n return;\n }\n\n // Everything else goes through the generic deep link handler\n if (config.onDeepLink) {\n config.onDeepLink(parsed.path);\n }\n },\n [parseDeepLink, config]\n );\n\n const containsDeepLink = useCallback((text: string): boolean => {\n return text.includes(DEEP_LINK_PREFIX);\n }, []);\n\n const extractDeepLinks = useCallback(\n (text: string): ParsedDeepLink[] => {\n // Match natoe://path/segments patterns in text\n const regex = new RegExp(`${escapeRegex(DEEP_LINK_PREFIX)}[\\\\w/.-]+`, 'g');\n const matches = text.match(regex) || [];\n return matches.map(parseDeepLink).filter((link): link is ParsedDeepLink => link !== null);\n },\n [parseDeepLink]\n );\n\n return {\n parseDeepLink,\n handleDeepLink,\n containsDeepLink,\n extractDeepLinks,\n };\n}\n\nfunction escapeRegex(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import React from 'react';\nimport { buildChannelName } from '../core/channelName';\nimport type { PatientData, Participant } from '../core/types';\n\ninterface PatientHeaderProps {\n patientData: PatientData;\n participants: Participant[];\n onOpenDicom?: () => void;\n onOpenSettings?: () => void;\n className?: string;\n}\n\nexport function PatientHeader({\n patientData,\n onOpenDicom,\n onOpenSettings,\n className,\n}: PatientHeaderProps) {\n const hasDicom = !!(patientData.studyId && patientData.storageId);\n\n return (\n <div className={className} style={styles.container}>\n {/* Channel name row — primary identifier */}\n <div style={styles.infoRow}>\n <div style={styles.patientInfo}>\n <span style={styles.patientName}>{buildChannelName(patientData)}</span>\n </div>\n </div>\n\n {/* Secondary info — clinical context */}\n <div style={styles.secondaryRow}>\n {patientData.patientAge && (\n <span style={styles.secondary}>\n {patientData.patientAge}\n {patientData.patientSex ? `/${patientData.patientSex}` : ''}\n </span>\n )}\n {patientData.studyType && (\n <span style={styles.secondary}>{patientData.studyType}</span>\n )}\n {patientData.bodyParts && patientData.bodyParts.length > 0 && (\n <span style={styles.secondary}>{patientData.bodyParts.join(', ')}</span>\n )}\n {patientData.referringPhysician && (\n <span style={styles.secondary}>Ref: {patientData.referringPhysician}</span>\n )}\n </div>\n\n {/* Action buttons */}\n <div style={styles.actions}>\n {hasDicom && onOpenDicom && (\n <button onClick={onOpenDicom} style={styles.dicomButton} type=\"button\">\n View DICOM\n </button>\n )}\n {onOpenSettings && (\n <button onClick={onOpenSettings} style={styles.settingsButton} type=\"button\">\n Settings\n </button>\n )}\n </div>\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n padding: '12px 16px',\n borderBottom: '1px solid #e5e7eb',\n backgroundColor: '#f9fafb',\n },\n infoRow: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n patientInfo: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n flexWrap: 'wrap' as const,\n },\n patientName: {\n fontWeight: 600,\n fontSize: '15px',\n color: '#111827',\n },\n detail: {\n fontSize: '13px',\n color: '#6b7280',\n },\n studyType: {\n fontSize: '13px',\n color: '#2563eb',\n fontWeight: 500,\n },\n orderId: {\n fontSize: '12px',\n color: '#9ca3af',\n fontFamily: 'monospace',\n },\n secondaryRow: {\n display: 'flex',\n gap: '12px',\n marginTop: '4px',\n alignItems: 'center',\n },\n secondary: {\n fontSize: '12px',\n color: '#6b7280',\n },\n participantCount: {\n fontSize: '12px',\n color: '#6b7280',\n marginLeft: 'auto',\n },\n actions: {\n display: 'flex',\n gap: '8px',\n marginTop: '8px',\n },\n dicomButton: {\n padding: '6px 12px',\n fontSize: '13px',\n fontWeight: 500,\n color: '#ffffff',\n backgroundColor: '#2563eb',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n settingsButton: {\n padding: '6px 12px',\n fontSize: '13px',\n fontWeight: 500,\n color: '#374151',\n backgroundColor: '#ffffff',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n};\n","import React from 'react';\nimport type { MessageSnapshot } from '../core/types';\n\ninterface ReplyQuoteBlockProps {\n snapshot: MessageSnapshot;\n /** True when rendered inside an own-message bubble (affects color contrast) */\n inOwnBubble?: boolean;\n /** Called when user clicks the quote — host can scroll to the original message */\n onClick?: (messageId: string) => void;\n className?: string;\n}\n\n/**\n * Rendered inside a MessageBubble when the message is a reply.\n * Shows a compact quote of the original message.\n */\nexport function ReplyQuoteBlock({\n snapshot,\n inOwnBubble = false,\n onClick,\n className,\n}: ReplyQuoteBlockProps) {\n const baseBg = inOwnBubble ? 'rgba(255,255,255,0.18)' : '#f3f4f6';\n const barColor = inOwnBubble ? '#ffffff' : '#2563eb';\n const nameColor = inOwnBubble ? '#ffffff' : '#2563eb';\n const bodyColor = inOwnBubble ? 'rgba(255,255,255,0.85)' : '#4b5563';\n\n const preview = renderSnapshotPreview(snapshot);\n\n return (\n <div\n className={className}\n style={{ ...styles.container, backgroundColor: baseBg }}\n onClick={() => onClick?.(snapshot.messageId)}\n role={onClick ? 'button' : undefined}\n tabIndex={onClick ? 0 : undefined}\n >\n <div style={{ ...styles.bar, backgroundColor: barColor }} />\n <div style={styles.content}>\n <span style={{ ...styles.senderName, color: nameColor }}>{snapshot.senderName}</span>\n <span style={{ ...styles.body, color: bodyColor }}>{preview}</span>\n </div>\n </div>\n );\n}\n\nfunction renderSnapshotPreview(snapshot: MessageSnapshot): string {\n switch (snapshot.type) {\n case 'audio':\n return '🎤 Voice message';\n case 'image':\n return '📷 Image';\n case 'file':\n return '📎 File';\n case 'deep_link':\n return `🔗 ${snapshot.body}`;\n default: {\n const body = snapshot.body || '';\n return body.length > 80 ? `${body.slice(0, 80)}…` : body;\n }\n }\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n gap: '6px',\n padding: '4px 8px',\n marginBottom: '4px',\n borderRadius: '6px',\n cursor: 'pointer',\n maxWidth: '100%',\n },\n bar: {\n width: '3px',\n borderRadius: '2px',\n flexShrink: 0,\n },\n content: {\n display: 'flex',\n flexDirection: 'column',\n gap: '1px',\n minWidth: 0,\n overflow: 'hidden',\n },\n senderName: {\n fontSize: '11px',\n fontWeight: 600,\n lineHeight: '1.2',\n },\n body: {\n fontSize: '11px',\n lineHeight: '1.3',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n};\n","import React, { useState } from 'react';\nimport type { Participant } from '../core/types';\n\ninterface SeenByIndicatorProps {\n /** User IDs who have read the message */\n readBy: string[];\n /** All participants in the conversation — used to resolve names */\n participants: Participant[];\n /** Current user ID (excluded from the display) */\n currentUserId: string;\n /** Message sender ID (excluded from the display) */\n senderId: string;\n className?: string;\n}\n\n/**\n * WhatsApp-style \"Seen by\" indicator shown under own messages.\n * Shows up to 3 names inline; if more, shows remainder count with a tap-to-expand.\n *\n * Only renders when the current user is the sender (seen-by on others' messages\n * is redundant — they obviously saw their own message).\n */\nexport function SeenByIndicator({\n readBy,\n participants,\n currentUserId,\n senderId,\n className,\n}: SeenByIndicatorProps) {\n const [expanded, setExpanded] = useState(false);\n\n // Only show on own messages\n if (senderId !== currentUserId) return null;\n\n const seenByOthers = readBy\n .filter((id) => id !== currentUserId && id !== senderId)\n .map((id) => participants.find((p) => p.userId === id))\n .filter((p): p is Participant => !!p);\n\n if (seenByOthers.length === 0) return null;\n\n const displayCount = expanded ? seenByOthers.length : Math.min(3, seenByOthers.length);\n const shown = seenByOthers.slice(0, displayCount);\n const remainder = seenByOthers.length - displayCount;\n\n return (\n <div className={className} style={styles.container}>\n <span style={styles.checkmark}>✓✓</span>\n <span style={styles.label}>Seen by {shown.map((p) => p.userName ?? 'User').join(', ')}</span>\n {remainder > 0 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n setExpanded(true);\n }}\n style={styles.moreButton}\n type=\"button\"\n >\n +{remainder}\n </button>\n )}\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n marginTop: '2px',\n fontSize: '10px',\n opacity: 0.75,\n },\n checkmark: {\n fontSize: '10px',\n color: '#60a5fa',\n },\n label: {\n fontSize: '10px',\n color: 'inherit',\n },\n moreButton: {\n fontSize: '10px',\n fontWeight: 600,\n color: 'inherit',\n backgroundColor: 'transparent',\n border: 'none',\n padding: 0,\n cursor: 'pointer',\n textDecoration: 'underline',\n },\n};\n","import React from 'react';\nimport type { Message } from '../core/types';\n\ninterface MessageActionsMenuProps {\n message: Message;\n onReply: (message: Message) => void;\n onPin: (messageId: string) => void;\n onUnpin: (messageId: string) => void;\n onCopy?: (text: string) => void;\n /** True when the menu should show (hover / open state managed by parent) */\n visible: boolean;\n /** Whether we've hit the pin limit — if true, pin is disabled */\n pinDisabled?: boolean;\n className?: string;\n}\n\n/**\n * Inline action menu for a single message.\n * Parent controls visibility (typically via hover state in MessageBubble).\n */\nexport function MessageActionsMenu({\n message,\n onReply,\n onPin,\n onUnpin,\n onCopy,\n visible,\n pinDisabled = false,\n className,\n}: MessageActionsMenuProps) {\n if (!visible) return null;\n\n const isPinned = !!message.isPinned;\n const canCopy = message.type === 'text' && !!message.body;\n\n const handleCopy = () => {\n if (!onCopy) return;\n onCopy(message.body);\n };\n\n return (\n <div className={className} style={styles.container}>\n <button\n onClick={() => onReply(message)}\n style={styles.button}\n title=\"Reply\"\n type=\"button\"\n >\n ↩\n </button>\n\n {isPinned ? (\n <button\n onClick={() => onUnpin(message.id)}\n style={styles.button}\n title=\"Unpin\"\n type=\"button\"\n >\n 📌\n </button>\n ) : (\n <button\n onClick={() => onPin(message.id)}\n style={{\n ...styles.button,\n opacity: pinDisabled ? 0.4 : 1,\n cursor: pinDisabled ? 'not-allowed' : 'pointer',\n }}\n disabled={pinDisabled}\n title={pinDisabled ? 'Pin limit reached (max 3)' : 'Pin'}\n type=\"button\"\n >\n 📌\n </button>\n )}\n\n {canCopy && onCopy && (\n <button\n onClick={handleCopy}\n style={styles.button}\n title=\"Copy text\"\n type=\"button\"\n >\n ⎘\n </button>\n )}\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n gap: '2px',\n padding: '2px',\n backgroundColor: '#ffffff',\n border: '1px solid #e5e7eb',\n borderRadius: '20px',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)',\n },\n button: {\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '12px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n },\n};\n","import React, { useState } from 'react';\nimport { ReplyQuoteBlock } from './ReplyQuoteBlock';\nimport { SeenByIndicator } from './SeenByIndicator';\nimport { MessageActionsMenu } from './MessageActionsMenu';\nimport type { Message, Participant, UserRole } from '../core/types';\nimport { DEEP_LINK_PREFIX } from '../core/constants';\n\ninterface MessageBubbleProps {\n message: Message;\n isOwn: boolean;\n /** Participants list — needed for SeenByIndicator */\n participants?: Participant[];\n /** Current user ID — needed for SeenByIndicator */\n currentUserId?: string;\n /** Show \"seen by\" indicator under own messages (default true — inline disables this) */\n showSeenBy?: boolean;\n onDeepLinkClick?: (link: string) => void;\n onReply?: (message: Message) => void;\n onPin?: (messageId: string) => void;\n onUnpin?: (messageId: string) => void;\n onCopy?: (text: string) => void;\n onReplyJumpTo?: (messageId: string) => void;\n /** True if pin limit reached — disables pin action */\n pinDisabled?: boolean;\n className?: string;\n}\n\nexport function MessageBubble({\n message,\n isOwn,\n participants = [],\n currentUserId = '',\n showSeenBy = true,\n onDeepLinkClick,\n onReply,\n onPin,\n onUnpin,\n onCopy,\n onReplyJumpTo,\n pinDisabled = false,\n className,\n}: MessageBubbleProps) {\n const [isHovered, setIsHovered] = useState(false);\n\n if (message.type === 'system') {\n return <SystemBubble message={message} />;\n }\n\n const hasActions = !!(onReply || onPin || onUnpin || onCopy);\n\n return (\n <div\n className={className}\n style={{\n ...styles.wrapper,\n justifyContent: isOwn ? 'flex-end' : 'flex-start',\n }}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n <div style={styles.bubbleWrapper}>\n <div\n style={{\n ...styles.bubble,\n ...(isOwn ? styles.ownBubble : styles.otherBubble),\n }}\n >\n {/* Pinned indicator */}\n {message.isPinned && (\n <div style={styles.pinnedBadge}>📌 Pinned</div>\n )}\n\n {/* Reply quote (when this message is a reply) */}\n {message.replyToSnapshot && (\n <ReplyQuoteBlock\n snapshot={message.replyToSnapshot}\n inOwnBubble={isOwn}\n onClick={onReplyJumpTo}\n />\n )}\n\n {/* Sender info for others' messages */}\n {!isOwn && (\n <div style={styles.senderRow}>\n <span style={styles.senderName}>{message.senderName}</span>\n <RoleBadge role={message.senderRole} />\n </div>\n )}\n\n {/* Message content by type */}\n {message.type === 'text' && <TextContent body={message.body} onDeepLinkClick={onDeepLinkClick} />}\n {message.type === 'audio' && <AudioContent mediaUrl={message.mediaUrl} duration={message.mediaDuration} />}\n {message.type === 'image' && <ImageContent mediaUrl={message.mediaUrl} fileName={message.fileName} />}\n {message.type === 'file' && <FileContent mediaUrl={message.mediaUrl} fileName={message.fileName} />}\n {message.type === 'deep_link' && (\n <DeepLinkContent body={message.body} metadata={message.metadata} onDeepLinkClick={onDeepLinkClick} />\n )}\n\n {/* Timestamp */}\n <div style={styles.timestamp}>{formatTime(message.insertedAt)}</div>\n\n {/* Seen by indicator (own messages only) */}\n {showSeenBy && isOwn && (\n <SeenByIndicator\n readBy={message.readBy ?? []}\n participants={participants}\n currentUserId={currentUserId}\n senderId={message.senderId}\n />\n )}\n </div>\n\n {/* Actions menu (hover) */}\n {hasActions && (\n <div\n style={{\n ...styles.actionsWrapper,\n [isOwn ? 'right' : 'left']: '100%',\n [isOwn ? 'marginRight' : 'marginLeft']: '6px',\n }}\n >\n <MessageActionsMenu\n message={message}\n onReply={onReply ?? (() => {})}\n onPin={onPin ?? (() => {})}\n onUnpin={onUnpin ?? (() => {})}\n onCopy={onCopy}\n visible={isHovered}\n pinDisabled={pinDisabled}\n />\n </div>\n )}\n </div>\n </div>\n );\n}\n\n// ── Sub-components ──\n\nfunction TextContent({ body, onDeepLinkClick }: { body: string; onDeepLinkClick?: (link: string) => void }) {\n if (body.includes(DEEP_LINK_PREFIX)) {\n const parts = body.split(new RegExp(`(${escapeRegex(DEEP_LINK_PREFIX)}[\\\\w/.-]+)`, 'g'));\n return (\n <p style={styles.textBody}>\n {parts.map((part, i) =>\n part.startsWith(DEEP_LINK_PREFIX) ? (\n <a\n key={i}\n onClick={(e) => {\n e.preventDefault();\n onDeepLinkClick?.(part);\n }}\n href=\"#\"\n style={styles.deepLink}\n >\n {part}\n </a>\n ) : (\n <span key={i}>{part}</span>\n )\n )}\n </p>\n );\n }\n\n return <p style={styles.textBody}>{body}</p>;\n}\n\nfunction AudioContent({ mediaUrl, duration }: { mediaUrl?: string; duration?: number }) {\n if (!mediaUrl) return null;\n\n return (\n <div style={styles.audioContainer}>\n <audio controls preload=\"metadata\" style={styles.audioPlayer}>\n <source src={mediaUrl} />\n </audio>\n {duration != null && <span style={styles.audioDuration}>{formatDuration(duration)}</span>}\n </div>\n );\n}\n\nfunction ImageContent({ mediaUrl, fileName }: { mediaUrl?: string; fileName?: string }) {\n if (!mediaUrl) return null;\n\n return (\n <a href={mediaUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n <img src={mediaUrl} alt={fileName || 'Image'} style={styles.imagePreview} />\n </a>\n );\n}\n\nfunction FileContent({ mediaUrl, fileName }: { mediaUrl?: string; fileName?: string }) {\n if (!mediaUrl) return null;\n\n return (\n <a href={mediaUrl} target=\"_blank\" rel=\"noopener noreferrer\" style={styles.fileLink}>\n <span style={styles.fileIcon}>📄</span>\n <span style={styles.fileName}>{fileName || 'Download file'}</span>\n </a>\n );\n}\n\nfunction DeepLinkContent({\n body,\n metadata,\n onDeepLinkClick,\n}: {\n body: string;\n metadata?: Record<string, unknown>;\n onDeepLinkClick?: (link: string) => void;\n}) {\n const path = metadata?.path as string | undefined;\n\n return (\n <div\n style={styles.deepLinkCard}\n onClick={() => path && onDeepLinkClick?.(`${DEEP_LINK_PREFIX}${path}`)}\n >\n <span style={styles.deepLinkLabel}>{body}</span>\n {path && <span style={styles.deepLinkPath}>{DEEP_LINK_PREFIX}{path}</span>}\n </div>\n );\n}\n\nfunction SystemBubble({ message }: { message: Message }) {\n return (\n <div style={styles.systemMessage}>\n <span>{message.body}</span>\n <span style={styles.systemTime}>{formatTime(message.insertedAt)}</span>\n </div>\n );\n}\n\nfunction RoleBadge({ role }: { role: UserRole }) {\n const colors: Record<UserRole, string> = {\n radiologist: '#7c3aed',\n lab: '#2563eb',\n physician: '#059669',\n admin: '#dc2626',\n };\n\n return (\n <span style={{ ...styles.roleBadge, backgroundColor: `${colors[role]}15`, color: colors[role] }}>\n {role}\n </span>\n );\n}\n\n// ── Helpers ──\n\nfunction formatTime(iso: string): string {\n try {\n return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n } catch {\n return '';\n }\n}\n\nfunction formatDuration(seconds: number): string {\n const m = Math.floor(seconds / 60);\n const s = seconds % 60;\n return `${m}:${s.toString().padStart(2, '0')}`;\n}\n\nfunction escapeRegex(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n// ── Styles ──\n\nconst styles: Record<string, React.CSSProperties> = {\n wrapper: {\n display: 'flex',\n marginBottom: '8px',\n paddingLeft: '16px',\n paddingRight: '16px',\n },\n bubbleWrapper: {\n position: 'relative',\n maxWidth: '75%',\n },\n bubble: {\n padding: '8px 12px',\n borderRadius: '12px',\n wordBreak: 'break-word',\n },\n ownBubble: {\n backgroundColor: '#2563eb',\n color: '#ffffff',\n borderBottomRightRadius: '4px',\n },\n otherBubble: {\n backgroundColor: '#f3f4f6',\n color: '#111827',\n borderBottomLeftRadius: '4px',\n },\n pinnedBadge: {\n display: 'inline-block',\n fontSize: '10px',\n fontWeight: 600,\n marginBottom: '4px',\n opacity: 0.7,\n },\n senderRow: {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n marginBottom: '4px',\n },\n senderName: {\n fontSize: '12px',\n fontWeight: 600,\n color: '#374151',\n },\n roleBadge: {\n fontSize: '10px',\n fontWeight: 500,\n padding: '1px 6px',\n borderRadius: '4px',\n },\n textBody: {\n margin: 0,\n fontSize: '14px',\n lineHeight: '1.4',\n },\n timestamp: {\n fontSize: '10px',\n opacity: 0.7,\n marginTop: '4px',\n textAlign: 'right' as const,\n },\n actionsWrapper: {\n position: 'absolute' as const,\n top: '50%',\n transform: 'translateY(-50%)',\n zIndex: 10,\n },\n audioContainer: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n },\n audioPlayer: {\n height: '32px',\n maxWidth: '220px',\n },\n audioDuration: {\n fontSize: '12px',\n opacity: 0.7,\n whiteSpace: 'nowrap' as const,\n },\n imagePreview: {\n maxWidth: '240px',\n maxHeight: '180px',\n borderRadius: '8px',\n objectFit: 'cover' as const,\n cursor: 'pointer',\n },\n fileLink: {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n textDecoration: 'none',\n color: 'inherit',\n padding: '6px 0',\n },\n fileIcon: {\n fontSize: '18px',\n },\n fileName: {\n fontSize: '13px',\n textDecoration: 'underline',\n },\n deepLink: {\n color: '#3b82f6',\n textDecoration: 'underline',\n cursor: 'pointer',\n },\n deepLinkCard: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '2px',\n padding: '8px',\n backgroundColor: '#eff6ff',\n borderRadius: '8px',\n border: '1px solid #bfdbfe',\n cursor: 'pointer',\n },\n deepLinkLabel: {\n fontSize: '13px',\n fontWeight: 500,\n color: '#1d4ed8',\n },\n deepLinkPath: {\n fontSize: '11px',\n color: '#6b7280',\n fontFamily: 'monospace',\n },\n systemMessage: {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n gap: '8px',\n padding: '4px 16px',\n fontSize: '12px',\n color: '#9ca3af',\n },\n systemTime: {\n fontSize: '10px',\n color: '#d1d5db',\n },\n};\n","/**\n * Shared date/time labels for the chat UI.\n *\n * Two surfaces consume these:\n * - The inbox row's right-side timestamp ({@link formatInboxTimestamp})\n * - The in-chat day divider pill ({@link formatDayDivider})\n *\n * Bucketing is identical between them, so a conversation labeled \"Tuesday\"\n * in the inbox is grouped under a \"Tuesday\" pill inside its chat — no\n * drift between surfaces.\n *\n * Format choices:\n * - Full date: \"15 May 2026\" (fixed English short month, day, year)\n * - Weekday: \"Tuesday\" (fixed English long weekday)\n * - Time: locale-defaulted (respects the user's OS region)\n */\n\nconst SHORT_MONTHS = [\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\n];\n\nconst LONG_WEEKDAYS = [\n 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',\n];\n\nconst ONE_DAY_MS = 86_400_000;\n\nfunction parseSafe(iso: string): Date | null {\n const d = new Date(iso);\n return Number.isNaN(d.getTime()) ? null : d;\n}\n\n/** Returns the start of the day for the given date (local time). */\nfunction startOfDay(d: Date): Date {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate());\n}\n\n/** Number of calendar days between two dates (local time). Negative if a < b. */\nfunction daysBetween(a: Date, b: Date): number {\n return Math.floor((startOfDay(a).getTime() - startOfDay(b).getTime()) / ONE_DAY_MS);\n}\n\nfunction formatFullDate(d: Date): string {\n return `${d.getDate()} ${SHORT_MONTHS[d.getMonth()]} ${d.getFullYear()}`;\n}\n\nfunction formatLocaleTime(d: Date): string {\n // Locale-default time. Tries to match the user's OS preference for 12h vs\n // 24h. Falls back to a manual 12h format if Intl is unavailable.\n try {\n return d.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });\n } catch {\n const h = d.getHours();\n const m = d.getMinutes().toString().padStart(2, '0');\n const suffix = h >= 12 ? 'PM' : 'AM';\n const h12 = ((h + 11) % 12) + 1;\n return `${h12}:${m} ${suffix}`;\n }\n}\n\n/**\n * Inbox row timestamp (right-edge of each conversation row).\n *\n * today → \"9:42 PM\"\n * yesterday → \"Yesterday\"\n * last 7 days → weekday name (\"Tuesday\")\n * older → \"15 May 2026\"\n */\nexport function formatInboxTimestamp(iso: string | null | undefined): string {\n if (!iso) return '';\n const d = parseSafe(iso);\n if (!d) return '';\n\n const diffDays = daysBetween(new Date(), d);\n\n if (diffDays === 0) return formatLocaleTime(d);\n if (diffDays === 1) return 'Yesterday';\n if (diffDays > 1 && diffDays < 7) return LONG_WEEKDAYS[d.getDay()];\n return formatFullDate(d);\n}\n\n/**\n * In-chat day divider pill text.\n *\n * today → \"Today\"\n * yesterday → \"Yesterday\"\n * last 7 days → weekday name (\"Tuesday\")\n * older → \"15 May 2026\"\n */\nexport function formatDayDivider(iso: string | null | undefined): string {\n if (!iso) return '';\n const d = parseSafe(iso);\n if (!d) return '';\n\n const diffDays = daysBetween(new Date(), d);\n\n if (diffDays === 0) return 'Today';\n if (diffDays === 1) return 'Yesterday';\n if (diffDays > 1 && diffDays < 7) return LONG_WEEKDAYS[d.getDay()];\n return formatFullDate(d);\n}\n\n/**\n * Stable day-bucket key for grouping messages. Two messages with the same\n * key belong under the same day divider.\n */\nexport function dayBucketKey(iso: string | null | undefined): string {\n if (!iso) return '';\n const d = parseSafe(iso);\n if (!d) return '';\n return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;\n}\n","import React, { useEffect, useRef, useCallback, useImperativeHandle, forwardRef } from 'react';\nimport { MessageBubble } from './MessageBubble';\nimport { dayBucketKey, formatDayDivider } from '../core/dateLabels';\nimport type { Message, Participant, TypingEvent } from '../core/types';\n\nexport interface MessageListHandle {\n /** Scroll to a specific message by ID (used by pin jump-to) */\n scrollToMessage: (messageId: string) => void;\n}\n\ninterface MessageListProps {\n messages: Message[];\n currentUserId: string;\n participants?: Participant[];\n showSeenBy?: boolean;\n typingUsers: TypingEvent[];\n hasMore: boolean;\n isLoading: boolean;\n onLoadMore: () => void;\n onDeepLinkClick?: (link: string) => void;\n onMessageVisible?: (messageId: string) => void;\n onReply?: (message: Message) => void;\n onPin?: (messageId: string) => void;\n onUnpin?: (messageId: string) => void;\n onCopy?: (text: string) => void;\n pinDisabled?: boolean;\n className?: string;\n}\n\nexport const MessageList = forwardRef<MessageListHandle, MessageListProps>(function MessageList(\n {\n messages,\n currentUserId,\n participants = [],\n showSeenBy = true,\n typingUsers,\n hasMore,\n isLoading,\n onLoadMore,\n onDeepLinkClick,\n onMessageVisible,\n onReply,\n onPin,\n onUnpin,\n onCopy,\n pinDisabled,\n className,\n },\n ref\n) {\n const containerRef = useRef<HTMLDivElement>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const prevMessageCount = useRef(messages.length);\n\n useImperativeHandle(\n ref,\n () => ({\n scrollToMessage: (messageId: string) => {\n const element = containerRef.current?.querySelector(`[data-message-id=\"${messageId}\"]`);\n if (element) {\n element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n // Brief flash to draw attention\n (element as HTMLElement).style.transition = 'background-color 200ms';\n (element as HTMLElement).style.backgroundColor = '#fef3c7';\n setTimeout(() => {\n (element as HTMLElement).style.backgroundColor = '';\n }, 800);\n }\n },\n }),\n []\n );\n\n // Auto-scroll to bottom on new messages\n useEffect(() => {\n if (messages.length > prevMessageCount.current) {\n const lastMessage = messages[messages.length - 1];\n const isOwnMessage = lastMessage?.senderId === currentUserId;\n\n // Always scroll for own messages, or if already near bottom\n if (isOwnMessage || isNearBottom(containerRef.current)) {\n bottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n }\n }\n prevMessageCount.current = messages.length;\n }, [messages, currentUserId]);\n\n // Intersection observer for marking messages as read\n useEffect(() => {\n if (!onMessageVisible || !containerRef.current) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n const messageId = (entry.target as HTMLElement).dataset.messageId;\n if (messageId) onMessageVisible(messageId);\n }\n });\n },\n { root: containerRef.current, threshold: 0.5 }\n );\n\n const messageElements = containerRef.current.querySelectorAll('[data-message-id]');\n messageElements.forEach((el) => observer.observe(el));\n\n return () => observer.disconnect();\n }, [messages, onMessageVisible]);\n\n // Scroll-to-top detection for loading more messages\n const handleScroll = useCallback(() => {\n if (!containerRef.current || !hasMore || isLoading) return;\n\n if (containerRef.current.scrollTop < 50) {\n onLoadMore();\n }\n }, [hasMore, isLoading, onLoadMore]);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={styles.container}\n onScroll={handleScroll}\n >\n {/* Load more indicator */}\n {isLoading && (\n <div style={styles.loadingMore}>Loading earlier messages...</div>\n )}\n\n {hasMore && !isLoading && messages.length > 0 && (\n <button onClick={onLoadMore} style={styles.loadMoreButton} type=\"button\">\n Load earlier messages\n </button>\n )}\n\n {/* Empty state */}\n {messages.length === 0 && !isLoading && (\n <div style={styles.empty}>\n <p style={styles.emptyTitle}>No messages yet</p>\n <p style={styles.emptySubtitle}>Start the conversation about this study</p>\n </div>\n )}\n\n {/* Message list — day dividers inserted when the bucket key changes.\n Messages arrive sorted oldest → newest, so we walk forward and\n emit a pill before any message whose day differs from the prior. */}\n {messages.map((message, index) => {\n const currentBucket = dayBucketKey(message.insertedAt);\n const prevBucket =\n index === 0 ? null : dayBucketKey(messages[index - 1].insertedAt);\n const showDivider = currentBucket && currentBucket !== prevBucket;\n\n return (\n <React.Fragment key={message.id}>\n {showDivider && (\n <div style={styles.dayDivider} role=\"separator\" aria-label=\"Date\">\n <span style={styles.dayDividerPill}>\n {formatDayDivider(message.insertedAt)}\n </span>\n </div>\n )}\n <div data-message-id={message.id}>\n <MessageBubble\n message={message}\n isOwn={message.senderId === currentUserId}\n participants={participants}\n currentUserId={currentUserId}\n showSeenBy={showSeenBy}\n onDeepLinkClick={onDeepLinkClick}\n onReply={onReply}\n onPin={onPin}\n onUnpin={onUnpin}\n onCopy={onCopy}\n pinDisabled={pinDisabled}\n />\n </div>\n </React.Fragment>\n );\n })}\n\n {/* Typing indicators */}\n {typingUsers.length > 0 && (\n <div style={styles.typingIndicator}>\n {typingUsers.map((t) => t.userName ?? 'Someone').join(', ')}\n {typingUsers.length === 1 ? ' is ' : ' are '}typing...\n </div>\n )}\n\n <div ref={bottomRef} />\n </div>\n );\n});\n\nfunction isNearBottom(container: HTMLDivElement | null): boolean {\n if (!container) return true;\n const threshold = 150;\n return container.scrollHeight - container.scrollTop - container.clientHeight < threshold;\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n flex: 1,\n overflowY: 'auto',\n paddingTop: '12px',\n paddingBottom: '8px',\n },\n loadingMore: {\n textAlign: 'center',\n padding: '12px',\n fontSize: '13px',\n color: '#9ca3af',\n },\n loadMoreButton: {\n display: 'block',\n margin: '0 auto 12px',\n padding: '6px 16px',\n fontSize: '12px',\n color: '#6b7280',\n backgroundColor: 'transparent',\n border: '1px solid #e5e7eb',\n borderRadius: '16px',\n cursor: 'pointer',\n },\n empty: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '48px 16px',\n color: '#9ca3af',\n },\n emptyTitle: {\n fontSize: '15px',\n fontWeight: 500,\n margin: '0 0 4px',\n },\n emptySubtitle: {\n fontSize: '13px',\n margin: 0,\n },\n typingIndicator: {\n padding: '4px 16px 8px',\n fontSize: '12px',\n color: '#9ca3af',\n fontStyle: 'italic',\n },\n dayDivider: {\n display: 'flex',\n justifyContent: 'center',\n margin: '12px 0 8px',\n },\n dayDividerPill: {\n display: 'inline-block',\n padding: '4px 12px',\n fontSize: '12px',\n fontWeight: 500,\n color: '#475569',\n backgroundColor: '#f1f5f9',\n border: '1px solid #e2e8f0',\n borderRadius: '12px',\n letterSpacing: '0.2px',\n },\n};\n","import React from 'react';\nimport type { Message } from '../core/types';\n\ninterface ReplyPreviewProps {\n /** The message being replied to */\n message: Message;\n /** Called when user cancels the reply */\n onCancel: () => void;\n className?: string;\n}\n\n/**\n * Shown above the MessageInput when the user is composing a reply.\n * Displays the quoted message with a cancel button.\n */\nexport function ReplyPreview({ message, onCancel, className }: ReplyPreviewProps) {\n const preview = renderQuotedPreview(message);\n\n return (\n <div className={className} style={styles.container}>\n <div style={styles.bar} />\n <div style={styles.content}>\n <div style={styles.senderLine}>\n <span style={styles.senderIcon}>↩</span>\n <span style={styles.senderName}>Replying to {message.senderName}</span>\n </div>\n <div style={styles.preview}>{preview}</div>\n </div>\n <button onClick={onCancel} style={styles.cancelButton} title=\"Cancel reply\" type=\"button\">\n ✕\n </button>\n </div>\n );\n}\n\nfunction renderQuotedPreview(message: Message): string {\n switch (message.type) {\n case 'audio':\n return '🎤 Voice message';\n case 'image':\n return `📷 ${message.fileName || 'Image'}`;\n case 'file':\n return `📎 ${message.fileName || 'File'}`;\n case 'deep_link':\n return `🔗 ${message.body}`;\n default: {\n const body = message.body || '';\n return body.length > 120 ? `${body.slice(0, 120)}…` : body;\n }\n }\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n alignItems: 'stretch',\n gap: '8px',\n padding: '8px 12px',\n backgroundColor: '#f9fafb',\n borderTop: '1px solid #e5e7eb',\n },\n bar: {\n width: '3px',\n backgroundColor: '#2563eb',\n borderRadius: '2px',\n flexShrink: 0,\n },\n content: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n minWidth: 0,\n },\n senderLine: {\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n },\n senderIcon: {\n fontSize: '11px',\n color: '#2563eb',\n },\n senderName: {\n fontSize: '12px',\n fontWeight: 600,\n color: '#2563eb',\n },\n preview: {\n fontSize: '12px',\n color: '#6b7280',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n cancelButton: {\n alignSelf: 'center',\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#6b7280',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '12px',\n flexShrink: 0,\n },\n};\n","import React, { useState, useRef, useCallback, useEffect } from 'react';\n// MIC DISABLED — voice messaging temporarily removed. Imports kept for easy re-enable.\n// import { useAudioRecorder } from '../hooks/useAudioRecorder';\n// import { MicIcon } from './icons/MicIcon';\nimport { ReplyPreview } from './ReplyPreview';\nimport { MAX_FILE_SIZE, SUPPORTED_IMAGE_TYPES } from '../core/constants';\nimport type { Message } from '../core/types';\n\ninterface MessageInputProps {\n onSendText: (body: string) => Promise<void>;\n /** @deprecated MIC DISABLED — kept in the prop signature for backward compat. */\n onSendAudio?: (blob: Blob, duration: number) => Promise<void>;\n onSendFile: (file: File) => Promise<void>;\n onTyping: (isTyping: boolean) => void;\n /** When set, shows a ReplyPreview above the input */\n replyTo?: Message | null;\n /** Called when user cancels the reply */\n onCancelReply?: () => void;\n disabled?: boolean;\n placeholder?: string;\n className?: string;\n}\n\nexport function MessageInput({\n onSendText,\n // MIC DISABLED — onSendAudio still accepted but unused.\n // onSendAudio,\n onSendFile,\n onTyping,\n replyTo,\n onCancelReply,\n disabled = false,\n placeholder = 'Type a message...',\n className,\n}: MessageInputProps) {\n const [text, setText] = useState('');\n const [isSending, setIsSending] = useState(false);\n const [fileError, setFileError] = useState<string | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const typingTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const isTypingRef = useRef(false);\n // Synchronous guard — useState's async update can't block a second click\n // that lands before React re-renders. The ref flips immediately.\n const sendingRef = useRef(false);\n\n // MIC DISABLED — voice recorder hook is not invoked. Restore by uncommenting\n // the original destructure below (and the import at the top of the file).\n // const { isRecording, duration, start: startRecording, stop: stopRecording, cancel: cancelRecording, isSupported: micSupported, error: micError } = useAudioRecorder();\n\n // Rising-edge only — fire once when the user starts typing, then a single\n // \"stopped\" event after 2s of idle. Previously this called onTyping(true)\n // on EVERY keystroke, flooding the socket with redundant events.\n const handleTyping = useCallback(() => {\n if (!isTypingRef.current) {\n isTypingRef.current = true;\n onTyping(true);\n }\n\n if (typingTimeoutRef.current) {\n clearTimeout(typingTimeoutRef.current);\n }\n\n typingTimeoutRef.current = setTimeout(() => {\n isTypingRef.current = false;\n onTyping(false);\n }, 2000);\n }, [onTyping]);\n\n useEffect(() => {\n return () => {\n if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);\n };\n }, []);\n\n const handleSendText = useCallback(async () => {\n const trimmed = text.trim();\n if (!trimmed || sendingRef.current) return;\n\n sendingRef.current = true;\n setIsSending(true);\n if (isTypingRef.current) {\n isTypingRef.current = false;\n onTyping(false);\n }\n if (typingTimeoutRef.current) {\n clearTimeout(typingTimeoutRef.current);\n typingTimeoutRef.current = null;\n }\n\n try {\n await onSendText(trimmed);\n setText('');\n } finally {\n sendingRef.current = false;\n setIsSending(false);\n }\n }, [text, onSendText, onTyping]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSendText();\n }\n },\n [handleSendText]\n );\n\n // MIC DISABLED — audio stop handler unused. Restore alongside useAudioRecorder.\n // const handleAudioStop = useCallback(async () => {\n // const result = await stopRecording();\n // if (result) {\n // setIsSending(true);\n // try {\n // await onSendAudio(result.blob, result.duration);\n // } finally {\n // setIsSending(false);\n // }\n // }\n // }, [stopRecording, onSendAudio]);\n\n const handleFileSelect = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n setFileError(null);\n\n if (file.size > MAX_FILE_SIZE) {\n setFileError(`File too large. Maximum size is ${MAX_FILE_SIZE / (1024 * 1024)}MB.`);\n return;\n }\n\n setIsSending(true);\n try {\n await onSendFile(file);\n } finally {\n setIsSending(false);\n // Reset file input\n if (fileInputRef.current) fileInputRef.current.value = '';\n }\n },\n [onSendFile]\n );\n\n return (\n <div className={className} style={styles.container}>\n {/* Reply preview */}\n {replyTo && onCancelReply && (\n <ReplyPreview message={replyTo} onCancel={onCancelReply} />\n )}\n\n {/* Error messages */}\n {fileError && (\n <div style={styles.error}>{fileError}</div>\n )}\n\n {/* MIC DISABLED — recording bar and mic button removed.\n Original blocks kept here for easy re-enable:\n\n {isRecording ? (\n <div style={styles.recordingBar}>\n <div style={styles.recordingIndicator}>\n <span style={styles.recordingDot} />\n Recording {formatDuration(duration)}\n </div>\n <div style={styles.recordingActions}>\n <button onClick={cancelRecording} style={styles.cancelButton} type=\"button\">Cancel</button>\n <button onClick={handleAudioStop} style={styles.stopButton} type=\"button\">Send</button>\n </div>\n </div>\n ) : (\n ...input bar with mic button...\n )}\n */}\n <div style={styles.inputBar}>\n {/* MIC DISABLED — mic button hidden.\n {micSupported && (\n <button onClick={startRecording} disabled={disabled || isSending} style={styles.iconButton} title=\"Record voice message\" type=\"button\">\n <MicIcon size={20} color=\"#374151\" />\n </button>\n )}\n */}\n\n {/* File attach */}\n <button\n onClick={() => fileInputRef.current?.click()}\n disabled={disabled || isSending}\n style={styles.iconButton}\n title=\"Attach file\"\n type=\"button\"\n >\n 📎\n </button>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n onChange={handleFileSelect}\n style={{ display: 'none' }}\n accept={[...SUPPORTED_IMAGE_TYPES, 'application/pdf', '.doc', '.docx'].join(',')}\n />\n\n {/* Text input */}\n <textarea\n value={text}\n onChange={(e) => {\n setText(e.target.value);\n handleTyping();\n }}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled || isSending}\n rows={1}\n style={styles.textarea}\n />\n\n {/* Send button */}\n <button\n onClick={handleSendText}\n disabled={disabled || isSending || !text.trim()}\n style={{\n ...styles.sendButton,\n opacity: text.trim() ? 1 : 0.4,\n }}\n type=\"button\"\n >\n ➤\n </button>\n </div>\n </div>\n );\n}\n\n// MIC DISABLED — formatDuration was only used by the recording UI.\n// Kept here for easy restore when mic is re-enabled.\n// function formatDuration(seconds: number): string {\n// const m = Math.floor(seconds / 60);\n// const s = seconds % 60;\n// return `${m}:${s.toString().padStart(2, '0')}`;\n// }\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n borderTop: '1px solid #e5e7eb',\n backgroundColor: '#ffffff',\n },\n error: {\n padding: '6px 16px',\n fontSize: '12px',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n },\n inputBar: {\n display: 'flex',\n alignItems: 'flex-end',\n gap: '4px',\n padding: '8px 12px',\n },\n iconButton: {\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '18px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n flexShrink: 0,\n },\n textarea: {\n flex: 1,\n padding: '8px 12px',\n fontSize: '14px',\n lineHeight: '1.4',\n border: '1px solid #e5e7eb',\n borderRadius: '20px',\n resize: 'none',\n outline: 'none',\n fontFamily: 'inherit',\n maxHeight: '120px',\n },\n sendButton: {\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '18px',\n backgroundColor: '#2563eb',\n color: '#ffffff',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n flexShrink: 0,\n },\n recordingBar: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '12px 16px',\n backgroundColor: '#fef2f2',\n },\n recordingIndicator: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n fontSize: '14px',\n color: '#dc2626',\n fontWeight: 500,\n },\n recordingDot: {\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: '#dc2626',\n animation: 'pulse 1.5s infinite',\n },\n recordingActions: {\n display: 'flex',\n gap: '8px',\n },\n cancelButton: {\n padding: '6px 14px',\n fontSize: '13px',\n color: '#6b7280',\n backgroundColor: '#ffffff',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n stopButton: {\n padding: '6px 14px',\n fontSize: '13px',\n fontWeight: 500,\n color: '#ffffff',\n backgroundColor: '#dc2626',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n};\n","import React from 'react';\nimport type { Participant, UserRole } from '../core/types';\n\ninterface ParticipantsListProps {\n participants: Participant[];\n currentUserId: string;\n isAdmin: boolean;\n onRemoveUser: (userId: string) => Promise<void>;\n className?: string;\n}\n\nexport function ParticipantsList({\n participants,\n currentUserId,\n isAdmin,\n onRemoveUser,\n className,\n}: ParticipantsListProps) {\n return (\n <div className={className} style={styles.list}>\n {participants.map((participant) => (\n <div key={participant.userId} style={styles.item}>\n {/* Avatar */}\n <div style={styles.avatar}>\n {participant.avatar ? (\n <img src={participant.avatar} alt=\"\" style={styles.avatarImg} />\n ) : (\n <span style={styles.avatarFallback}>\n {(participant.userName ?? '?').charAt(0).toUpperCase()}\n </span>\n )}\n {/* Online indicator */}\n <span\n style={{\n ...styles.statusDot,\n backgroundColor: participant.isOnline ? '#22c55e' : '#d1d5db',\n }}\n />\n </div>\n\n {/* Info */}\n <div style={styles.info}>\n <span style={styles.name}>\n {participant.userName ?? fallbackName(participant.userRole)}\n {participant.userId === currentUserId && (\n <span style={styles.youBadge}> (you)</span>\n )}\n </span>\n <RoleBadge role={participant.userRole} />\n </div>\n\n {/* Remove button (admin only, can't remove self) */}\n {isAdmin && participant.userId !== currentUserId && (\n <button\n onClick={() => onRemoveUser(participant.userId)}\n style={styles.removeButton}\n title={`Remove ${participant.userName ?? fallbackName(participant.userRole)}`}\n type=\"button\"\n >\n ✕\n </button>\n )}\n </div>\n ))}\n </div>\n );\n}\n\nfunction fallbackName(role: UserRole): string {\n switch (role) {\n case 'lab':\n return 'Imaging Center';\n case 'radiologist':\n return 'Radiologist';\n case 'physician':\n return 'Physician';\n case 'admin':\n return 'Natoe Admin';\n default:\n return 'User';\n }\n}\n\nfunction RoleBadge({ role }: { role: UserRole }) {\n const colors: Record<UserRole, { bg: string; text: string }> = {\n radiologist: { bg: '#f5f3ff', text: '#7c3aed' },\n lab: { bg: '#eff6ff', text: '#2563eb' },\n physician: { bg: '#ecfdf5', text: '#059669' },\n admin: { bg: '#fef2f2', text: '#dc2626' },\n };\n\n const color = colors[role];\n\n return (\n <span style={{ ...styles.roleBadge, backgroundColor: color.bg, color: color.text }}>\n {role}\n </span>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n list: {\n display: 'flex',\n flexDirection: 'column',\n },\n item: {\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n padding: '8px 0',\n borderBottom: '1px solid #f9fafb',\n },\n avatar: {\n position: 'relative',\n width: '32px',\n height: '32px',\n flexShrink: 0,\n },\n avatarImg: {\n width: '32px',\n height: '32px',\n borderRadius: '50%',\n objectFit: 'cover' as const,\n },\n avatarFallback: {\n width: '32px',\n height: '32px',\n borderRadius: '50%',\n backgroundColor: '#e5e7eb',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '13px',\n fontWeight: 600,\n color: '#6b7280',\n },\n statusDot: {\n position: 'absolute' as const,\n bottom: '0',\n right: '0',\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n border: '2px solid #ffffff',\n },\n info: {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n flex: 1,\n minWidth: 0,\n },\n name: {\n fontSize: '13px',\n fontWeight: 500,\n color: '#111827',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap' as const,\n },\n youBadge: {\n fontSize: '11px',\n fontWeight: 400,\n color: '#9ca3af',\n },\n roleBadge: {\n fontSize: '10px',\n fontWeight: 500,\n padding: '1px 6px',\n borderRadius: '4px',\n whiteSpace: 'nowrap' as const,\n },\n removeButton: {\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '11px',\n color: '#9ca3af',\n flexShrink: 0,\n },\n};\n","import React, { useState } from 'react';\nimport { ParticipantsList } from './ParticipantsList';\nimport type { Participant, InviteUserPayload, UserRole, CollabError } from '../core/types';\n\ninterface ChannelSettingsProps {\n conversationId: string;\n channelName: string;\n channelPicture?: string;\n participants: Participant[];\n currentUserId: string;\n isAdmin: boolean;\n isUpdating: boolean;\n error: CollabError | null;\n onUpdateChannel: (payload: { name?: string; picture?: string }) => Promise<void>;\n onInviteUser: (payload: InviteUserPayload) => Promise<void>;\n onRemoveUser: (userId: string) => Promise<void>;\n onLeaveChannel: () => Promise<void>;\n onDeleteChannel: () => Promise<void>;\n onClose: () => void;\n className?: string;\n}\n\nexport function ChannelSettings({\n channelName,\n participants,\n currentUserId,\n isAdmin,\n isUpdating,\n error,\n onUpdateChannel,\n onInviteUser,\n onRemoveUser,\n onLeaveChannel,\n onDeleteChannel,\n onClose,\n className,\n}: ChannelSettingsProps) {\n const [editingName, setEditingName] = useState(false);\n const [nameValue, setNameValue] = useState(channelName);\n const [showInvite, setShowInvite] = useState(false);\n const [inviteId, setInviteId] = useState('');\n const [inviteName, setInviteName] = useState('');\n const [inviteRole, setInviteRole] = useState<UserRole>('radiologist');\n const [confirmDelete, setConfirmDelete] = useState(false);\n\n const handleSaveName = async () => {\n if (nameValue.trim() && nameValue !== channelName) {\n await onUpdateChannel({ name: nameValue.trim() });\n }\n setEditingName(false);\n };\n\n const handleInvite = async () => {\n if (!inviteId.trim() || !inviteName.trim()) return;\n await onInviteUser({\n userId: inviteId.trim(),\n userName: inviteName.trim(),\n userRole: inviteRole,\n });\n setInviteId('');\n setInviteName('');\n setShowInvite(false);\n };\n\n const handleDelete = async () => {\n if (!confirmDelete) {\n setConfirmDelete(true);\n return;\n }\n await onDeleteChannel();\n };\n\n return (\n <div className={className} style={styles.container}>\n {/* Header */}\n <div style={styles.header}>\n <h3 style={styles.title}>Channel Settings</h3>\n <button onClick={onClose} style={styles.closeButton} type=\"button\">\n ✕\n </button>\n </div>\n\n {/* Error */}\n {error && (\n <div style={styles.error}>{error.message}</div>\n )}\n\n {/* Channel name */}\n <div style={styles.section}>\n <label style={styles.label}>Channel Name</label>\n {editingName ? (\n <div style={styles.editRow}>\n <input\n value={nameValue}\n onChange={(e) => setNameValue(e.target.value)}\n style={styles.input}\n autoFocus\n />\n <button onClick={handleSaveName} disabled={isUpdating} style={styles.saveButton} type=\"button\">\n Save\n </button>\n <button onClick={() => setEditingName(false)} style={styles.cancelButton} type=\"button\">\n Cancel\n </button>\n </div>\n ) : (\n <div style={styles.editRow}>\n <span style={styles.channelName}>{channelName}</span>\n <button onClick={() => setEditingName(true)} style={styles.editButton} type=\"button\">\n Edit\n </button>\n </div>\n )}\n </div>\n\n {/* Participants */}\n <div style={styles.section}>\n <div style={styles.sectionHeader}>\n <label style={styles.label}>Participants ({participants.length})</label>\n <button onClick={() => setShowInvite(!showInvite)} style={styles.addButton} type=\"button\">\n + Add\n </button>\n </div>\n\n {/* Invite form */}\n {showInvite && (\n <div style={styles.inviteForm}>\n <input\n value={inviteId}\n onChange={(e) => setInviteId(e.target.value)}\n placeholder=\"User ID\"\n style={styles.input}\n />\n <input\n value={inviteName}\n onChange={(e) => setInviteName(e.target.value)}\n placeholder=\"User Name\"\n style={styles.input}\n />\n <select\n value={inviteRole}\n onChange={(e) => setInviteRole(e.target.value as UserRole)}\n style={styles.input}\n >\n <option value=\"radiologist\">Radiologist</option>\n <option value=\"lab\">Lab</option>\n <option value=\"physician\">Physician</option>\n <option value=\"admin\">Admin</option>\n </select>\n <div style={styles.inviteActions}>\n <button onClick={handleInvite} disabled={isUpdating} style={styles.saveButton} type=\"button\">\n Invite\n </button>\n <button onClick={() => setShowInvite(false)} style={styles.cancelButton} type=\"button\">\n Cancel\n </button>\n </div>\n </div>\n )}\n\n <ParticipantsList\n participants={participants}\n currentUserId={currentUserId}\n isAdmin={isAdmin}\n onRemoveUser={onRemoveUser}\n />\n </div>\n\n {/* Actions */}\n <div style={styles.dangerZone}>\n <button onClick={onLeaveChannel} disabled={isUpdating} style={styles.leaveButton} type=\"button\">\n Leave Channel\n </button>\n\n {isAdmin && (\n <button\n onClick={handleDelete}\n disabled={isUpdating}\n style={confirmDelete ? styles.confirmDeleteButton : styles.deleteButton}\n type=\"button\"\n >\n {confirmDelete ? 'Confirm Delete' : 'Delete Channel'}\n </button>\n )}\n </div>\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n backgroundColor: '#ffffff',\n },\n header: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '12px 16px',\n borderBottom: '1px solid #e5e7eb',\n },\n title: {\n margin: 0,\n fontSize: '16px',\n fontWeight: 600,\n },\n closeButton: {\n width: '28px',\n height: '28px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '14px',\n color: '#6b7280',\n },\n error: {\n padding: '8px 16px',\n fontSize: '13px',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n },\n section: {\n padding: '16px',\n borderBottom: '1px solid #f3f4f6',\n },\n sectionHeader: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n marginBottom: '8px',\n },\n label: {\n fontSize: '12px',\n fontWeight: 600,\n color: '#6b7280',\n textTransform: 'uppercase' as const,\n letterSpacing: '0.05em',\n },\n channelName: {\n fontSize: '14px',\n color: '#111827',\n },\n editRow: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginTop: '6px',\n },\n input: {\n padding: '6px 10px',\n fontSize: '13px',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n outline: 'none',\n width: '100%',\n },\n editButton: {\n padding: '4px 10px',\n fontSize: '12px',\n color: '#2563eb',\n backgroundColor: 'transparent',\n border: 'none',\n cursor: 'pointer',\n },\n saveButton: {\n padding: '6px 12px',\n fontSize: '12px',\n fontWeight: 500,\n color: '#ffffff',\n backgroundColor: '#2563eb',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n whiteSpace: 'nowrap' as const,\n },\n cancelButton: {\n padding: '6px 12px',\n fontSize: '12px',\n color: '#6b7280',\n backgroundColor: 'transparent',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n cursor: 'pointer',\n whiteSpace: 'nowrap' as const,\n },\n addButton: {\n padding: '4px 10px',\n fontSize: '12px',\n fontWeight: 500,\n color: '#2563eb',\n backgroundColor: '#eff6ff',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n },\n inviteForm: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '8px',\n padding: '12px',\n marginBottom: '12px',\n backgroundColor: '#f9fafb',\n borderRadius: '8px',\n },\n inviteActions: {\n display: 'flex',\n gap: '8px',\n },\n dangerZone: {\n padding: '16px',\n marginTop: 'auto',\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '8px',\n },\n leaveButton: {\n padding: '8px',\n fontSize: '13px',\n fontWeight: 500,\n color: '#b45309',\n backgroundColor: '#fffbeb',\n border: '1px solid #fde68a',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n deleteButton: {\n padding: '8px',\n fontSize: '13px',\n fontWeight: 500,\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n confirmDeleteButton: {\n padding: '8px',\n fontSize: '13px',\n fontWeight: 600,\n color: '#ffffff',\n backgroundColor: '#dc2626',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n};\n","import React, { useState } from 'react';\nimport type { Message } from '../core/types';\n\ninterface PinnedMessagesBarProps {\n pinnedMessages: Message[];\n /** Clicking a pinned message scrolls to it in the thread */\n onJumpTo: (messageId: string) => void;\n /** Called when user unpins a message */\n onUnpin: (messageId: string) => void;\n className?: string;\n}\n\n/**\n * Horizontal strip at the top of the thread showing pinned messages (max 3).\n * Cycles through them on click if more than one.\n */\nexport function PinnedMessagesBar({\n pinnedMessages,\n onJumpTo,\n onUnpin,\n className,\n}: PinnedMessagesBarProps) {\n const [index, setIndex] = useState(0);\n\n if (pinnedMessages.length === 0) return null;\n\n const safeIndex = Math.min(index, pinnedMessages.length - 1);\n const current = pinnedMessages[safeIndex];\n const preview = renderPinPreview(current);\n\n const handleClick = () => {\n onJumpTo(current.id);\n if (pinnedMessages.length > 1) {\n setIndex((prev) => (prev + 1) % pinnedMessages.length);\n }\n };\n\n return (\n <div className={className} style={styles.container}>\n <div style={styles.indicator}>\n <span style={styles.pinIcon}>📌</span>\n {pinnedMessages.length > 1 && (\n <div style={styles.segments}>\n {pinnedMessages.map((_, i) => (\n <span\n key={i}\n style={{\n ...styles.segment,\n backgroundColor: i === safeIndex ? '#2563eb' : '#d1d5db',\n }}\n />\n ))}\n </div>\n )}\n </div>\n\n <button\n onClick={handleClick}\n style={styles.contentButton}\n type=\"button\"\n title=\"Click to jump to message\"\n >\n <div style={styles.label}>\n Pinned {pinnedMessages.length > 1 ? `(${safeIndex + 1}/${pinnedMessages.length})` : ''}\n </div>\n <div style={styles.preview}>\n <span style={styles.sender}>{current.senderName}:</span> {preview}\n </div>\n </button>\n\n <button\n onClick={(e) => {\n e.stopPropagation();\n onUnpin(current.id);\n }}\n style={styles.unpinButton}\n title=\"Unpin this message\"\n type=\"button\"\n >\n ✕\n </button>\n </div>\n );\n}\n\nfunction renderPinPreview(message: Message): string {\n switch (message.type) {\n case 'audio':\n return '🎤 Voice message';\n case 'image':\n return `📷 ${message.fileName || 'Image'}`;\n case 'file':\n return `📎 ${message.fileName || 'File'}`;\n case 'deep_link':\n return `🔗 ${message.body}`;\n default: {\n const body = message.body || '';\n return body.length > 100 ? `${body.slice(0, 100)}…` : body;\n }\n }\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '6px 12px',\n backgroundColor: '#eff6ff',\n borderBottom: '1px solid #dbeafe',\n },\n indicator: {\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n flexShrink: 0,\n },\n pinIcon: {\n fontSize: '13px',\n },\n segments: {\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n },\n segment: {\n width: '3px',\n height: '6px',\n borderRadius: '1px',\n },\n contentButton: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n padding: '2px 0',\n backgroundColor: 'transparent',\n border: 'none',\n textAlign: 'left',\n cursor: 'pointer',\n minWidth: 0,\n overflow: 'hidden',\n },\n label: {\n fontSize: '11px',\n fontWeight: 600,\n color: '#2563eb',\n },\n preview: {\n fontSize: '12px',\n color: '#374151',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n sender: {\n fontWeight: 600,\n },\n unpinButton: {\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#6b7280',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '11px',\n flexShrink: 0,\n },\n};\n","import React, { useRef, useState } from 'react';\nimport { useConversation } from '../hooks/useConversation';\nimport { useChannelSettings } from '../hooks/useChannelSettings';\nimport { useDeepLinks } from '../hooks/useDeepLinks';\nimport { useCollab } from '../context/CollabProvider';\nimport { PatientHeader } from './PatientHeader';\nimport { MessageList, type MessageListHandle } from './MessageList';\nimport { MessageInput } from './MessageInput';\nimport { ChannelSettings } from './ChannelSettings';\nimport { PinnedMessagesBar } from './PinnedMessagesBar';\nimport { MAX_PINNED_MESSAGES } from '../core/constants';\nimport type { PatientData } from '../core/types';\n\ninterface CollabPanelProps {\n /** Order ID — one conversation per study */\n orderId: string;\n /** Patient/study data displayed in the header */\n patientData: PatientData;\n /** Participant user IDs — only used when creating a brand-new conversation */\n participantIds?: string[];\n /** Show \"seen by\" indicator under own messages (default true) */\n showSeenBy?: boolean;\n /** Custom class name for the outer container */\n className?: string;\n /** Custom inline styles for the outer container */\n style?: React.CSSProperties;\n}\n\n/**\n * Full collaboration panel: patient header + pinned bar + message thread + input.\n * Supports reply, pin/unpin, and (optionally) seen-by indicators.\n */\nexport function CollabPanel({\n orderId,\n patientData,\n participantIds,\n showSeenBy = true,\n className,\n style,\n}: CollabPanelProps) {\n const { config } = useCollab();\n const [showSettings, setShowSettings] = useState(false);\n const messageListRef = useRef<MessageListHandle>(null);\n\n const {\n conversation,\n messages,\n pinnedMessages,\n participants,\n typingUsers,\n isLoading,\n hasMore,\n error,\n replyTo,\n setReplyTo,\n sendMessage,\n sendAudioMessage,\n sendFileMessage,\n sendTyping,\n markAsRead,\n loadMoreMessages,\n pinMessage,\n unpinMessage,\n } = useConversation({ orderId, patientData, participantIds });\n\n const channelSettings = useChannelSettings({\n conversationId: conversation?.id ?? null,\n });\n\n const { handleDeepLink } = useDeepLinks();\n\n const handleOpenDicom = () => {\n if (patientData.studyId && patientData.storageId && config.onOpenDicom) {\n config.onOpenDicom(patientData.studyId, patientData.storageId);\n }\n };\n\n const handleJumpToMessage = (messageId: string) => {\n messageListRef.current?.scrollToMessage(messageId);\n };\n\n const handleCopy = async (text: string) => {\n try {\n if (navigator.clipboard) {\n await navigator.clipboard.writeText(text);\n }\n } catch {\n // Silent fail — clipboard not available\n }\n };\n\n const pinDisabled = pinnedMessages.length >= MAX_PINNED_MESSAGES;\n\n if (error) {\n return (\n <div className={className} style={{ ...panelStyles.container, ...style }}>\n <div style={panelStyles.errorState}>\n <p style={panelStyles.errorTitle}>Unable to load conversation</p>\n <p style={panelStyles.errorMessage}>{error}</p>\n </div>\n </div>\n );\n }\n\n if (isLoading && !conversation) {\n return (\n <div className={className} style={{ ...panelStyles.container, ...style }}>\n <div style={panelStyles.loadingState}>Loading conversation...</div>\n </div>\n );\n }\n\n return (\n <div className={className} style={{ ...panelStyles.container, ...style }}>\n {showSettings && conversation ? (\n <ChannelSettings\n conversationId={conversation.id}\n channelName={conversation.name}\n channelPicture={conversation.picture}\n participants={participants}\n currentUserId={config.userId}\n isAdmin={channelSettings.isAdmin}\n isUpdating={channelSettings.isUpdating}\n error={channelSettings.error}\n onUpdateChannel={channelSettings.updateChannel}\n onInviteUser={channelSettings.inviteUser}\n onRemoveUser={channelSettings.removeUser}\n onLeaveChannel={channelSettings.leaveChannel}\n onDeleteChannel={channelSettings.deleteChannel}\n onClose={() => setShowSettings(false)}\n />\n ) : (\n <>\n <PatientHeader\n patientData={patientData}\n participants={participants}\n onOpenDicom={handleOpenDicom}\n onOpenSettings={() => setShowSettings(true)}\n />\n\n {pinnedMessages.length > 0 && (\n <PinnedMessagesBar\n pinnedMessages={pinnedMessages}\n onJumpTo={handleJumpToMessage}\n onUnpin={unpinMessage}\n />\n )}\n\n <MessageList\n ref={messageListRef}\n messages={messages}\n currentUserId={config.userId}\n participants={participants}\n showSeenBy={showSeenBy}\n typingUsers={typingUsers}\n hasMore={hasMore}\n isLoading={isLoading}\n onLoadMore={loadMoreMessages}\n onDeepLinkClick={handleDeepLink}\n onMessageVisible={markAsRead}\n onReply={setReplyTo}\n onPin={pinMessage}\n onUnpin={unpinMessage}\n onCopy={handleCopy}\n pinDisabled={pinDisabled}\n />\n\n <MessageInput\n onSendText={sendMessage}\n onSendAudio={sendAudioMessage}\n onSendFile={sendFileMessage}\n onTyping={sendTyping}\n replyTo={replyTo}\n onCancelReply={() => setReplyTo(null)}\n />\n </>\n )}\n </div>\n );\n}\n\nconst panelStyles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n backgroundColor: '#ffffff',\n borderRadius: '8px',\n overflow: 'hidden',\n border: '1px solid #e5e7eb',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n },\n loadingState: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n fontSize: '14px',\n color: '#9ca3af',\n },\n errorState: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n padding: '24px',\n textAlign: 'center',\n },\n errorTitle: {\n fontSize: '15px',\n fontWeight: 500,\n color: '#dc2626',\n margin: '0 0 4px',\n },\n errorMessage: {\n fontSize: '13px',\n color: '#6b7280',\n margin: 0,\n },\n};\n","import React, { useState, useRef, useCallback, useEffect } from 'react';\nimport { CollabPanel } from './CollabPanel';\nimport { buildChannelName } from '../core/channelName';\nimport type { PatientData } from '../core/types';\n\ninterface CollabPopupProps {\n /** Order ID for this conversation */\n orderId: string;\n /** Patient/study data */\n patientData: PatientData;\n /** Participant user IDs — only used when creating a brand-new conversation */\n participantIds?: string[];\n /** Whether the popup is open */\n isOpen: boolean;\n /** Close the popup */\n onClose: () => void;\n /** Initial position (defaults to bottom-right) */\n initialPosition?: { x: number; y: number };\n /** Width of the popup */\n width?: number;\n /** Height of the popup */\n height?: number;\n className?: string;\n}\n\n/**\n * Draggable floating chat popup — drop-in replacement for DraggableChatPopup.\n * Renders a CollabPanel inside a movable, resizable container.\n */\nexport function CollabPopup({\n orderId,\n patientData,\n participantIds,\n isOpen,\n onClose,\n initialPosition,\n width = 380,\n height = 520,\n className,\n}: CollabPopupProps) {\n // Default spawn: anchored bottom-right but offset vertically by enough\n // to clear a standard FAB (56px) + its 24px margin + visual breathing room\n // so the popup never lands on top of a host-app launcher button.\n const [position, setPosition] = useState(\n initialPosition || {\n x: window.innerWidth - width - 24,\n y: Math.max(24, window.innerHeight - height - 104),\n }\n );\n const [isDragging, setIsDragging] = useState(false);\n const [isMinimized, setIsMinimized] = useState(false);\n const dragOffset = useRef({ x: 0, y: 0 });\n const containerRef = useRef<HTMLDivElement>(null);\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n // Only allow dragging from the drag handle area\n if (!(e.target as HTMLElement).closest('[data-drag-handle]')) return;\n\n setIsDragging(true);\n dragOffset.current = {\n x: e.clientX - position.x,\n y: e.clientY - position.y,\n };\n e.preventDefault();\n },\n [position]\n );\n\n // ESC key to close — works only when popup is open\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose();\n }\n };\n\n window.addEventListener('keydown', handleKey);\n return () => window.removeEventListener('keydown', handleKey);\n }, [isOpen, onClose]);\n\n useEffect(() => {\n if (!isDragging) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n setPosition({\n x: Math.max(0, Math.min(e.clientX - dragOffset.current.x, window.innerWidth - width)),\n y: Math.max(0, Math.min(e.clientY - dragOffset.current.y, window.innerHeight - (isMinimized ? 48 : height))),\n });\n };\n\n const handleMouseUp = () => {\n setIsDragging(false);\n };\n\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n };\n }, [isDragging, width, height, isMinimized]);\n\n if (!isOpen) return null;\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{\n ...styles.container,\n left: position.x,\n top: position.y,\n width,\n height: isMinimized ? 48 : height,\n cursor: isDragging ? 'grabbing' : 'default',\n }}\n onMouseDown={handleMouseDown}\n >\n {/* Drag handle / title bar */}\n <div data-drag-handle style={styles.titleBar}>\n <span style={styles.titleText}>{buildChannelName(patientData)}</span>\n <div style={styles.titleActions}>\n <button\n onClick={() => setIsMinimized(!isMinimized)}\n style={styles.titleButton}\n title={isMinimized ? 'Expand' : 'Minimize'}\n type=\"button\"\n >\n {isMinimized ? '▢' : '—'}\n </button>\n <button onClick={onClose} style={styles.titleButton} title=\"Close\" type=\"button\">\n ✕\n </button>\n </div>\n </div>\n\n {/* Panel content */}\n {!isMinimized && (\n <div style={styles.panelWrapper}>\n <CollabPanel orderId={orderId} patientData={patientData} participantIds={participantIds} />\n </div>\n )}\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n position: 'fixed',\n zIndex: 9999,\n borderRadius: '12px',\n boxShadow: '0 8px 30px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08)',\n overflow: 'hidden',\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: '#ffffff',\n border: '1px solid #e5e7eb',\n transition: 'height 0.2s ease',\n },\n titleBar: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '0 12px',\n height: '48px',\n backgroundColor: '#1e293b',\n cursor: 'grab',\n userSelect: 'none',\n flexShrink: 0,\n },\n titleText: {\n fontSize: '13px',\n fontWeight: 500,\n color: '#ffffff',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n titleActions: {\n display: 'flex',\n gap: '4px',\n flexShrink: 0,\n },\n titleButton: {\n width: '28px',\n height: '28px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '13px',\n color: '#94a3b8',\n },\n panelWrapper: {\n flex: 1,\n overflow: 'hidden',\n },\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type {\n ConversationPreview,\n Message,\n Participant,\n PatientData,\n SendMessagePayload,\n} from '../core/types';\nimport { buildChannelName } from '../core/channelName';\n\ninterface UseInlineCollabOptions {\n orderId: string;\n patientData: PatientData;\n /** Participant IDs passed to the backend only when creating a new conversation */\n participantIds?: string[];\n /** Max messages to keep in inline state (default 5) */\n messageLimit?: number;\n}\n\ninterface UseInlineCollabReturn {\n hasConversation: boolean;\n messages: Message[];\n participants: Participant[];\n unreadCount: number;\n isLoading: boolean;\n isSubscribed: boolean;\n error: string | null;\n sendMessage: (body: string) => Promise<void>;\n /** Send a voice message — uploads the blob via config.onUploadFile first */\n sendAudioMessage: (audioBlob: Blob, duration: number) => Promise<void>;\n /** Attach to the DOM element that represents the row — drives lazy socket subscription */\n containerRef: (element: HTMLElement | null) => void;\n}\n\n/**\n * Lightweight hook for inline chat in table rows.\n *\n * Behavior:\n * - On mount: fetches preview (batched) — no socket work\n * - If conversation exists AND row becomes visible: joins Phoenix channel (real-time)\n * - If row scrolls out of view: leaves channel (frees resources)\n * - First sendMessage creates conversation atomically + starts real-time flow\n * - Subsequent sends go through the socket\n */\nexport function useInlineCollab({\n orderId,\n patientData,\n participantIds = [],\n messageLimit = 5,\n}: UseInlineCollabOptions): UseInlineCollabReturn {\n const {\n socket,\n config,\n requestPreview,\n invalidatePreview,\n createConversationWithMessage,\n } = useCollab();\n\n const [preview, setPreview] = useState<ConversationPreview | null>(null);\n const [messages, setMessages] = useState<Message[]>([]);\n const [participants, setParticipants] = useState<Participant[]>([]);\n const [unreadCount, setUnreadCount] = useState(0);\n const [isLoading, setIsLoading] = useState(true);\n const [isSubscribed, setIsSubscribed] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const elementRef = useRef<HTMLElement | null>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n const subscribedConversationIdRef = useRef<string | null>(null);\n\n const trimToLimit = useCallback(\n (msgs: Message[]): Message[] =>\n msgs.length > messageLimit ? msgs.slice(msgs.length - messageLimit) : msgs,\n [messageLimit]\n );\n\n const buildName = useCallback(\n (): string => buildChannelName(patientData),\n [patientData]\n );\n\n // ── Fetch preview on mount (batched) ──\n useEffect(() => {\n let cancelled = false;\n\n const load = async () => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await requestPreview(orderId);\n if (cancelled) return;\n setPreview(result);\n if (result) {\n setMessages(trimToLimit(result.lastMessages));\n setParticipants(result.participants);\n setUnreadCount(result.unreadCount);\n }\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err.message : 'Failed to load preview');\n } finally {\n if (!cancelled) setIsLoading(false);\n }\n };\n\n load();\n return () => {\n cancelled = true;\n };\n }, [orderId, requestPreview, trimToLimit]);\n\n // ── Subscribe/unsubscribe socket based on visibility ──\n const subscribe = useCallback(\n (conversationId: string) => {\n if (subscribedConversationIdRef.current === conversationId) return;\n\n socket.joinConversation(conversationId, {\n onMessage: (msg) => {\n setMessages((prev) => trimToLimit([...prev, msg]));\n if (msg.senderId !== config.userId) {\n setUnreadCount((prev) => prev + 1);\n }\n },\n onUserJoined: (participant) => {\n setParticipants((prev) =>\n prev.some((p) => p.userId === participant.userId) ? prev : [...prev, participant]\n );\n },\n onUserLeft: (participant) => {\n setParticipants((prev) => prev.filter((p) => p.userId !== participant.userId));\n },\n });\n\n subscribedConversationIdRef.current = conversationId;\n setIsSubscribed(true);\n },\n [socket, trimToLimit, config.userId]\n );\n\n const unsubscribe = useCallback(() => {\n const convId = subscribedConversationIdRef.current;\n if (convId) {\n socket.leaveConversation(convId);\n subscribedConversationIdRef.current = null;\n setIsSubscribed(false);\n }\n }, [socket]);\n\n // ── IntersectionObserver lifecycle ──\n const containerRef = useCallback(\n (element: HTMLElement | null) => {\n // Teardown old observer\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n\n elementRef.current = element;\n if (!element) return;\n\n observerRef.current = new IntersectionObserver(\n (entries) => {\n const entry = entries[0];\n if (!entry) return;\n\n const convId = preview?.conversationId;\n if (!convId) return;\n\n if (entry.isIntersecting) {\n subscribe(convId);\n } else {\n unsubscribe();\n }\n },\n { threshold: 0.1 }\n );\n\n observerRef.current.observe(element);\n },\n [preview, subscribe, unsubscribe]\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (observerRef.current) observerRef.current.disconnect();\n unsubscribe();\n };\n }, [unsubscribe]);\n\n // Re-attach observer when preview becomes available after element is mounted\n useEffect(() => {\n if (preview?.conversationId && elementRef.current && !observerRef.current) {\n containerRef(elementRef.current);\n }\n }, [preview, containerRef]);\n\n // ── Internal: send a message payload, lazy-creating the conversation on the first send ──\n const dispatchSend = useCallback(\n async (payload: SendMessagePayload) => {\n if (!preview) {\n // First message — create conversation + send atomically\n try {\n const result = await createConversationWithMessage(orderId, payload, {\n name: buildName(),\n participantIds,\n });\n\n const newPreview: ConversationPreview = {\n conversationId: result.conversation.id,\n orderId,\n messageCount: 1,\n unreadCount: 0,\n lastMessages: [result.message],\n participants: result.conversation.participants,\n name: result.conversation.name,\n };\n\n setPreview(newPreview);\n setMessages([result.message]);\n setParticipants(result.conversation.participants);\n invalidatePreview(orderId);\n\n if (elementRef.current) {\n subscribe(result.conversation.id);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to send message');\n config.onError?.({\n code: 'SEND_ERROR',\n message: 'Failed to send first message',\n details: err,\n });\n }\n return;\n }\n\n try {\n await socket.sendMessage(preview.conversationId, payload);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to send message');\n config.onError?.({\n code: 'SEND_ERROR',\n message: 'Failed to send message',\n details: err,\n });\n }\n },\n [\n preview,\n orderId,\n buildName,\n participantIds,\n createConversationWithMessage,\n invalidatePreview,\n subscribe,\n socket,\n config,\n ]\n );\n\n const sendMessage = useCallback(\n async (body: string) => {\n const trimmed = body.trim();\n if (!trimmed) return;\n await dispatchSend({ body: trimmed, type: 'text' });\n },\n [dispatchSend]\n );\n\n const sendAudioMessage = useCallback(\n async (audioBlob: Blob, duration: number) => {\n if (!config.onUploadFile) {\n setError('File upload is not configured');\n return;\n }\n try {\n const url = await config.onUploadFile(audioBlob, 'voice-message.webm');\n await dispatchSend({\n body: 'Voice message',\n type: 'audio',\n mediaUrl: url,\n mediaDuration: duration,\n });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to send voice message');\n config.onError?.({\n code: 'SEND_ERROR',\n message: 'Failed to send voice message',\n details: err,\n });\n }\n },\n [config, dispatchSend]\n );\n\n return {\n hasConversation: !!preview,\n messages,\n participants,\n unreadCount,\n isLoading,\n isSubscribed,\n error,\n sendMessage,\n sendAudioMessage,\n containerRef,\n };\n}\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { useInlineCollab } from '../hooks/useInlineCollab';\n// MIC DISABLED — voice messaging temporarily removed. Imports kept for easy re-enable.\n// import { useAudioRecorder } from '../hooks/useAudioRecorder';\n// import { MicIcon } from './icons/MicIcon';\nimport type { Message, PatientData, UserRole } from '../core/types';\n\ninterface CollabInlineProps {\n orderId: string;\n patientData: PatientData;\n /** User IDs to invite when the first message creates the conversation */\n participantIds?: string[];\n /** Called when user clicks the expand button — host opens the floating popup */\n onExpand?: () => void;\n /** Max inline messages to show (default 5) */\n messageLimit?: number;\n /** Placeholder text for the input */\n placeholder?: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Inline chat for table rows.\n *\n * Two states:\n * - No conversation yet: just an input bar (no socket, no preview)\n * - Conversation exists: last N messages + input + expand button\n *\n * Supports text and voice messages. File attachments and full chat features\n * stay in the floating popup / inbox.\n */\nexport function CollabInline({\n orderId,\n patientData,\n participantIds,\n onExpand,\n messageLimit = 5,\n placeholder = 'Type a message about this case...',\n className,\n style,\n}: CollabInlineProps) {\n const {\n hasConversation,\n messages,\n unreadCount,\n isLoading,\n isSubscribed,\n error,\n sendMessage,\n sendAudioMessage,\n containerRef,\n } = useInlineCollab({ orderId, patientData, participantIds, messageLimit });\n\n if (isLoading && !hasConversation) {\n return (\n <div className={className} style={{ ...styles.container, ...style }}>\n <div style={styles.loadingState}>Loading...</div>\n </div>\n );\n }\n\n return (\n <div ref={containerRef} className={className} style={{ ...styles.container, ...style }}>\n {hasConversation && messages.length > 0 && (\n <div style={styles.preview}>\n {messages.slice(-messageLimit).map((message) => (\n <InlineMessageRow key={message.id} message={message} />\n ))}\n </div>\n )}\n\n {error && <div style={styles.error}>{error}</div>}\n\n <InlineInputBar\n onSend={sendMessage}\n onSendAudio={sendAudioMessage}\n placeholder={placeholder}\n unreadCount={hasConversation ? unreadCount : 0}\n isLive={isSubscribed}\n showExpand={hasConversation && !!onExpand}\n onExpand={onExpand}\n />\n </div>\n );\n}\n\n// ─────────────────────────────────────────\n// Sub-components\n// ─────────────────────────────────────────\n\nfunction InlineMessageRow({ message }: { message: Message }) {\n if (message.type === 'system') {\n return (\n <div style={styles.systemRow}>\n <span style={styles.systemText}>{message.body}</span>\n </div>\n );\n }\n\n // Audio gets a compact play/pause + duration player inline\n if (message.type === 'audio' && message.mediaUrl) {\n return (\n <div style={styles.messageRow}>\n <RoleDot role={message.senderRole} />\n <span style={styles.senderName}>{message.senderName}:</span>\n <InlineAudioPlayer url={message.mediaUrl} duration={message.mediaDuration} />\n </div>\n );\n }\n\n const preview = renderMessagePreview(message);\n\n return (\n <div style={styles.messageRow}>\n <RoleDot role={message.senderRole} />\n <span style={styles.senderName}>{message.senderName}:</span>\n <span style={styles.messageText}>{preview}</span>\n </div>\n );\n}\n\nfunction RoleDot({ role }: { role: UserRole }) {\n const colors: Record<UserRole, string> = {\n radiologist: '#7c3aed',\n lab: '#2563eb',\n physician: '#059669',\n admin: '#dc2626',\n };\n\n return <span style={{ ...styles.roleDot, backgroundColor: colors[role] }} />;\n}\n\n/**\n * Compact audio player designed to fit in a single inline row.\n * Shows just a play/pause toggle + duration. No scrubber.\n */\nfunction InlineAudioPlayer({ url, duration }: { url: string; duration?: number }) {\n const audioRef = useRef<HTMLAudioElement>(null);\n const [isPlaying, setIsPlaying] = useState(false);\n const [currentTime, setCurrentTime] = useState(0);\n\n const toggle = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n const audio = audioRef.current;\n if (!audio) return;\n if (isPlaying) {\n audio.pause();\n } else {\n audio.play().catch(() => {\n // Silent fail — autoplay blocked, etc.\n });\n }\n },\n [isPlaying]\n );\n\n useEffect(() => {\n const audio = audioRef.current;\n if (!audio) return;\n\n const onPlay = () => setIsPlaying(true);\n const onPause = () => setIsPlaying(false);\n const onEnded = () => {\n setIsPlaying(false);\n setCurrentTime(0);\n };\n const onTimeUpdate = () => setCurrentTime(audio.currentTime);\n\n audio.addEventListener('play', onPlay);\n audio.addEventListener('pause', onPause);\n audio.addEventListener('ended', onEnded);\n audio.addEventListener('timeupdate', onTimeUpdate);\n\n return () => {\n audio.removeEventListener('play', onPlay);\n audio.removeEventListener('pause', onPause);\n audio.removeEventListener('ended', onEnded);\n audio.removeEventListener('timeupdate', onTimeUpdate);\n };\n }, []);\n\n const total = duration ?? 0;\n const remaining = Math.max(0, total - Math.floor(currentTime));\n const displayTime = isPlaying ? remaining : total;\n\n return (\n <span style={styles.audioPlayer}>\n <button\n onClick={toggle}\n style={styles.audioButton}\n title={isPlaying ? 'Pause' : 'Play'}\n type=\"button\"\n >\n {isPlaying ? '⏸' : '▶'}\n </button>\n <span style={styles.audioWaveform}>\n {/* Purely decorative bars */}\n <span style={{ ...styles.waveBar, height: '40%' }} />\n <span style={{ ...styles.waveBar, height: '80%' }} />\n <span style={{ ...styles.waveBar, height: '60%' }} />\n <span style={{ ...styles.waveBar, height: '90%' }} />\n <span style={{ ...styles.waveBar, height: '50%' }} />\n <span style={{ ...styles.waveBar, height: '70%' }} />\n <span style={{ ...styles.waveBar, height: '40%' }} />\n </span>\n <span style={styles.audioDuration}>{formatDuration(displayTime)}</span>\n <audio ref={audioRef} src={url} preload=\"metadata\" />\n </span>\n );\n}\n\nfunction renderMessagePreview(message: Message): string {\n switch (message.type) {\n case 'image':\n return `📷 ${message.fileName || 'Image'}`;\n case 'file':\n return `📎 ${message.fileName || 'File'}`;\n case 'deep_link':\n return `🔗 ${message.body}`;\n default:\n return message.body;\n }\n}\n\nfunction formatDuration(seconds: number): string {\n const safe = Math.max(0, Math.floor(seconds));\n const m = Math.floor(safe / 60);\n const s = safe % 60;\n return `${m}:${s.toString().padStart(2, '0')}`;\n}\n\ninterface InlineInputBarProps {\n onSend: (body: string) => Promise<void>;\n /** @deprecated MIC DISABLED — kept in prop signature for backward compat. */\n onSendAudio?: (blob: Blob, duration: number) => Promise<void>;\n placeholder: string;\n unreadCount: number;\n isLive: boolean;\n showExpand: boolean;\n onExpand?: () => void;\n}\n\nfunction InlineInputBar({\n onSend,\n // MIC DISABLED — onSendAudio accepted but unused.\n // onSendAudio,\n placeholder,\n unreadCount,\n isLive,\n showExpand,\n onExpand,\n}: InlineInputBarProps) {\n const [text, setText] = useState('');\n const [isSending, setIsSending] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n\n // MIC DISABLED — voice recorder hook + handlers not invoked. Restore by\n // uncommenting the destructure and handleStopRecording below (and the\n // imports at the top of the file).\n // const {\n // isRecording,\n // duration,\n // start: startRecording,\n // stop: stopRecording,\n // cancel: cancelRecording,\n // isSupported: micSupported,\n // error: micError,\n // } = useAudioRecorder();\n\n const handleSend = useCallback(async () => {\n const trimmed = text.trim();\n if (!trimmed || isSending) return;\n\n setIsSending(true);\n try {\n await onSend(trimmed);\n setText('');\n inputRef.current?.focus();\n } finally {\n setIsSending(false);\n }\n }, [text, isSending, onSend]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n },\n [handleSend]\n );\n\n // MIC DISABLED — audio stop handler unused. Restore alongside useAudioRecorder.\n // const handleStopRecording = useCallback(async () => {\n // const result = await stopRecording();\n // if (result) {\n // setIsSending(true);\n // try {\n // await onSendAudio(result.blob, result.duration);\n // } finally {\n // setIsSending(false);\n // }\n // }\n // }, [stopRecording, onSendAudio]);\n\n /* MIC DISABLED — recording mode branch removed. Original block kept here\n for easy re-enable when mic is restored:\n\n if (isRecording) {\n return (\n <div style={styles.recordingBar}>\n <span style={styles.recordingDot} />\n <span style={styles.recordingLabel}>Recording {formatDuration(duration)}</span>\n <button onClick={cancelRecording} style={styles.recordingCancel} title=\"Cancel recording\" type=\"button\">Cancel</button>\n <button onClick={handleStopRecording} style={styles.recordingSend} title=\"Send voice message\" type=\"button\">Send</button>\n </div>\n );\n }\n */\n\n return (\n <div style={styles.inputBar}>\n <input\n ref={inputRef}\n type=\"text\"\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={isSending}\n style={styles.input}\n />\n\n {unreadCount > 0 && (\n <span style={styles.unreadBadge} title={`${unreadCount} unread`}>\n {unreadCount > 99 ? '99+' : unreadCount}\n </span>\n )}\n\n {isLive && <span style={styles.liveDot} title=\"Live updates active\" />}\n\n {/* MIC DISABLED — mic button hidden. Original block:\n {micSupported && !text.trim() && (\n <button onClick={startRecording} disabled={isSending} style={styles.micButton} title=\"Record voice message\" type=\"button\">\n <MicIcon size={16} color=\"#374151\" />\n </button>\n )}\n */}\n\n {/* Send button — shown when there's text to send */}\n {text.trim() && (\n <button\n onClick={handleSend}\n disabled={isSending}\n style={styles.sendButton}\n title=\"Send message\"\n type=\"button\"\n >\n ➤\n </button>\n )}\n\n {showExpand && onExpand && (\n <button\n onClick={onExpand}\n style={styles.expandButton}\n title=\"Expand to full chat\"\n type=\"button\"\n >\n ⛶\n </button>\n )}\n </div>\n );\n}\n\n// ─────────────────────────────────────────\n// Styles\n// ─────────────────────────────────────────\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n flexDirection: 'column',\n width: '100%',\n padding: '6px 8px',\n backgroundColor: '#ffffff',\n border: '1px solid #e5e7eb',\n borderRadius: '8px',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n },\n loadingState: {\n padding: '8px',\n fontSize: '12px',\n color: '#9ca3af',\n textAlign: 'center',\n },\n error: {\n padding: '4px 8px',\n marginBottom: '4px',\n fontSize: '11px',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n borderRadius: '4px',\n },\n preview: {\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n marginBottom: '6px',\n paddingBottom: '6px',\n borderBottom: '1px solid #f3f4f6',\n },\n messageRow: {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n fontSize: '12px',\n lineHeight: '1.4',\n overflow: 'hidden',\n },\n roleDot: {\n flexShrink: 0,\n width: '6px',\n height: '6px',\n borderRadius: '50%',\n },\n senderName: {\n flexShrink: 0,\n fontWeight: 600,\n color: '#374151',\n },\n messageText: {\n color: '#4b5563',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n minWidth: 0,\n flex: 1,\n },\n systemRow: {\n fontSize: '11px',\n color: '#9ca3af',\n fontStyle: 'italic',\n textAlign: 'center',\n padding: '2px 0',\n },\n systemText: {\n opacity: 0.8,\n },\n // ── Audio player (inline) ──\n audioPlayer: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px',\n padding: '2px 8px',\n borderRadius: '12px',\n backgroundColor: '#eff6ff',\n border: '1px solid #dbeafe',\n flex: 1,\n minWidth: 0,\n },\n audioButton: {\n width: '20px',\n height: '20px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '10px',\n color: '#ffffff',\n backgroundColor: '#2563eb',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n flexShrink: 0,\n },\n audioWaveform: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '2px',\n height: '16px',\n flex: 1,\n minWidth: 0,\n },\n waveBar: {\n display: 'inline-block',\n width: '2px',\n borderRadius: '1px',\n backgroundColor: '#60a5fa',\n },\n audioDuration: {\n fontSize: '11px',\n color: '#2563eb',\n fontVariantNumeric: 'tabular-nums',\n fontWeight: 500,\n flexShrink: 0,\n },\n // ── Input bar ──\n inputBar: {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n },\n input: {\n flex: 1,\n padding: '6px 10px',\n fontSize: '13px',\n border: '1px solid #e5e7eb',\n borderRadius: '16px',\n outline: 'none',\n fontFamily: 'inherit',\n minWidth: 0,\n },\n unreadBadge: {\n flexShrink: 0,\n minWidth: '18px',\n height: '18px',\n padding: '0 5px',\n fontSize: '10px',\n fontWeight: 600,\n color: '#ffffff',\n backgroundColor: '#dc2626',\n borderRadius: '10px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n liveDot: {\n flexShrink: 0,\n width: '6px',\n height: '6px',\n borderRadius: '50%',\n backgroundColor: '#22c55e',\n },\n micButton: {\n flexShrink: 0,\n width: '28px',\n height: '28px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '13px',\n backgroundColor: '#f3f4f6',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n },\n sendButton: {\n flexShrink: 0,\n width: '28px',\n height: '28px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '13px',\n color: '#ffffff',\n backgroundColor: '#2563eb',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n },\n expandButton: {\n flexShrink: 0,\n width: '28px',\n height: '28px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '12px',\n color: '#6b7280',\n backgroundColor: 'transparent',\n border: '1px solid #e5e7eb',\n borderRadius: '50%',\n cursor: 'pointer',\n },\n // ── Recording mode ──\n recordingBar: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '6px 10px',\n backgroundColor: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: '16px',\n },\n recordingDot: {\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: '#dc2626',\n flexShrink: 0,\n animation: 'pulse 1.5s infinite',\n },\n recordingLabel: {\n flex: 1,\n fontSize: '12px',\n fontWeight: 500,\n color: '#dc2626',\n fontVariantNumeric: 'tabular-nums',\n },\n recordingCancel: {\n padding: '4px 10px',\n fontSize: '11px',\n color: '#6b7280',\n backgroundColor: '#ffffff',\n border: '1px solid #d1d5db',\n borderRadius: '12px',\n cursor: 'pointer',\n flexShrink: 0,\n },\n recordingSend: {\n padding: '4px 10px',\n fontSize: '11px',\n fontWeight: 500,\n color: '#ffffff',\n backgroundColor: '#dc2626',\n border: 'none',\n borderRadius: '12px',\n cursor: 'pointer',\n flexShrink: 0,\n },\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type { ConversationListItem } from '../core/types';\n\ninterface UseConversationListOptions {\n /**\n * When false, skips the initial auto-fetch. The caller can still invoke\n * `refresh()` manually (e.g. on user interaction). Defaults to true.\n */\n enabled?: boolean;\n}\n\ninterface UseConversationListReturn {\n conversations: ConversationListItem[];\n isLoading: boolean;\n error: string | null;\n refresh: () => Promise<void>;\n /** Filter conversations by query string (matches channel name + patient name) */\n filter: (query: string) => ConversationListItem[];\n /** Total unread across all conversations */\n totalUnread: number;\n}\n\n/**\n * Fetches the current user's full conversation list for the inbox.\n * Conversations are returned sorted by last activity (backend-sorted).\n *\n * Pass `{ enabled: false }` for lazy mode — useful when the list is behind\n * a click (e.g. a collapsed FAB panel) and you don't want to hit the API\n * until the user opens it.\n */\nexport function useConversationList(\n options?: UseConversationListOptions\n): UseConversationListReturn {\n const enabled = options?.enabled ?? true;\n const { fetchConversationList, config, totalUnread: serverTotalUnread } =\n useCollab();\n const [conversations, setConversations] = useState<ConversationListItem[]>([]);\n const [isLoading, setIsLoading] = useState(enabled);\n const [error, setError] = useState<string | null>(null);\n\n // Silent refresh (no spinner flash) — used for socket-driven resyncs so a\n // background update doesn't blink the list.\n const silentRefresh = useCallback(async () => {\n try {\n const list = await fetchConversationList();\n setConversations(list);\n } catch (err) {\n config.onError?.({\n code: 'LIST_ERROR',\n message: err instanceof Error ? err.message : 'Failed to load conversations',\n details: err,\n });\n }\n }, [fetchConversationList, config]);\n\n const refresh = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const list = await fetchConversationList();\n setConversations(list);\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to load conversations';\n setError(msg);\n config.onError?.({\n code: 'LIST_ERROR',\n message: msg,\n details: err,\n });\n } finally {\n setIsLoading(false);\n }\n }, [fetchConversationList, config]);\n\n useEffect(() => {\n if (!enabled) return;\n refresh();\n }, [enabled, refresh]);\n\n // Live resync: the server pushes an `unread_update` event on the user\n // notifications channel any time a message arrives, gets read, etc.\n // CollabProvider surfaces that as `serverTotalUnread`. When it changes\n // and the list is currently showing, pull fresh data silently so the\n // last-message / activity order / unread badges all stay in sync without\n // the user having to close and reopen the panel.\n //\n // Skip the first run — the main effect above already handled mount,\n // firing a silent refetch here on top would double-fetch.\n const hasHandledInitialUnreadRef = useRef(false);\n useEffect(() => {\n if (!enabled) return;\n if (!hasHandledInitialUnreadRef.current) {\n hasHandledInitialUnreadRef.current = true;\n return;\n }\n silentRefresh();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [serverTotalUnread, enabled]);\n\n const filter = useCallback(\n (query: string): ConversationListItem[] => {\n const q = query.trim().toLowerCase();\n if (!q) return conversations;\n return conversations.filter((c) => {\n const patient = c.patientSnapshot?.patientName?.toLowerCase() || '';\n const name = c.name.toLowerCase();\n return name.includes(q) || patient.includes(q);\n });\n },\n [conversations]\n );\n\n const totalUnread = conversations.reduce((sum, c) => sum + c.unreadCount, 0);\n\n return {\n conversations,\n isLoading,\n error,\n refresh,\n filter,\n totalUnread,\n };\n}\n","import React from 'react';\nimport type { ConversationListItem as ListItem, Message } from '../core/types';\nimport { formatInboxTimestamp } from '../core/dateLabels';\n\ninterface ConversationListItemProps {\n item: ListItem;\n isSelected: boolean;\n onClick: () => void;\n className?: string;\n}\n\n/**\n * Single row in the inbox sidebar — shows patient/channel name, last message\n * preview, timestamp, and unread badge.\n */\nexport function ConversationListItem({\n item,\n isSelected,\n onClick,\n className,\n}: ConversationListItemProps) {\n const hasUnread = item.unreadCount > 0;\n // Prefer the channel name (patient - lab - last4) so labels are consistent\n // everywhere a channel is shown.\n const displayName = item.name || item.patientSnapshot?.patientName || 'Unknown';\n\n return (\n <button\n className={className}\n onClick={onClick}\n style={{\n ...styles.container,\n ...(isSelected ? styles.selected : {}),\n ...(hasUnread ? styles.unread : {}),\n }}\n type=\"button\"\n >\n {/* Avatar / unread dot */}\n <div style={styles.avatarWrapper}>\n {item.picture ? (\n <img src={item.picture} alt=\"\" style={styles.avatar} />\n ) : (\n <div style={styles.avatarFallback}>{(displayName || '?').charAt(0).toUpperCase()}</div>\n )}\n {hasUnread && <span style={styles.unreadDot} />}\n </div>\n\n {/* Main content */}\n <div style={styles.content}>\n <div style={styles.topRow}>\n <span\n style={{\n ...styles.name,\n ...(hasUnread ? styles.nameUnread : {}),\n }}\n >\n {displayName}\n </span>\n <span\n style={{\n ...styles.time,\n ...(hasUnread ? styles.timeUnread : {}),\n }}\n >\n {formatInboxTimestamp(item.lastActivityAt)}\n </span>\n </div>\n\n <div style={styles.bottomRow}>\n <span\n style={{\n ...styles.preview,\n ...(hasUnread ? styles.previewUnread : {}),\n }}\n >\n {renderLastMessagePreview(item.lastMessage)}\n </span>\n {hasUnread && (\n <span style={styles.badge}>\n {item.unreadCount > 99 ? '99+' : item.unreadCount}\n </span>\n )}\n </div>\n </div>\n </button>\n );\n}\n\nfunction renderLastMessagePreview(message?: Message): string {\n if (!message) return 'No messages yet';\n\n const prefix = message.senderName ? `${message.senderName}: ` : '';\n\n switch (message.type) {\n case 'audio':\n return `${prefix}🎤 Voice message`;\n case 'image':\n return `${prefix}📷 ${message.fileName || 'Image'}`;\n case 'file':\n return `${prefix}📎 ${message.fileName || 'File'}`;\n case 'deep_link':\n return `${prefix}🔗 ${message.body}`;\n case 'system':\n return message.body;\n default: {\n const body = message.body || '';\n const preview = body.length > 60 ? `${body.slice(0, 60)}…` : body;\n return `${prefix}${preview}`;\n }\n }\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '10px 12px',\n width: '100%',\n backgroundColor: 'transparent',\n border: 'none',\n borderBottom: '1px solid #f3f4f6',\n cursor: 'pointer',\n textAlign: 'left',\n },\n selected: {\n backgroundColor: '#eff6ff',\n },\n unread: {},\n avatarWrapper: {\n position: 'relative',\n width: '40px',\n height: '40px',\n flexShrink: 0,\n },\n avatar: {\n width: '40px',\n height: '40px',\n borderRadius: '50%',\n objectFit: 'cover',\n },\n avatarFallback: {\n width: '40px',\n height: '40px',\n borderRadius: '50%',\n backgroundColor: '#e5e7eb',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '15px',\n fontWeight: 600,\n color: '#6b7280',\n },\n unreadDot: {\n position: 'absolute',\n top: '0',\n left: '0',\n width: '10px',\n height: '10px',\n borderRadius: '50%',\n backgroundColor: '#2563eb',\n border: '2px solid #ffffff',\n },\n content: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n minWidth: 0,\n },\n topRow: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'baseline',\n gap: '8px',\n },\n name: {\n fontSize: '14px',\n fontWeight: 500,\n color: '#111827',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n flex: 1,\n minWidth: 0,\n },\n nameUnread: {\n fontWeight: 700,\n },\n studyType: {\n fontSize: '12px',\n fontWeight: 400,\n color: '#6b7280',\n },\n time: {\n fontSize: '11px',\n color: '#9ca3af',\n flexShrink: 0,\n },\n timeUnread: {\n color: '#2563eb',\n fontWeight: 600,\n },\n bottomRow: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n gap: '8px',\n },\n preview: {\n fontSize: '13px',\n color: '#6b7280',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n flex: 1,\n minWidth: 0,\n },\n previewUnread: {\n color: '#111827',\n fontWeight: 500,\n },\n badge: {\n minWidth: '20px',\n height: '20px',\n padding: '0 6px',\n fontSize: '11px',\n fontWeight: 600,\n color: '#ffffff',\n backgroundColor: '#2563eb',\n borderRadius: '10px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n },\n};\n","import React, { useMemo, useState } from 'react';\nimport { ConversationListItem } from './ConversationListItem';\nimport type { ConversationListItem as ListItem } from '../core/types';\n\ninterface ConversationListProps {\n conversations: ListItem[];\n selectedId: string | null;\n isLoading: boolean;\n error: string | null;\n onSelect: (item: ListItem) => void;\n /** Optional title shown above the list */\n title?: string;\n className?: string;\n}\n\n/**\n * Scrollable sidebar list of conversations with search and unread filter.\n */\nexport function ConversationList({\n conversations,\n selectedId,\n isLoading,\n error,\n onSelect,\n title = 'Conversations',\n className,\n}: ConversationListProps) {\n const [query, setQuery] = useState('');\n const [showUnreadOnly, setShowUnreadOnly] = useState(false);\n\n const filtered = useMemo(() => {\n let result = conversations;\n\n if (showUnreadOnly) {\n result = result.filter((c) => c.unreadCount > 0);\n }\n\n const q = query.trim().toLowerCase();\n if (q) {\n result = result.filter((c) => {\n const patient = c.patientSnapshot?.patientName?.toLowerCase() || '';\n const name = c.name.toLowerCase();\n return name.includes(q) || patient.includes(q);\n });\n }\n\n return result;\n }, [conversations, query, showUnreadOnly]);\n\n const totalUnread = conversations.reduce((sum, c) => sum + c.unreadCount, 0);\n\n return (\n <div className={className} style={styles.container}>\n <div style={styles.header}>\n <div style={styles.titleRow}>\n <h3 style={styles.title}>{title}</h3>\n {totalUnread > 0 && <span style={styles.totalBadge}>{totalUnread}</span>}\n </div>\n\n <div style={styles.searchRow}>\n <input\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search patients or channels...\"\n style={styles.searchInput}\n />\n </div>\n\n <div style={styles.filterRow}>\n <button\n onClick={() => setShowUnreadOnly(false)}\n style={{\n ...styles.filterButton,\n ...(!showUnreadOnly ? styles.filterButtonActive : {}),\n }}\n type=\"button\"\n >\n All\n </button>\n <button\n onClick={() => setShowUnreadOnly(true)}\n style={{\n ...styles.filterButton,\n ...(showUnreadOnly ? styles.filterButtonActive : {}),\n }}\n type=\"button\"\n >\n Unread {totalUnread > 0 && `(${totalUnread})`}\n </button>\n </div>\n </div>\n\n <div style={styles.list}>\n {isLoading && <div style={styles.state}>Loading conversations...</div>}\n {error && <div style={styles.errorState}>{error}</div>}\n\n {!isLoading && !error && filtered.length === 0 && (\n <div style={styles.state}>\n {query ? 'No matching conversations' : 'No conversations yet'}\n </div>\n )}\n\n {filtered.map((item) => (\n <ConversationListItem\n key={item.id}\n item={item}\n isSelected={selectedId === item.id}\n onClick={() => onSelect(item)}\n />\n ))}\n </div>\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n backgroundColor: '#ffffff',\n borderRight: '1px solid #e5e7eb',\n },\n header: {\n padding: '12px',\n borderBottom: '1px solid #e5e7eb',\n backgroundColor: '#f9fafb',\n flexShrink: 0,\n },\n titleRow: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginBottom: '8px',\n },\n title: {\n margin: 0,\n fontSize: '15px',\n fontWeight: 600,\n color: '#111827',\n },\n totalBadge: {\n minWidth: '20px',\n height: '20px',\n padding: '0 6px',\n fontSize: '11px',\n fontWeight: 600,\n color: '#ffffff',\n backgroundColor: '#2563eb',\n borderRadius: '10px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n searchRow: {\n marginBottom: '8px',\n },\n searchInput: {\n width: '100%',\n padding: '6px 10px',\n fontSize: '13px',\n border: '1px solid #e5e7eb',\n borderRadius: '6px',\n outline: 'none',\n fontFamily: 'inherit',\n },\n filterRow: {\n display: 'flex',\n gap: '4px',\n },\n filterButton: {\n flex: 1,\n padding: '5px 8px',\n fontSize: '12px',\n color: '#6b7280',\n backgroundColor: '#ffffff',\n border: '1px solid #e5e7eb',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n filterButtonActive: {\n color: '#ffffff',\n backgroundColor: '#2563eb',\n borderColor: '#2563eb',\n fontWeight: 500,\n },\n list: {\n flex: 1,\n overflowY: 'auto',\n },\n state: {\n padding: '24px 16px',\n fontSize: '13px',\n color: '#9ca3af',\n textAlign: 'center',\n },\n errorState: {\n padding: '16px',\n fontSize: '13px',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n margin: '12px',\n borderRadius: '6px',\n textAlign: 'center',\n },\n};\n","import React, { useState } from 'react';\nimport { useConversationList } from '../hooks/useConversationList';\nimport { ConversationList } from './ConversationList';\nimport { CollabPanel } from './CollabPanel';\nimport type { ConversationListItem, PatientData } from '../core/types';\n\ninterface CollabInboxProps {\n /** Optional: preselect a specific conversation (by conversation ID) */\n initialConversationId?: string;\n /** Optional callback when the user selects a conversation */\n onSelectConversation?: (item: ConversationListItem) => void;\n /** Title for the sidebar */\n title?: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Full-page inbox — WhatsApp-style sidebar of all user's conversations\n * with the selected conversation's CollabPanel on the right.\n *\n * Uses the same CollabPanel as the floating popup, so all features\n * (reply, pin, seen-by, DICOM, voice, attachments) are available.\n */\nexport function CollabInbox({\n initialConversationId,\n onSelectConversation,\n title,\n className,\n style,\n}: CollabInboxProps) {\n const { conversations, isLoading, error } = useConversationList();\n const [selectedId, setSelectedId] = useState<string | null>(initialConversationId ?? null);\n\n const selected = conversations.find((c) => c.id === selectedId) || null;\n\n const handleSelect = (item: ConversationListItem) => {\n setSelectedId(item.id);\n onSelectConversation?.(item);\n };\n\n return (\n <div className={className} style={{ ...styles.container, ...style }}>\n <div style={styles.sidebar}>\n <ConversationList\n conversations={conversations}\n selectedId={selectedId}\n isLoading={isLoading}\n error={error}\n onSelect={handleSelect}\n title={title}\n />\n </div>\n\n <div style={styles.main}>\n {selected ? (\n <CollabPanel\n key={selected.id}\n orderId={selected.orderId}\n patientData={buildPatientData(selected)}\n showSeenBy={true}\n style={styles.panel}\n />\n ) : (\n <EmptyState hasAny={conversations.length > 0} />\n )}\n </div>\n </div>\n );\n}\n\nfunction buildPatientData(item: ConversationListItem): PatientData {\n if (item.patientSnapshot) return item.patientSnapshot;\n\n // Fallback — build minimal PatientData from available fields\n return {\n patientName: item.name,\n orderId: item.orderId,\n };\n}\n\nfunction EmptyState({ hasAny }: { hasAny: boolean }) {\n return (\n <div style={styles.empty}>\n <div style={styles.emptyIcon}>💬</div>\n <h3 style={styles.emptyTitle}>\n {hasAny ? 'Select a conversation' : 'No conversations yet'}\n </h3>\n <p style={styles.emptySubtitle}>\n {hasAny\n ? 'Pick a patient from the list to start collaborating'\n : 'Conversations appear here once you start messaging about a case'}\n </p>\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n height: '100%',\n width: '100%',\n backgroundColor: '#ffffff',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n },\n sidebar: {\n width: '320px',\n minWidth: '280px',\n flexShrink: 0,\n display: 'flex',\n flexDirection: 'column',\n },\n main: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n minWidth: 0,\n padding: '12px',\n backgroundColor: '#f3f4f6',\n },\n panel: {\n height: '100%',\n width: '100%',\n },\n empty: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '48px 24px',\n textAlign: 'center',\n },\n emptyIcon: {\n fontSize: '48px',\n marginBottom: '12px',\n },\n emptyTitle: {\n margin: '0 0 6px',\n fontSize: '16px',\n fontWeight: 600,\n color: '#374151',\n },\n emptySubtitle: {\n margin: 0,\n fontSize: '13px',\n color: '#6b7280',\n maxWidth: '320px',\n },\n};\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type { Message } from '../core/types';\nimport { MESSAGES_PAGE_SIZE } from '../core/constants';\n\ninterface UseMessagesOptions {\n conversationId: string | null;\n /** Initial page size (default 30) */\n initialLimit?: number;\n}\n\ninterface UseMessagesReturn {\n messages: Message[];\n isLoading: boolean;\n hasMore: boolean;\n error: string | null;\n loadMore: () => Promise<void>;\n addMessage: (message: Message) => void;\n updateMessageReadBy: (messageId: string, userId: string) => void;\n reset: () => void;\n}\n\n/**\n * Standalone hook for message history management.\n * Use this if you need message data outside of useConversation\n * (e.g. building a completely custom UI).\n */\nexport function useMessages({\n conversationId,\n initialLimit = MESSAGES_PAGE_SIZE,\n}: UseMessagesOptions): UseMessagesReturn {\n const { fetchMessages, config } = useCollab();\n const [messages, setMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const loadedRef = useRef<string | null>(null);\n\n // Load initial messages when conversation changes\n useEffect(() => {\n if (!conversationId) {\n setMessages([]);\n setHasMore(false);\n loadedRef.current = null;\n return;\n }\n\n if (loadedRef.current === conversationId) return;\n\n let cancelled = false;\n\n const loadInitial = async () => {\n setIsLoading(true);\n setError(null);\n try {\n const initial = await fetchMessages(conversationId, { limit: initialLimit });\n if (cancelled) return;\n setMessages(initial);\n setHasMore(initial.length >= initialLimit);\n loadedRef.current = conversationId;\n } catch (err) {\n if (cancelled) return;\n const msg = err instanceof Error ? err.message : 'Failed to load messages';\n setError(msg);\n config.onError?.({\n code: 'LOAD_ERROR',\n message: 'Failed to load messages',\n details: err,\n });\n } finally {\n if (!cancelled) setIsLoading(false);\n }\n };\n\n loadInitial();\n\n return () => {\n cancelled = true;\n };\n }, [conversationId, initialLimit, fetchMessages, config]);\n\n const loadMore = useCallback(async () => {\n if (!conversationId || !hasMore || isLoading) return;\n\n const oldestId = messages[0]?.id;\n setIsLoading(true);\n try {\n const older = await fetchMessages(conversationId, {\n limit: initialLimit,\n before: oldestId,\n });\n setMessages((prev) => [...older, ...prev]);\n setHasMore(older.length >= initialLimit);\n } catch (err) {\n config.onError?.({\n code: 'LOAD_ERROR',\n message: 'Failed to load older messages',\n details: err,\n });\n } finally {\n setIsLoading(false);\n }\n }, [conversationId, hasMore, isLoading, messages, initialLimit, fetchMessages, config]);\n\n const addMessage = useCallback((message: Message) => {\n setMessages((prev) => [...prev, message]);\n }, []);\n\n const updateMessageReadBy = useCallback((messageId: string, userId: string) => {\n setMessages((prev) =>\n prev.map((msg) =>\n msg.id === messageId && !(msg.readBy ?? []).includes(userId)\n ? { ...msg, readBy: [...(msg.readBy ?? []), userId] }\n : msg\n )\n );\n }, []);\n\n const reset = useCallback(() => {\n setMessages([]);\n setHasMore(true);\n setError(null);\n loadedRef.current = null;\n }, []);\n\n return {\n messages,\n isLoading,\n hasMore,\n error,\n loadMore,\n addMessage,\n updateMessageReadBy,\n reset,\n };\n}\n","import { useState, useRef, useCallback } from 'react';\nimport { AUDIO_MIME_TYPE } from '../core/constants';\n\ninterface UseAudioRecorderReturn {\n /** Whether the mic is currently recording */\n isRecording: boolean;\n /** Recording duration in seconds (updates every second while recording) */\n duration: number;\n /** Start recording from the microphone */\n start: () => Promise<void>;\n /** Stop recording and return the audio blob */\n stop: () => Promise<{ blob: Blob; duration: number } | null>;\n /** Cancel recording without producing output */\n cancel: () => void;\n /** Whether the browser supports audio recording */\n isSupported: boolean;\n /** Error message if recording fails */\n error: string | null;\n}\n\n/**\n * Wraps the browser MediaRecorder API for voice message recording.\n * Returns a blob suitable for uploading via config.onUploadFile.\n */\nexport function useAudioRecorder(): UseAudioRecorderReturn {\n const [isRecording, setIsRecording] = useState(false);\n const [duration, setDuration] = useState(0);\n const [error, setError] = useState<string | null>(null);\n\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const chunksRef = useRef<Blob[]>([]);\n const streamRef = useRef<MediaStream | null>(null);\n const timerRef = useRef<NodeJS.Timeout | null>(null);\n const startTimeRef = useRef<number>(0);\n const resolveRef = useRef<((value: { blob: Blob; duration: number } | null) => void) | null>(null);\n\n const isSupported =\n typeof window !== 'undefined' &&\n typeof navigator !== 'undefined' &&\n !!navigator.mediaDevices?.getUserMedia &&\n !!window.MediaRecorder;\n\n const cleanup = useCallback(() => {\n if (timerRef.current) {\n clearInterval(timerRef.current);\n timerRef.current = null;\n }\n\n if (streamRef.current) {\n streamRef.current.getTracks().forEach((track) => track.stop());\n streamRef.current = null;\n }\n\n mediaRecorderRef.current = null;\n chunksRef.current = [];\n setIsRecording(false);\n setDuration(0);\n }, []);\n\n const start = useCallback(async () => {\n if (!isSupported) {\n setError('Audio recording is not supported in this browser');\n return;\n }\n\n try {\n setError(null);\n chunksRef.current = [];\n\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n streamRef.current = stream;\n\n // Pick the best supported MIME type\n const mimeType = MediaRecorder.isTypeSupported(AUDIO_MIME_TYPE)\n ? AUDIO_MIME_TYPE\n : MediaRecorder.isTypeSupported('audio/webm')\n ? 'audio/webm'\n : 'audio/mp4';\n\n const recorder = new MediaRecorder(stream, { mimeType });\n mediaRecorderRef.current = recorder;\n\n recorder.ondataavailable = (event) => {\n if (event.data.size > 0) {\n chunksRef.current.push(event.data);\n }\n };\n\n recorder.onerror = () => {\n setError('Recording failed');\n cleanup();\n resolveRef.current?.(null);\n resolveRef.current = null;\n };\n\n recorder.onstop = () => {\n const finalDuration = Math.round((Date.now() - startTimeRef.current) / 1000);\n const blob = new Blob(chunksRef.current, { type: mimeType });\n\n cleanup();\n resolveRef.current?.({ blob, duration: finalDuration });\n resolveRef.current = null;\n };\n\n recorder.start(250); // collect data every 250ms\n startTimeRef.current = Date.now();\n setIsRecording(true);\n\n // Update duration counter every second\n timerRef.current = setInterval(() => {\n const elapsed = Math.round((Date.now() - startTimeRef.current) / 1000);\n setDuration(elapsed);\n }, 1000);\n } catch (err) {\n if (err instanceof DOMException && err.name === 'NotAllowedError') {\n setError('Microphone access denied. Please allow microphone permissions.');\n } else {\n setError('Failed to start recording');\n }\n cleanup();\n }\n }, [isSupported, cleanup]);\n\n const stop = useCallback(async (): Promise<{ blob: Blob; duration: number } | null> => {\n return new Promise((resolve) => {\n if (!mediaRecorderRef.current || mediaRecorderRef.current.state === 'inactive') {\n resolve(null);\n return;\n }\n\n resolveRef.current = resolve;\n mediaRecorderRef.current.stop();\n });\n }, []);\n\n const cancel = useCallback(() => {\n if (mediaRecorderRef.current && mediaRecorderRef.current.state !== 'inactive') {\n // Remove onstop handler to avoid producing output\n mediaRecorderRef.current.onstop = null;\n mediaRecorderRef.current.stop();\n }\n cleanup();\n resolveRef.current?.(null);\n resolveRef.current = null;\n }, [cleanup]);\n\n return {\n isRecording,\n duration,\n start,\n stop,\n cancel,\n isSupported,\n error,\n };\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { useCollab } from '../context/CollabProvider';\n\ninterface UseUnreadCountReturn {\n /** Total unread messages across all conversations */\n totalUnread: number;\n /** Get unread count for a specific conversation */\n getCountForConversation: (conversationId: string) => number;\n /** Manually clear unread count for a conversation (e.g. when user opens it) */\n clearForConversation: (conversationId: string) => void;\n}\n\n/**\n * Tracks unread message counts.\n * Counts are pushed from the server via the user channel (no polling).\n */\nexport function useUnreadCount(): UseUnreadCountReturn {\n const { socket, totalUnread } = useCollab();\n const [counts, setCounts] = useState<Record<string, number>>({});\n\n useEffect(() => {\n socket.onUnreadCountUpdate((serverCounts) => {\n setCounts(serverCounts);\n });\n }, [socket]);\n\n const getCountForConversation = useCallback(\n (conversationId: string): number => {\n return counts[conversationId] ?? 0;\n },\n [counts]\n );\n\n const clearForConversation = useCallback((conversationId: string) => {\n setCounts((prev) => {\n const next = { ...prev };\n delete next[conversationId];\n return next;\n });\n }, []);\n\n return {\n totalUnread,\n getCountForConversation,\n clearForConversation,\n };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type { Message } from '../core/types';\n\ninterface UsePinnedMessagesOptions {\n conversationId: string | null;\n /** Initial pinned messages from preview/initial load (avoids extra fetch) */\n initial?: Message[];\n}\n\ninterface UsePinnedMessagesReturn {\n pinnedMessages: Message[];\n isLoading: boolean;\n error: string | null;\n pin: (messageId: string) => Promise<void>;\n unpin: (messageId: string) => Promise<void>;\n /** Handlers to wire to socket pin/unpin events */\n handlePinned: (message: Message) => void;\n handleUnpinned: (messageId: string) => void;\n refresh: () => Promise<void>;\n}\n\n/**\n * Manages pinned messages for a conversation.\n * Backend enforces MAX_PINNED_MESSAGES (3) — attempting to pin a 4th returns an error.\n */\nexport function usePinnedMessages({\n conversationId,\n initial = [],\n}: UsePinnedMessagesOptions): UsePinnedMessagesReturn {\n const { pinMessage, unpinMessage, fetchPinnedMessages, config } = useCollab();\n const [pinnedMessages, setPinnedMessages] = useState<Message[]>(initial);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const refresh = useCallback(async () => {\n if (!conversationId) return;\n setIsLoading(true);\n setError(null);\n try {\n const pinned = await fetchPinnedMessages(conversationId);\n setPinnedMessages(pinned);\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to load pinned messages';\n setError(msg);\n } finally {\n setIsLoading(false);\n }\n }, [conversationId, fetchPinnedMessages]);\n\n // Only auto-fetch if we don't have initial data\n useEffect(() => {\n if (conversationId && initial.length === 0) {\n refresh();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [conversationId]);\n\n const pin = useCallback(\n async (messageId: string) => {\n if (!conversationId) return;\n setError(null);\n try {\n await pinMessage(conversationId, messageId);\n // Server broadcasts message:pinned — handled via handlePinned\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to pin message';\n setError(msg);\n config.onError?.({\n code: 'PIN_ERROR',\n message: msg,\n details: err,\n });\n }\n },\n [conversationId, pinMessage, config]\n );\n\n const unpin = useCallback(\n async (messageId: string) => {\n if (!conversationId) return;\n setError(null);\n try {\n await unpinMessage(conversationId, messageId);\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to unpin message';\n setError(msg);\n config.onError?.({\n code: 'UNPIN_ERROR',\n message: msg,\n details: err,\n });\n }\n },\n [conversationId, unpinMessage, config]\n );\n\n const handlePinned = useCallback((message: Message) => {\n setPinnedMessages((prev) => {\n if (prev.some((m) => m.id === message.id)) return prev;\n return [...prev, message];\n });\n }, []);\n\n const handleUnpinned = useCallback((messageId: string) => {\n setPinnedMessages((prev) => prev.filter((m) => m.id !== messageId));\n }, []);\n\n return {\n pinnedMessages,\n isLoading,\n error,\n pin,\n unpin,\n handlePinned,\n handleUnpinned,\n refresh,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/core/constants.ts","../src/core/caseConvert.ts","../src/core/socket.ts","../src/context/CollabProvider.tsx","../src/core/channelName.ts","../src/hooks/useConversation.ts","../src/hooks/useChannelSettings.ts","../src/hooks/useDeepLinks.ts","../src/components/PatientHeader.tsx","../src/components/ReplyQuoteBlock.tsx","../src/components/SeenByIndicator.tsx","../src/components/MessageActionsMenu.tsx","../src/components/icons/FileIcon.tsx","../src/components/icons/PinIcon.tsx","../src/components/MessageBubble.tsx","../src/core/dateLabels.ts","../src/components/MessageList.tsx","../src/components/ReplyPreview.tsx","../src/components/icons/AttachIcon.tsx","../src/components/icons/SendIcon.tsx","../src/components/icons/CloseIcon.tsx","../src/components/MessageInput.tsx","../src/components/ParticipantsList.tsx","../src/components/ChannelSettings.tsx","../src/components/PinnedMessagesBar.tsx","../src/components/CollabPanel.tsx","../src/components/icons/MinimizeIcon.tsx","../src/components/CollabPopup.tsx","../src/hooks/useInlineCollab.ts","../src/components/CollabInline.tsx","../src/hooks/useConversationList.ts","../src/components/ConversationListItem.tsx","../src/components/ConversationList.tsx","../src/components/CollabInbox.tsx","../src/hooks/useMessages.ts","../src/hooks/useAudioRecorder.ts","../src/hooks/useUnreadCount.ts","../src/hooks/usePinnedMessages.ts"],"names":["useState","useRef","useCallback","useEffect","jsx","jsxs","styles","escapeRegex","MessageList","React","RoleBadge","formatDuration"],"mappings":"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","file":"index.mjs","sourcesContent":["/** Phoenix channel event names — must match backend channel implementation */\nexport const EVENTS = {\n MESSAGE_NEW: 'message:new',\n MESSAGE_READ: 'message:read',\n MESSAGE_PINNED: 'message:pinned',\n MESSAGE_UNPINNED: 'message:unpinned',\n USER_TYPING: 'user:typing',\n USER_JOINED: 'user:joined',\n USER_LEFT: 'user:left',\n CHANNEL_UPDATED: 'channel:updated',\n CHANNEL_DELETED: 'channel:deleted',\n PRESENCE_STATE: 'presence_state',\n PRESENCE_DIFF: 'presence_diff',\n} as const;\n\n/** Maximum number of pinned messages allowed per conversation */\nexport const MAX_PINNED_MESSAGES = 3;\n\n/** Message types */\nexport const MESSAGE_TYPES = {\n TEXT: 'text',\n AUDIO: 'audio',\n IMAGE: 'image',\n FILE: 'file',\n SYSTEM: 'system',\n DEEP_LINK: 'deep_link',\n} as const;\n\n/** Deep link protocol prefix */\nexport const DEEP_LINK_PREFIX = 'natoe://';\n\n/** Typing indicator debounce in ms */\nexport const TYPING_DEBOUNCE_MS = 2000;\n\n/** Messages to load per page when scrolling back */\nexport const MESSAGES_PAGE_SIZE = 30;\n\n/** Supported audio MIME type for recording */\nexport const AUDIO_MIME_TYPE = 'audio/webm;codecs=opus';\n\n/** Supported image types for attachments */\nexport const SUPPORTED_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];\n\n/** Max file size in bytes (20MB) */\nexport const MAX_FILE_SIZE = 20 * 1024 * 1024;\n","/**\n * Recursively converts object keys from snake_case to camelCase.\n *\n * Used at every backend boundary (REST responses, socket events) to bridge\n * the Phoenix (snake_case) → TypeScript (camelCase) gap.\n *\n * Idempotent — keys already in camelCase stay unchanged (no underscores to\n * convert). Arrays and primitives pass through untouched.\n */\nexport function snakeToCamel<T = unknown>(input: unknown): T {\n if (Array.isArray(input)) {\n return input.map((item) => snakeToCamel(item)) as unknown as T;\n }\n\n if (input !== null && typeof input === 'object') {\n const source = input as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(source)) {\n const camelKey = toCamelKey(key);\n out[camelKey] = snakeToCamel(source[key]);\n }\n return out as T;\n }\n\n return input as T;\n}\n\nfunction toCamelKey(key: string): string {\n if (!key.includes('_')) return key;\n return key.replace(/_([a-zA-Z0-9])/g, (_, c: string) => c.toUpperCase());\n}\n","import { Socket, Channel, Presence } from 'phoenix';\nimport type {\n CollabConfig,\n Message,\n Conversation,\n Participant,\n SendMessagePayload,\n TypingEvent,\n ChannelUpdatePayload,\n InviteUserPayload,\n} from './types';\nimport { EVENTS } from './constants';\nimport { snakeToCamel } from './caseConvert';\n\ntype MessageCallback = (message: Message) => void;\ntype TypingCallback = (event: TypingEvent) => void;\ntype ParticipantCallback = (participant: Participant) => void;\ntype ChannelUpdateCallback = (conversation: Partial<Conversation>) => void;\ntype PresenceCallback = (presences: Record<string, { userId: string; isOnline: boolean }>) => void;\n\ninterface ConversationCallbacks {\n onMessage?: MessageCallback;\n onTyping?: TypingCallback;\n onUserJoined?: ParticipantCallback;\n onUserLeft?: ParticipantCallback;\n onChannelUpdated?: ChannelUpdateCallback;\n onChannelDeleted?: () => void;\n onPresence?: PresenceCallback;\n onMessageRead?: (data: { messageId: string; userId: string }) => void;\n onMessagePinned?: (message: Message) => void;\n onMessageUnpinned?: (data: { messageId: string }) => void;\n}\n\n/**\n * Manages Phoenix WebSocket connection and channel subscriptions.\n * One instance per authenticated user session.\n */\nexport class CollabSocket {\n private socket: Socket | null = null;\n private channels: Map<string, Channel> = new Map();\n private presences: Map<string, Presence> = new Map();\n private userChannel: Channel | null = null;\n private config: CollabConfig | null = null;\n private onUnreadUpdate: ((counts: Record<string, number>) => void) | null = null;\n\n /** Connect to Phoenix WebSocket server. Idempotent — safe to call when\n * the token becomes available later (e.g. after async login) without\n * stacking up multiple open sockets. */\n connect(config: CollabConfig): void {\n this.config = config;\n\n // No token means the host hasn't finished login yet. Skip the connect\n // so we don't churn through reconnect attempts that the server would\n // reject with 1006 anyway. The host re-calls connect() once auth lands.\n if (!config.getToken()) {\n return;\n }\n\n // If a prior (live or half-dead) socket exists, retire it before\n // creating a new one. Otherwise the old heartbeat / channels leak.\n if (this.socket) {\n if (this.socket.isConnected()) return;\n try {\n this.socket.disconnect();\n } catch {\n // best-effort; we're about to replace it anyway\n }\n this.channels.clear();\n this.presences.clear();\n this.userChannel = null;\n }\n\n this.socket = new Socket(config.socketUrl, {\n params: () => ({ token: config.getToken() }),\n });\n\n // Phoenix's onError hands us the native WebSocket error/close event. We\n // forward whatever useful fields the browser gave us so failures like a\n // 403 handshake (bad token / missing Redis session) can be distinguished\n // from transport drops instead of all showing as \"error undefined\".\n this.socket.onError((err) => {\n const closeEvent = err as unknown as CloseEvent | undefined;\n config.onError?.({\n code: 'SOCKET_ERROR',\n message: 'WebSocket connection error',\n details: closeEvent\n ? {\n type: closeEvent.type,\n code: closeEvent.code,\n reason: closeEvent.reason,\n wasClean: closeEvent.wasClean,\n }\n : err,\n });\n });\n\n this.socket.onClose((event) => {\n // Code 1006 = abnormal closure (no close frame — usually means the\n // server rejected the upgrade, e.g. auth failed before handshake).\n // Code 1000 = normal; code 1011 = server error.\n config.onError?.({\n code: 'SOCKET_CLOSED',\n message: `Socket closed (code ${event?.code ?? 'unknown'})`,\n details: event\n ? { code: event.code, reason: event.reason, wasClean: event.wasClean }\n : undefined,\n });\n });\n\n this.socket.connect();\n this.joinUserChannel();\n }\n\n /** Subscribe to user-level events (unread counts, notifications) */\n private joinUserChannel(): void {\n if (!this.socket || !this.config) return;\n\n // Topic has no user_id suffix — backend derives it from the authenticated socket.\n // This avoids any mismatch between client-side stored IDs and the token's claims.\n this.userChannel = this.socket.channel('user_notifications', {});\n\n this.userChannel.on('unread_update', (payload: Record<string, number>) => {\n this.onUnreadUpdate?.(payload);\n });\n\n this.userChannel\n .join()\n .receive('ok', () => {\n // connected to user channel\n })\n .receive('error', (reason) => {\n this.config?.onError?.({\n code: 'USER_CHANNEL_ERROR',\n message: 'Failed to join user channel',\n details: reason,\n });\n });\n }\n\n /** Register callback for unread count changes */\n onUnreadCountUpdate(callback: (counts: Record<string, number>) => void): void {\n this.onUnreadUpdate = callback;\n }\n\n /** Join a conversation channel and subscribe to events */\n joinConversation(conversationId: string, callbacks: ConversationCallbacks): Channel | null {\n if (!this.socket) return null;\n\n // Don't rejoin if already in this channel\n if (this.channels.has(conversationId)) {\n return this.channels.get(conversationId)!;\n }\n\n const channel = this.socket.channel(`conversation:${conversationId}`, {});\n\n // Real-time message delivery\n if (callbacks.onMessage) {\n channel.on(EVENTS.MESSAGE_NEW, (payload: unknown) => {\n callbacks.onMessage!(snakeToCamel<Message>(payload));\n });\n }\n\n // Typing indicators\n if (callbacks.onTyping) {\n channel.on(EVENTS.USER_TYPING, (payload: unknown) => {\n callbacks.onTyping!(snakeToCamel<TypingEvent>(payload));\n });\n }\n\n // Participant events\n if (callbacks.onUserJoined) {\n channel.on(EVENTS.USER_JOINED, (payload: unknown) => {\n callbacks.onUserJoined!(snakeToCamel<Participant>(payload));\n });\n }\n\n if (callbacks.onUserLeft) {\n channel.on(EVENTS.USER_LEFT, (payload: unknown) => {\n callbacks.onUserLeft!(snakeToCamel<Participant>(payload));\n });\n }\n\n // Channel metadata changes\n if (callbacks.onChannelUpdated) {\n channel.on(EVENTS.CHANNEL_UPDATED, (payload: unknown) => {\n callbacks.onChannelUpdated!(snakeToCamel<Partial<Conversation>>(payload));\n });\n }\n\n if (callbacks.onChannelDeleted) {\n channel.on(EVENTS.CHANNEL_DELETED, () => {\n callbacks.onChannelDeleted!();\n });\n }\n\n // Read receipts\n if (callbacks.onMessageRead) {\n channel.on(EVENTS.MESSAGE_READ, (payload: unknown) => {\n callbacks.onMessageRead!(snakeToCamel<{ messageId: string; userId: string }>(payload));\n });\n }\n\n // Pin events\n if (callbacks.onMessagePinned) {\n channel.on(EVENTS.MESSAGE_PINNED, (payload: unknown) => {\n callbacks.onMessagePinned!(snakeToCamel<Message>(payload));\n });\n }\n\n if (callbacks.onMessageUnpinned) {\n channel.on(EVENTS.MESSAGE_UNPINNED, (payload: unknown) => {\n callbacks.onMessageUnpinned!(snakeToCamel<{ messageId: string }>(payload));\n });\n }\n\n // Presence tracking (online/offline)\n if (callbacks.onPresence) {\n const presence = new Presence(channel);\n\n presence.onSync(() => {\n const online: Record<string, { userId: string; isOnline: boolean }> = {};\n presence.list((id: string) => {\n online[id] = { userId: id, isOnline: true };\n });\n callbacks.onPresence!(online);\n });\n\n this.presences.set(conversationId, presence);\n }\n\n channel\n .join()\n .receive('ok', () => {\n // successfully joined conversation channel\n })\n .receive('error', (reason) => {\n this.config?.onError?.({\n code: 'CHANNEL_JOIN_ERROR',\n message: `Failed to join conversation ${conversationId}`,\n details: reason,\n });\n });\n\n this.channels.set(conversationId, channel);\n return channel;\n }\n\n /** Leave a conversation channel */\n leaveConversation(conversationId: string): void {\n const channel = this.channels.get(conversationId);\n if (channel) {\n channel.leave();\n this.channels.delete(conversationId);\n this.presences.delete(conversationId);\n }\n }\n\n /** Send a message to a conversation.\n *\n * Phoenix buffers pushes fired while a channel is still joining and\n * replays them on successful join. The default per-push timeout is 10s,\n * which is tight on slow dev backends — we bump to 30s so a late join\n * doesn't surface as a \"timed out\" error to a message that ultimately\n * persists. The caller still gets 'ok' once the server acks.\n */\n sendMessage(conversationId: string, payload: SendMessagePayload): Promise<Message> {\n return new Promise((resolve, reject) => {\n const channel = this.channels.get(conversationId);\n if (!channel) {\n reject({ code: 'NOT_JOINED', message: 'Not joined to this conversation' });\n return;\n }\n\n // If the underlying socket is down (token cleared, server restarted\n // mid-session, etc.) Phoenix will silently buffer the push until the\n // per-push timeout fires 30s later. Fail fast instead — the caller\n // can remove the optimistic row and the user can retry once we're\n // back online.\n if (!this.socket?.isConnected()) {\n reject({\n code: 'SOCKET_DISCONNECTED',\n message: 'Cannot send — chat server not connected',\n });\n return;\n }\n\n channel\n .push(EVENTS.MESSAGE_NEW, payload, 30_000)\n .receive('ok', (response: Message) => resolve(response))\n .receive('error', (reason) =>\n reject({ code: 'SEND_ERROR', message: 'Failed to send message', details: reason })\n )\n .receive('timeout', () =>\n reject({ code: 'TIMEOUT', message: 'Message send timed out' })\n );\n });\n }\n\n /** Broadcast typing indicator */\n sendTyping(conversationId: string, isTyping: boolean): void {\n const channel = this.channels.get(conversationId);\n channel?.push(EVENTS.USER_TYPING, {\n userId: this.config?.userId,\n userName: this.config?.userName,\n isTyping,\n });\n }\n\n /** Mark messages as read */\n markAsRead(conversationId: string, messageId: string): void {\n const channel = this.channels.get(conversationId);\n channel?.push(EVENTS.MESSAGE_READ, {\n messageId,\n userId: this.config?.userId,\n });\n }\n\n // ── Channel Management ──\n\n /** Add a user to the conversation */\n inviteUser(conversationId: string, payload: InviteUserPayload): Promise<Participant> {\n return this.channelPush(conversationId, 'invite_user', payload);\n }\n\n /** Remove a user from the conversation */\n removeUser(conversationId: string, userId: string): Promise<void> {\n return this.channelPush(conversationId, 'remove_user', { userId });\n }\n\n /** Update channel name/picture */\n updateChannel(conversationId: string, payload: ChannelUpdatePayload): Promise<Conversation> {\n return this.channelPush(conversationId, 'update_channel', payload);\n }\n\n /** Delete channel (admin only) */\n deleteChannel(conversationId: string): Promise<void> {\n return this.channelPush(conversationId, 'delete_channel', {});\n }\n\n /** Pin a message in the conversation (max MAX_PINNED_MESSAGES) */\n pinMessage(conversationId: string, messageId: string): Promise<Message> {\n return this.channelPush(conversationId, 'pin_message', { messageId });\n }\n\n /** Unpin a message in the conversation */\n unpinMessage(conversationId: string, messageId: string): Promise<void> {\n return this.channelPush(conversationId, 'unpin_message', { messageId });\n }\n\n /** Generic push with promise wrapper */\n private channelPush<T>(conversationId: string, event: string, payload: object): Promise<T> {\n return new Promise((resolve, reject) => {\n const channel = this.channels.get(conversationId);\n if (!channel) {\n reject({ code: 'NOT_JOINED', message: 'Not joined to this conversation' });\n return;\n }\n\n channel\n .push(event, payload)\n .receive('ok', (response: T) => resolve(response))\n .receive('error', (reason) =>\n reject({ code: 'CHANNEL_ERROR', message: `Failed: ${event}`, details: reason })\n );\n });\n }\n\n /** Check if connected */\n isConnected(): boolean {\n return this.socket?.isConnected() ?? false;\n }\n\n /** Disconnect socket and leave all channels */\n disconnect(): void {\n this.channels.forEach((channel) => channel.leave());\n this.channels.clear();\n this.presences.clear();\n this.userChannel?.leave();\n this.socket?.disconnect();\n this.socket = null;\n this.config = null;\n }\n}\n","import React, { createContext, useContext, useEffect, useRef, useState, useCallback } from 'react';\nimport { CollabSocket } from '../core/socket';\nimport type {\n CollabConfig,\n ConversationListItem,\n ConversationPreview,\n CreateConversationResponse,\n Message,\n PreviewBatchResponse,\n SendMessagePayload,\n} from '../core/types';\nimport { MESSAGES_PAGE_SIZE } from '../core/constants';\nimport { snakeToCamel } from '../core/caseConvert';\n\ninterface FetchMessagesOptions {\n before?: string;\n limit?: number;\n}\n\ninterface CreateConversationOptions {\n name: string;\n participantIds?: string[];\n}\n\ninterface CollabContextValue {\n socket: CollabSocket;\n config: CollabConfig;\n apiBaseUrl: string;\n totalUnread: number;\n /** Batched preview lookup — coalesces calls within a microtask */\n requestPreview: (orderId: string) => Promise<ConversationPreview | null>;\n /** Invalidate a cached preview (e.g. when a new message arrives) */\n invalidatePreview: (orderId: string) => void;\n /** Fetch paginated message history */\n fetchMessages: (conversationId: string, options?: FetchMessagesOptions) => Promise<Message[]>;\n /** Atomic create-or-send — creates conversation if missing, then stores the first message */\n createConversationWithMessage: (\n orderId: string,\n message: SendMessagePayload,\n options: CreateConversationOptions\n ) => Promise<CreateConversationResponse>;\n /** Add a user to an existing conversation (e.g. when radiologist is assigned later) */\n addParticipant: (conversationId: string, userId: string) => Promise<void>;\n /** Remove a user from a conversation */\n removeParticipant: (conversationId: string, userId: string) => Promise<void>;\n /** Fetch the current user's full conversation list — feeds the CollabInbox sidebar */\n fetchConversationList: () => Promise<ConversationListItem[]>;\n /** Pin a message (max MAX_PINNED_MESSAGES per conversation — backend enforces) */\n pinMessage: (conversationId: string, messageId: string) => Promise<void>;\n /** Unpin a message */\n unpinMessage: (conversationId: string, messageId: string) => Promise<void>;\n /** Fetch current pinned messages for a conversation */\n fetchPinnedMessages: (conversationId: string) => Promise<Message[]>;\n}\n\nexport const CollabContext = createContext<CollabContextValue | null>(null);\nexport type { CollabContextValue };\n\nexport function useCollab(): CollabContextValue {\n const context = useContext(CollabContext);\n if (!context) {\n throw new Error('useCollab must be used within a <CollabProvider>');\n }\n return context;\n}\n\ninterface CollabProviderProps {\n config: CollabConfig;\n children: React.ReactNode;\n /** REST API base URL for the Phoenix backend (e.g. https://backend.natoe.ai) */\n apiBaseUrl: string;\n}\n\nexport function CollabProvider({ config, apiBaseUrl, children }: CollabProviderProps) {\n // Using useState (not useRef) so children re-render once the socket is ready.\n // Instantiated synchronously on first render so children have a non-null\n // socket reference immediately; the ACTUAL connect() happens in the\n // effect below, after the unread-count handler is wired in — otherwise\n // the backend's initial :after_join push races the handler registration\n // and the first unread_update is dropped silently.\n const [socket, setSocket] = useState<CollabSocket | null>(() => {\n if (typeof window === 'undefined') return null;\n return new CollabSocket();\n });\n const [unreadCounts, setUnreadCounts] = useState<Record<string, number>>({});\n\n // Preview batching state\n const pendingOrderIds = useRef<Set<string>>(new Set());\n const pendingResolvers = useRef<Map<string, Array<(preview: ConversationPreview | null) => void>>>(new Map());\n const previewCache = useRef<Map<string, ConversationPreview | null>>(new Map());\n const batchScheduled = useRef(false);\n\n // Wire unread-count listener + reconnect when identity changes.\n // The socket instance (wrapper) is created lazily in useState above, but\n // the underlying Phoenix Socket is only created if getToken() returned\n // something at that first render. When the token arrives later (post-login),\n // this effect re-fires and asks the wrapper to connect for real.\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n // Create the wrapper if it wasn't created during the useState init\n // (e.g. SSR branch that short-circuited).\n let s = socket;\n if (!s) {\n s = new CollabSocket();\n setSocket(s);\n }\n\n // Register the unread handler BEFORE connect() so the backend's\n // :after_join push (initial counts, fires immediately on channel join)\n // is never dropped because the handler was still unset. Push-driven\n // updates also clear the preview cache so the next popup open fetches\n // fresh server truth.\n s.onUnreadCountUpdate((counts) => {\n setUnreadCounts(counts);\n previewCache.current.clear();\n });\n\n // connect() is idempotent — no-op when already connected, retries when\n // the prior init saw an empty token.\n if (!s.isConnected()) {\n s.connect(config);\n }\n\n // Intentionally no cleanup disconnect here — identity changes should\n // reconnect in place rather than tearing down the whole session.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [config.socketUrl, config.userId]);\n\n const authHeaders = useCallback(\n (): HeadersInit => ({\n Authorization: `Bearer ${config.getToken()}`,\n 'Content-Type': 'application/json',\n }),\n [config]\n );\n\n // ── Batch preview fetching ──────────────────────────────────────────\n\n const flushPreviewBatch = useCallback(async () => {\n const orderIds = Array.from(pendingOrderIds.current);\n const resolvers = new Map(pendingResolvers.current);\n pendingOrderIds.current.clear();\n pendingResolvers.current.clear();\n batchScheduled.current = false;\n\n if (orderIds.length === 0) return;\n\n try {\n const query = orderIds.map((id) => `order_ids[]=${encodeURIComponent(id)}`).join('&');\n const response = await fetch(`${apiBaseUrl}/api/natoe-colab/conversations/previews?${query}`, {\n headers: authHeaders(),\n });\n\n if (!response.ok) throw new Error(`Preview batch failed: ${response.status}`);\n\n const data: PreviewBatchResponse = snakeToCamel(await response.json());\n\n orderIds.forEach((orderId) => {\n const preview = data.previews[orderId] ?? null;\n previewCache.current.set(orderId, preview);\n resolvers.get(orderId)?.forEach((resolve) => resolve(preview));\n });\n } catch (error) {\n config.onError?.({\n code: 'PREVIEW_BATCH_ERROR',\n message: 'Failed to fetch conversation previews',\n details: error,\n });\n orderIds.forEach((orderId) => {\n resolvers.get(orderId)?.forEach((resolve) => resolve(null));\n });\n }\n }, [apiBaseUrl, authHeaders, config]);\n\n const requestPreview = useCallback(\n (orderId: string): Promise<ConversationPreview | null> => {\n // Return cached if available\n if (previewCache.current.has(orderId)) {\n return Promise.resolve(previewCache.current.get(orderId) ?? null);\n }\n\n return new Promise((resolve) => {\n pendingOrderIds.current.add(orderId);\n const existing = pendingResolvers.current.get(orderId) || [];\n existing.push(resolve);\n pendingResolvers.current.set(orderId, existing);\n\n if (!batchScheduled.current) {\n batchScheduled.current = true;\n queueMicrotask(flushPreviewBatch);\n }\n });\n },\n [flushPreviewBatch]\n );\n\n const invalidatePreview = useCallback((orderId: string) => {\n previewCache.current.delete(orderId);\n }, []);\n\n // ── Message history ──────────────────────────────────────────\n\n const fetchMessages = useCallback(\n async (conversationId: string, options: FetchMessagesOptions = {}): Promise<Message[]> => {\n const limit = options.limit ?? MESSAGES_PAGE_SIZE;\n const params = new URLSearchParams({ limit: String(limit) });\n if (options.before) params.set('before', options.before);\n\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/messages?${params.toString()}`,\n { headers: authHeaders() }\n );\n\n if (!response.ok) {\n throw { code: 'FETCH_ERROR', message: 'Failed to fetch messages', status: response.status };\n }\n\n return snakeToCamel(await response.json());\n },\n [apiBaseUrl, authHeaders]\n );\n\n // ── Atomic create-or-send ──────────────────────────────────────────\n\n const createConversationWithMessage = useCallback(\n async (\n orderId: string,\n message: SendMessagePayload,\n options: CreateConversationOptions\n ): Promise<CreateConversationResponse> => {\n if (!orderId || !orderId.trim()) {\n throw {\n code: 'INVALID_ORDER_ID',\n message:\n 'Cannot create conversation: orderId is empty. Host app passed an order with no orderId/mainOrderId set.',\n };\n }\n const response = await fetch(`${apiBaseUrl}/api/natoe-colab/orders/${orderId}/messages`, {\n method: 'POST',\n headers: authHeaders(),\n body: JSON.stringify({\n message,\n conversation: {\n name: options.name,\n participant_ids: options.participantIds ?? [],\n },\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw { code: 'CREATE_ERROR', message: 'Failed to create conversation', details: error };\n }\n\n const data: CreateConversationResponse = snakeToCamel(await response.json());\n\n // The backend may have appended this message to an EXISTING\n // study-scoped conversation that already has plenty of history.\n // Drop the cached preview so the next requestPreview fetches truth\n // instead of reading a stale snapshot from before the new message.\n previewCache.current.delete(orderId);\n\n return data;\n },\n [apiBaseUrl, authHeaders]\n );\n\n // ── Participant management ──────────────────────────────────────────\n\n const addParticipant = useCallback(\n async (conversationId: string, userId: string): Promise<void> => {\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/participants`,\n {\n method: 'POST',\n headers: authHeaders(),\n body: JSON.stringify({ user_id: userId }),\n }\n );\n\n if (!response.ok) {\n throw { code: 'ADD_PARTICIPANT_ERROR', message: 'Failed to add participant' };\n }\n },\n [apiBaseUrl, authHeaders]\n );\n\n const removeParticipant = useCallback(\n async (conversationId: string, userId: string): Promise<void> => {\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/participants/${userId}`,\n {\n method: 'DELETE',\n headers: authHeaders(),\n }\n );\n\n if (!response.ok) {\n throw { code: 'REMOVE_PARTICIPANT_ERROR', message: 'Failed to remove participant' };\n }\n },\n [apiBaseUrl, authHeaders]\n );\n\n // ── Conversation list (Inbox) ──────────────────────────────────────────\n\n const fetchConversationList = useCallback(async (): Promise<ConversationListItem[]> => {\n const response = await fetch(`${apiBaseUrl}/api/natoe-colab/conversations`, {\n headers: authHeaders(),\n });\n\n if (!response.ok) {\n throw { code: 'LIST_ERROR', message: 'Failed to fetch conversation list' };\n }\n\n return snakeToCamel(await response.json());\n }, [apiBaseUrl, authHeaders]);\n\n // ── Pin management ──────────────────────────────────────────\n\n const pinMessage = useCallback(\n async (conversationId: string, messageId: string): Promise<void> => {\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/messages/${messageId}/pin`,\n {\n method: 'POST',\n headers: authHeaders(),\n }\n );\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw { code: 'PIN_ERROR', message: 'Failed to pin message', details: error };\n }\n },\n [apiBaseUrl, authHeaders]\n );\n\n const unpinMessage = useCallback(\n async (conversationId: string, messageId: string): Promise<void> => {\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/messages/${messageId}/pin`,\n {\n method: 'DELETE',\n headers: authHeaders(),\n }\n );\n\n if (!response.ok) {\n throw { code: 'UNPIN_ERROR', message: 'Failed to unpin message' };\n }\n },\n [apiBaseUrl, authHeaders]\n );\n\n const fetchPinnedMessages = useCallback(\n async (conversationId: string): Promise<Message[]> => {\n const response = await fetch(\n `${apiBaseUrl}/api/natoe-colab/conversations/${conversationId}/pinned`,\n { headers: authHeaders() }\n );\n\n if (!response.ok) {\n throw { code: 'FETCH_PINNED_ERROR', message: 'Failed to fetch pinned messages' };\n }\n\n return snakeToCamel(await response.json());\n },\n [apiBaseUrl, authHeaders]\n );\n\n const totalUnread = Object.values(unreadCounts).reduce((sum, count) => sum + count, 0);\n\n if (!socket) return null;\n\n return (\n <CollabContext.Provider\n value={{\n socket,\n config,\n apiBaseUrl,\n totalUnread,\n requestPreview,\n invalidatePreview,\n fetchMessages,\n createConversationWithMessage,\n addParticipant,\n removeParticipant,\n fetchConversationList,\n pinMessage,\n unpinMessage,\n fetchPinnedMessages,\n }}\n >\n {children}\n </CollabContext.Provider>\n );\n}\n","import type { PatientData } from './types';\n\n/**\n * Canonical channel name format, used both when creating conversations\n * and wherever a channel needs to be labeled in the UI.\n *\n * Format: `<patient> - <lab> - <last 4 of order id>`\n * Example: \"John Doe - Beachside Lab - 1189\"\n */\nexport function buildChannelName(patientData: PatientData): string {\n const patientPart = patientData.patientName?.trim() || 'Unknown';\n const labPart = patientData.labName?.trim()?.slice(0, 24) || '';\n const last4 = (patientData.displayOrderId ?? '').trim().slice(-4) || '0000';\n return `${patientPart} - ${labPart} - ${last4}`;\n}\n","import { useEffect, useRef, useState, useCallback } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type {\n Message,\n Participant,\n Conversation,\n SendMessagePayload,\n TypingEvent,\n PatientData,\n} from '../core/types';\nimport { buildChannelName } from '../core/channelName';\n\ninterface UseConversationOptions {\n orderId: string;\n patientData: PatientData;\n /** Participant user IDs used only when creating a brand-new conversation */\n participantIds?: string[];\n /** Load full history on mount (default true) */\n loadHistory?: boolean;\n}\n\ninterface UseConversationReturn {\n conversation: Conversation | null;\n messages: Message[];\n pinnedMessages: Message[];\n participants: Participant[];\n typingUsers: TypingEvent[];\n isLoading: boolean;\n hasMore: boolean;\n error: string | null;\n isConnected: boolean;\n /** Message currently being replied to (null if not replying) */\n replyTo: Message | null;\n /** Set/clear the active reply target */\n setReplyTo: (message: Message | null) => void;\n sendMessage: (body: string) => Promise<void>;\n sendAudioMessage: (audioBlob: Blob, duration: number) => Promise<void>;\n sendFileMessage: (file: File) => Promise<void>;\n sendDeepLink: (path: string, label: string) => Promise<void>;\n sendTyping: (isTyping: boolean) => void;\n markAsRead: (messageId: string) => void;\n loadMoreMessages: () => Promise<void>;\n pinMessage: (messageId: string) => Promise<void>;\n unpinMessage: (messageId: string) => Promise<void>;\n}\n\n/**\n * Full conversation hook used by CollabPanel / CollabPopup.\n *\n * Lazy creation: the conversation is NOT created on mount. It's only created\n * when the user sends the first message. If a conversation already exists for\n * the given orderId, it's loaded and joined automatically.\n */\nexport function useConversation({\n orderId,\n patientData,\n participantIds = [],\n loadHistory = true,\n}: UseConversationOptions): UseConversationReturn {\n const {\n socket,\n config,\n requestPreview,\n invalidatePreview,\n fetchMessages,\n createConversationWithMessage,\n pinMessage: pinMessageApi,\n unpinMessage: unpinMessageApi,\n } = useCollab();\n\n const [conversation, setConversation] = useState<Conversation | null>(null);\n const [messages, setMessages] = useState<Message[]>([]);\n const [pinnedMessages, setPinnedMessages] = useState<Message[]>([]);\n const [participants, setParticipants] = useState<Participant[]>([]);\n const [typingUsers, setTypingUsers] = useState<TypingEvent[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [hasMore, setHasMore] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [replyTo, setReplyTo] = useState<Message | null>(null);\n\n const joinedConversationId = useRef<string | null>(null);\n const typingTimers = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());\n // In-flight promise for the lazy-create call. Two sends hitting before\n // state updates would each see `conversation: null` and POST twice; with\n // this guard, the second caller awaits the first's result instead.\n const ensureConversationInFlight = useRef<Promise<Conversation> | null>(null);\n // Messages we've already sent a `message:read` push for, in this session.\n // The MessageList's IntersectionObserver refires on every messages[] state\n // change; without this dedupe, every broadcast-driven readBy update\n // retriggers mark-read on every visible row, causing a runaway loop.\n const markedReadIdsRef = useRef<Set<string>>(new Set());\n\n const buildName = useCallback(\n (): string => buildChannelName(patientData),\n [patientData]\n );\n\n const joinChannel = useCallback(\n (conv: Conversation) => {\n if (joinedConversationId.current === conv.id) return;\n\n socket.joinConversation(conv.id, {\n // Dedupe by id so an optimistic message (added client-side on send)\n // doesn't double up when the server's broadcast arrives.\n onMessage: (msg) =>\n setMessages((prev) => {\n if (prev.some((m) => m.id === msg.id)) return prev;\n // Replace any optimistic twin (same sender, same body, still pending).\n const optimisticIdx = prev.findIndex(\n (m) =>\n m.id.startsWith('pending-') &&\n m.senderId === msg.senderId &&\n m.body === msg.body\n );\n if (optimisticIdx >= 0) {\n const next = prev.slice();\n next[optimisticIdx] = msg;\n return next;\n }\n return [...prev, msg];\n }),\n onTyping: (event) => {\n if (event.userId === config.userId) return;\n\n if (event.isTyping) {\n setTypingUsers((prev) => {\n const exists = prev.some((t) => t.userId === event.userId);\n return exists ? prev : [...prev, event];\n });\n const existingTimer = typingTimers.current.get(event.userId);\n if (existingTimer) clearTimeout(existingTimer);\n const timer = setTimeout(() => {\n setTypingUsers((prev) => prev.filter((t) => t.userId !== event.userId));\n typingTimers.current.delete(event.userId);\n }, 3000);\n typingTimers.current.set(event.userId, timer);\n } else {\n setTypingUsers((prev) => prev.filter((t) => t.userId !== event.userId));\n const timer = typingTimers.current.get(event.userId);\n if (timer) clearTimeout(timer);\n typingTimers.current.delete(event.userId);\n }\n },\n onUserJoined: (participant) => {\n setParticipants((prev) =>\n prev.some((p) => p.userId === participant.userId) ? prev : [...prev, participant]\n );\n },\n onUserLeft: (participant) => {\n setParticipants((prev) => prev.filter((p) => p.userId !== participant.userId));\n },\n onChannelUpdated: (updates) => {\n setConversation((prev) => (prev ? { ...prev, ...updates } : prev));\n },\n onChannelDeleted: () => {\n setConversation(null);\n setMessages([]);\n joinedConversationId.current = null;\n setIsConnected(false);\n },\n onMessageRead: ({ messageId, userId }) => {\n setMessages((prev) =>\n prev.map((msg) =>\n msg.id === messageId && !(msg.readBy ?? []).includes(userId)\n ? { ...msg, readBy: [...(msg.readBy ?? []), userId] }\n : msg\n )\n );\n },\n onMessagePinned: (message) => {\n setPinnedMessages((prev) =>\n prev.some((m) => m.id === message.id) ? prev : [...prev, message]\n );\n setMessages((prev) =>\n prev.map((m) => (m.id === message.id ? { ...m, isPinned: true } : m))\n );\n },\n onMessageUnpinned: ({ messageId }) => {\n setPinnedMessages((prev) => prev.filter((m) => m.id !== messageId));\n setMessages((prev) =>\n prev.map((m) => (m.id === messageId ? { ...m, isPinned: false } : m))\n );\n },\n });\n\n joinedConversationId.current = conv.id;\n setIsConnected(true);\n },\n [socket, config.userId]\n );\n\n // Initial load: check for existing conversation via preview\n useEffect(() => {\n let cancelled = false;\n\n const init = async () => {\n setIsLoading(true);\n setError(null);\n\n try {\n const preview = await requestPreview(orderId);\n\n if (cancelled) return;\n\n if (!preview) {\n // No conversation exists yet — stay in \"new\" mode\n setConversation(null);\n setMessages([]);\n setParticipants([]);\n setHasMore(false);\n setIsLoading(false);\n return;\n }\n\n const existingConv: Conversation = {\n id: preview.conversationId,\n orderId: preview.orderId,\n name: preview.name,\n participants: preview.participants,\n unreadCount: preview.unreadCount,\n createdAt: '',\n updatedAt: '',\n };\n\n setConversation(existingConv);\n setParticipants(preview.participants);\n // Channel join kicks off synchronously (Phoenix push handles the\n // async part). Renders can proceed while the join completes.\n joinChannel(existingConv);\n\n // Paint the panel immediately with the last-N messages from the\n // preview — no wait. Unblock the user from typing while full\n // history loads in the background.\n setMessages(preview.lastMessages);\n setHasMore(preview.messageCount > preview.lastMessages.length);\n setPinnedMessages(preview.lastMessages.filter((m) => m.isPinned));\n setIsLoading(false);\n\n if (loadHistory) {\n // Always pull authoritative history from the server, even when the\n // preview looks \"complete\" by count — the preview cache can be\n // stale (messages may have arrived after it was populated but\n // before the user reopened the popup). Dedupe by id on merge so\n // we don't duplicate the ones already painted.\n fetchMessages(preview.conversationId)\n .then((history) => {\n if (cancelled) return;\n setMessages((prev) => {\n const seen = new Set(prev.map((m) => m.id));\n const older = history.filter((m) => !seen.has(m.id));\n return [...older, ...prev];\n });\n setHasMore(history.length > 0);\n setPinnedMessages((prev) => {\n const fromHistory = history.filter((m) => m.isPinned);\n const seen = new Set(prev.map((m) => m.id));\n return [...fromHistory.filter((m) => !seen.has(m.id)), ...prev];\n });\n })\n .catch(() => {\n // Non-fatal — user can still see the preview slice and scroll\n // up will retry. onError is already surfaced by fetchMessages.\n });\n }\n } catch (err) {\n if (cancelled) return;\n const msg = err instanceof Error ? err.message : 'Failed to load conversation';\n setError(msg);\n setIsLoading(false);\n }\n };\n\n init();\n\n return () => {\n cancelled = true;\n if (joinedConversationId.current) {\n socket.leaveConversation(joinedConversationId.current);\n joinedConversationId.current = null;\n }\n typingTimers.current.forEach((timer) => clearTimeout(timer));\n typingTimers.current.clear();\n markedReadIdsRef.current.clear();\n setIsConnected(false);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [orderId]);\n\n // ── Send helpers ──\n\n // `persistedByCreate` tells the caller whether THEIR payload was written\n // by the REST create (true = don't also send via socket, that would dup).\n // - conversation already existed → false\n // - piggy-backed on someone else's in-flight create → false (their payload\n // needs a socket send)\n // - this caller kicked off the create → true (their payload was in the POST)\n const ensureConversation = useCallback(\n async (\n payload: SendMessagePayload\n ): Promise<{ conv: Conversation; persistedByCreate: boolean }> => {\n if (conversation) return { conv: conversation, persistedByCreate: false };\n\n if (ensureConversationInFlight.current) {\n const conv = await ensureConversationInFlight.current;\n return { conv, persistedByCreate: false };\n }\n\n const inflight = (async () => {\n const result = await createConversationWithMessage(orderId, payload, {\n name: buildName(),\n participantIds,\n });\n\n setConversation(result.conversation);\n setParticipants(result.conversation.participants);\n setMessages([result.message]);\n joinChannel(result.conversation);\n invalidatePreview(orderId);\n\n // Create-or-send may have appended our message to an EXISTING\n // study-scoped conversation with prior history — the init effect's\n // preview-backed load doesn't cover that case because `conversation`\n // was null when it ran. Pull authoritative history now and merge\n // (dedupe by id so the just-inserted message isn't duplicated).\n if (loadHistory) {\n fetchMessages(result.conversation.id)\n .then((history) => {\n setMessages((prev) => {\n const seen = new Set(prev.map((m) => m.id));\n const older = history.filter((m) => !seen.has(m.id));\n return [...older, ...prev];\n });\n setPinnedMessages((prev) => {\n const fromHistory = history.filter((m) => m.isPinned);\n const seen = new Set(prev.map((m) => m.id));\n return [...fromHistory.filter((m) => !seen.has(m.id)), ...prev];\n });\n })\n .catch(() => {\n // Non-fatal — fetchMessages already surfaces via onError.\n });\n }\n\n return result.conversation;\n })();\n\n ensureConversationInFlight.current = inflight;\n\n try {\n const conv = await inflight;\n return { conv, persistedByCreate: true };\n } finally {\n ensureConversationInFlight.current = null;\n }\n },\n [\n conversation,\n createConversationWithMessage,\n orderId,\n buildName,\n participantIds,\n joinChannel,\n invalidatePreview,\n loadHistory,\n fetchMessages,\n ]\n );\n\n const sendMessage = useCallback(\n async (body: string) => {\n const payload: SendMessagePayload = {\n body,\n type: 'text',\n ...(replyTo ? { replyToId: replyTo.id } : {}),\n };\n const { conv, persistedByCreate } = await ensureConversation(payload);\n setReplyTo(null);\n\n // Our message was already written by the REST create — skip the socket\n // push, otherwise we'd persist the same message twice.\n if (persistedByCreate) return;\n\n // Optimistic insert so the user sees their text instantly, regardless\n // of socket roundtrip. The server broadcast (via onMessage above) will\n // swap this in for the real, persisted message.\n const optimistic: Message = {\n id: `pending-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n conversationId: conv.id,\n senderId: config.userId,\n senderName: config.userName,\n senderRole: config.userRole,\n body,\n type: 'text',\n insertedAt: new Date().toISOString(),\n ...(replyTo\n ? {\n replyToId: replyTo.id,\n replyToSnapshot: {\n messageId: replyTo.id,\n senderId: replyTo.senderId,\n senderName: replyTo.senderName,\n body: replyTo.body,\n type: replyTo.type,\n },\n }\n : {}),\n };\n setMessages((prev) => [...prev, optimistic]);\n\n try {\n await socket.sendMessage(conv.id, payload);\n } catch (err) {\n // Surface the failure and drop the optimistic row so the user can retry.\n setMessages((prev) => prev.filter((m) => m.id !== optimistic.id));\n config.onError?.({\n code: 'SEND_FAILED',\n message: 'Failed to send message',\n details: err,\n });\n }\n },\n [ensureConversation, socket, replyTo, config]\n );\n\n const sendAudioMessage = useCallback(\n async (audioBlob: Blob, duration: number) => {\n if (!config.onUploadFile) return;\n const url = await config.onUploadFile(audioBlob, 'voice-message.webm');\n const payload: SendMessagePayload = {\n body: 'Voice message',\n type: 'audio',\n mediaUrl: url,\n mediaDuration: duration,\n };\n const { conv, persistedByCreate } = await ensureConversation(payload);\n if (persistedByCreate) return;\n await socket.sendMessage(conv.id, payload);\n },\n [config, ensureConversation, socket]\n );\n\n const sendFileMessage = useCallback(\n async (file: File) => {\n if (!config.onUploadFile) return;\n const url = await config.onUploadFile(file, file.name);\n const isImage = file.type.startsWith('image/');\n const payload: SendMessagePayload = {\n body: file.name,\n type: isImage ? 'image' : 'file',\n mediaUrl: url,\n fileName: file.name,\n };\n const { conv, persistedByCreate } = await ensureConversation(payload);\n if (persistedByCreate) return;\n await socket.sendMessage(conv.id, payload);\n },\n [config, ensureConversation, socket]\n );\n\n const sendDeepLink = useCallback(\n async (path: string, label: string) => {\n const payload: SendMessagePayload = {\n body: label,\n type: 'deep_link',\n metadata: { path },\n };\n const { conv, persistedByCreate } = await ensureConversation(payload);\n if (persistedByCreate) return;\n await socket.sendMessage(conv.id, payload);\n },\n [ensureConversation, socket]\n );\n\n const sendTypingIndicator = useCallback(\n (isTyping: boolean) => {\n if (!conversation || !isConnected) return;\n socket.sendTyping(conversation.id, isTyping);\n },\n [conversation, isConnected, socket]\n );\n\n const markAsRead = useCallback(\n (messageId: string) => {\n if (!conversation || !isConnected) return;\n if (markedReadIdsRef.current.has(messageId)) return;\n markedReadIdsRef.current.add(messageId);\n socket.markAsRead(conversation.id, messageId);\n },\n [conversation, isConnected, socket]\n );\n\n const loadMoreMessages = useCallback(async () => {\n if (!conversation || !hasMore || isLoading) return;\n\n const oldestMessage = messages[0];\n const before = oldestMessage?.id;\n\n setIsLoading(true);\n try {\n const older = await fetchMessages(conversation.id, { before });\n setMessages((prev) => [...older, ...prev]);\n setHasMore(older.length > 0);\n } catch (err) {\n config.onError?.({\n code: 'LOAD_ERROR',\n message: 'Failed to load older messages',\n details: err,\n });\n } finally {\n setIsLoading(false);\n }\n }, [conversation, hasMore, isLoading, messages, fetchMessages, config]);\n\n const pinMessage = useCallback(\n async (messageId: string) => {\n if (!conversation) return;\n try {\n await pinMessageApi(conversation.id, messageId);\n } catch (err) {\n config.onError?.({\n code: 'PIN_ERROR',\n message: 'Failed to pin message',\n details: err,\n });\n }\n },\n [conversation, pinMessageApi, config]\n );\n\n const unpinMessage = useCallback(\n async (messageId: string) => {\n if (!conversation) return;\n try {\n await unpinMessageApi(conversation.id, messageId);\n } catch (err) {\n config.onError?.({\n code: 'UNPIN_ERROR',\n message: 'Failed to unpin message',\n details: err,\n });\n }\n },\n [conversation, unpinMessageApi, config]\n );\n\n return {\n conversation,\n messages,\n pinnedMessages,\n participants,\n typingUsers,\n isLoading,\n hasMore,\n error,\n isConnected,\n replyTo,\n setReplyTo,\n sendMessage,\n sendAudioMessage,\n sendFileMessage,\n sendDeepLink,\n sendTyping: sendTypingIndicator,\n markAsRead,\n loadMoreMessages,\n pinMessage,\n unpinMessage,\n };\n}\n","import { useCallback, useState } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type {\n ChannelUpdatePayload,\n InviteUserPayload,\n CollabError,\n} from '../core/types';\n\ninterface UseChannelSettingsOptions {\n conversationId: string | null;\n}\n\ninterface UseChannelSettingsReturn {\n /** Invite a user to the conversation */\n inviteUser: (payload: InviteUserPayload) => Promise<void>;\n /** Remove a user from the conversation (admin/creator only) */\n removeUser: (userId: string) => Promise<void>;\n /** Current user leaves the conversation */\n leaveChannel: () => Promise<void>;\n /** Delete the conversation entirely (admin only) */\n deleteChannel: () => Promise<void>;\n /** Update channel name and/or picture */\n updateChannel: (payload: ChannelUpdatePayload) => Promise<void>;\n /** Whether an operation is in progress */\n isUpdating: boolean;\n /** Last error from any operation */\n error: CollabError | null;\n /** Whether current user can perform admin actions */\n isAdmin: boolean;\n}\n\nexport function useChannelSettings({ conversationId }: UseChannelSettingsOptions): UseChannelSettingsReturn {\n const { socket, config } = useCollab();\n const [isUpdating, setIsUpdating] = useState(false);\n const [error, setError] = useState<CollabError | null>(null);\n\n const isAdmin = config.userRole === 'admin';\n\n const withLoading = useCallback(\n async <T>(operation: () => Promise<T>): Promise<T | undefined> => {\n if (!conversationId) return;\n setIsUpdating(true);\n setError(null);\n try {\n const result = await operation();\n setIsUpdating(false);\n return result;\n } catch (err) {\n const collabError: CollabError =\n typeof err === 'object' && err !== null && 'code' in err\n ? (err as CollabError)\n : { code: 'UNKNOWN', message: 'Operation failed' };\n\n setError(collabError);\n setIsUpdating(false);\n config.onError?.(collabError);\n return undefined;\n }\n },\n [conversationId, config]\n );\n\n const inviteUser = useCallback(\n async (payload: InviteUserPayload) => {\n await withLoading(() => socket.inviteUser(conversationId!, payload));\n },\n [conversationId, socket, withLoading]\n );\n\n const removeUser = useCallback(\n async (userId: string) => {\n await withLoading(() => socket.removeUser(conversationId!, userId));\n },\n [conversationId, socket, withLoading]\n );\n\n const leaveChannel = useCallback(async () => {\n await withLoading(async () => {\n await socket.removeUser(conversationId!, config.userId);\n socket.leaveConversation(conversationId!);\n });\n }, [conversationId, socket, config.userId, withLoading]);\n\n const deleteChannel = useCallback(async () => {\n if (!isAdmin) {\n const err: CollabError = {\n code: 'FORBIDDEN',\n message: 'Only admins can delete channels',\n };\n setError(err);\n config.onError?.(err);\n return;\n }\n await withLoading(() => socket.deleteChannel(conversationId!));\n }, [conversationId, socket, isAdmin, config, withLoading]);\n\n const updateChannel = useCallback(\n async (payload: ChannelUpdatePayload) => {\n await withLoading(() => socket.updateChannel(conversationId!, payload));\n },\n [conversationId, socket, withLoading]\n );\n\n return {\n inviteUser,\n removeUser,\n leaveChannel,\n deleteChannel,\n updateChannel,\n isUpdating,\n error,\n isAdmin,\n };\n}\n","import { useCallback } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport { DEEP_LINK_PREFIX } from '../core/constants';\n\ninterface ParsedDeepLink {\n /** Full original link string */\n raw: string;\n /** The path after natoe:// (e.g. \"order/4521\") */\n path: string;\n /** The resource type (e.g. \"order\", \"report\", \"dicom\", \"study\") */\n resource: string;\n /** The resource ID */\n id: string;\n}\n\ninterface UseDeepLinksReturn {\n /** Parse a deep link string into structured data */\n parseDeepLink: (link: string) => ParsedDeepLink | null;\n /** Handle a deep link click — calls config.onDeepLink or config.onOpenDicom */\n handleDeepLink: (link: string) => void;\n /** Check if a string contains deep links */\n containsDeepLink: (text: string) => boolean;\n /** Extract all deep links from a message body */\n extractDeepLinks: (text: string) => ParsedDeepLink[];\n}\n\n/**\n * Parses and handles natoe:// deep links in messages.\n *\n * Supported formats:\n * natoe://order/4521 → opens order detail\n * natoe://report/4521 → opens report\n * natoe://dicom/4521 → opens DICOM viewer (uses onOpenDicom callback)\n * natoe://study/4521 → opens study detail\n */\nexport function useDeepLinks(): UseDeepLinksReturn {\n const { config } = useCollab();\n\n const parseDeepLink = useCallback((link: string): ParsedDeepLink | null => {\n if (!link.startsWith(DEEP_LINK_PREFIX)) return null;\n\n const path = link.slice(DEEP_LINK_PREFIX.length);\n const parts = path.split('/').filter(Boolean);\n\n if (parts.length < 2) return null;\n\n return {\n raw: link,\n path,\n resource: parts[0],\n id: parts[1],\n };\n }, []);\n\n const handleDeepLink = useCallback(\n (link: string) => {\n const parsed = parseDeepLink(link);\n if (!parsed) return;\n\n // DICOM links use the dedicated callback\n if (parsed.resource === 'dicom' && config.onOpenDicom) {\n config.onOpenDicom(parsed.id, '');\n return;\n }\n\n // Everything else goes through the generic deep link handler\n if (config.onDeepLink) {\n config.onDeepLink(parsed.path);\n }\n },\n [parseDeepLink, config]\n );\n\n const containsDeepLink = useCallback((text: string): boolean => {\n return text.includes(DEEP_LINK_PREFIX);\n }, []);\n\n const extractDeepLinks = useCallback(\n (text: string): ParsedDeepLink[] => {\n // Match natoe://path/segments patterns in text\n const regex = new RegExp(`${escapeRegex(DEEP_LINK_PREFIX)}[\\\\w/.-]+`, 'g');\n const matches = text.match(regex) || [];\n return matches.map(parseDeepLink).filter((link): link is ParsedDeepLink => link !== null);\n },\n [parseDeepLink]\n );\n\n return {\n parseDeepLink,\n handleDeepLink,\n containsDeepLink,\n extractDeepLinks,\n };\n}\n\nfunction escapeRegex(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import React from 'react';\nimport { buildChannelName } from '../core/channelName';\nimport type { PatientData, Participant } from '../core/types';\n\ninterface PatientHeaderProps {\n patientData: PatientData;\n participants: Participant[];\n onOpenDicom?: () => void;\n onOpenSettings?: () => void;\n className?: string;\n}\n\nexport function PatientHeader({\n patientData,\n onOpenDicom,\n onOpenSettings,\n className,\n}: PatientHeaderProps) {\n const hasDicom = !!(patientData.studyId && patientData.storageId);\n\n return (\n <div className={className} style={styles.container}>\n {/* Channel name row — primary identifier */}\n <div style={styles.infoRow}>\n <div style={styles.patientInfo}>\n <span style={styles.patientName}>{buildChannelName(patientData)}</span>\n </div>\n </div>\n\n {/* Secondary info — clinical context */}\n <div style={styles.secondaryRow}>\n {patientData.patientAge && (\n <span style={styles.secondary}>\n {patientData.patientAge}\n {patientData.patientSex ? `/${patientData.patientSex}` : ''}\n </span>\n )}\n {patientData.studyType && (\n <span style={styles.secondary}>{patientData.studyType}</span>\n )}\n {patientData.bodyParts && patientData.bodyParts.length > 0 && (\n <span style={styles.secondary}>{patientData.bodyParts.join(', ')}</span>\n )}\n {patientData.referringPhysician && (\n <span style={styles.secondary}>Ref: {patientData.referringPhysician}</span>\n )}\n </div>\n\n {/* Action buttons */}\n <div style={styles.actions}>\n {hasDicom && onOpenDicom && (\n <button onClick={onOpenDicom} style={styles.dicomButton} type=\"button\">\n View DICOM\n </button>\n )}\n {onOpenSettings && (\n <button onClick={onOpenSettings} style={styles.settingsButton} type=\"button\">\n Settings\n </button>\n )}\n </div>\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n padding: '12px 16px',\n borderBottom: '1px solid #e5e7eb',\n backgroundColor: '#f9fafb',\n },\n infoRow: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n patientInfo: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n flexWrap: 'wrap' as const,\n },\n patientName: {\n fontWeight: 600,\n fontSize: '17px',\n color: '#111827',\n },\n detail: {\n fontSize: '13px',\n color: '#6b7280',\n },\n studyType: {\n fontSize: '13px',\n color: '#2563eb',\n fontWeight: 500,\n },\n orderId: {\n fontSize: '12px',\n color: '#9ca3af',\n fontFamily: 'monospace',\n },\n secondaryRow: {\n display: 'flex',\n gap: '12px',\n marginTop: '4px',\n alignItems: 'center',\n },\n secondary: {\n fontSize: '13px',\n color: '#4b5563',\n },\n participantCount: {\n fontSize: '12px',\n color: '#6b7280',\n marginLeft: 'auto',\n },\n actions: {\n display: 'flex',\n gap: '8px',\n marginTop: '8px',\n },\n dicomButton: {\n minHeight: '40px',\n padding: '8px 16px',\n fontSize: '14px',\n fontWeight: 500,\n color: '#ffffff',\n backgroundColor: '#2563eb',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n settingsButton: {\n minHeight: '40px',\n padding: '8px 16px',\n fontSize: '14px',\n fontWeight: 500,\n color: '#374151',\n backgroundColor: '#ffffff',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n};\n","import React from 'react';\nimport type { MessageSnapshot } from '../core/types';\n\ninterface ReplyQuoteBlockProps {\n snapshot: MessageSnapshot;\n /** True when rendered inside an own-message bubble (affects color contrast) */\n inOwnBubble?: boolean;\n /** Called when user clicks the quote — host can scroll to the original message */\n onClick?: (messageId: string) => void;\n className?: string;\n}\n\n/**\n * Rendered inside a MessageBubble when the message is a reply.\n * Shows a compact quote of the original message.\n */\nexport function ReplyQuoteBlock({\n snapshot,\n inOwnBubble = false,\n onClick,\n className,\n}: ReplyQuoteBlockProps) {\n const baseBg = inOwnBubble ? 'rgba(255,255,255,0.18)' : '#f3f4f6';\n const barColor = inOwnBubble ? '#ffffff' : '#2563eb';\n const nameColor = inOwnBubble ? '#ffffff' : '#2563eb';\n const bodyColor = inOwnBubble ? 'rgba(255,255,255,0.85)' : '#4b5563';\n\n const preview = renderSnapshotPreview(snapshot);\n\n return (\n <div\n className={className}\n style={{ ...styles.container, backgroundColor: baseBg }}\n onClick={() => onClick?.(snapshot.messageId)}\n role={onClick ? 'button' : undefined}\n tabIndex={onClick ? 0 : undefined}\n >\n <div style={{ ...styles.bar, backgroundColor: barColor }} />\n <div style={styles.content}>\n <span style={{ ...styles.senderName, color: nameColor }}>{snapshot.senderName}</span>\n <span style={{ ...styles.body, color: bodyColor }}>{preview}</span>\n </div>\n </div>\n );\n}\n\nfunction renderSnapshotPreview(snapshot: MessageSnapshot): string {\n switch (snapshot.type) {\n case 'audio':\n return '🎤 Voice message';\n case 'image':\n return '📷 Image';\n case 'file':\n return '📎 File';\n case 'deep_link':\n return `🔗 ${snapshot.body}`;\n default: {\n const body = snapshot.body || '';\n return body.length > 80 ? `${body.slice(0, 80)}…` : body;\n }\n }\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n gap: '6px',\n padding: '4px 8px',\n marginBottom: '4px',\n borderRadius: '6px',\n cursor: 'pointer',\n maxWidth: '100%',\n },\n bar: {\n width: '3px',\n borderRadius: '2px',\n flexShrink: 0,\n },\n content: {\n display: 'flex',\n flexDirection: 'column',\n gap: '1px',\n minWidth: 0,\n overflow: 'hidden',\n },\n senderName: {\n fontSize: '11px',\n fontWeight: 600,\n lineHeight: '1.2',\n },\n body: {\n fontSize: '11px',\n lineHeight: '1.3',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n};\n","import React, { useState } from 'react';\nimport type { Participant } from '../core/types';\n\ninterface SeenByIndicatorProps {\n /** User IDs who have read the message */\n readBy: string[];\n /** All participants in the conversation — used to resolve names */\n participants: Participant[];\n /** Current user ID (excluded from the display) */\n currentUserId: string;\n /** Message sender ID (excluded from the display) */\n senderId: string;\n className?: string;\n}\n\n/**\n * WhatsApp-style \"Seen by\" indicator shown under own messages.\n * Shows up to 3 names inline; if more, shows remainder count with a tap-to-expand.\n *\n * Only renders when the current user is the sender (seen-by on others' messages\n * is redundant — they obviously saw their own message).\n */\nexport function SeenByIndicator({\n readBy,\n participants,\n currentUserId,\n senderId,\n className,\n}: SeenByIndicatorProps) {\n const [expanded, setExpanded] = useState(false);\n\n // Only show on own messages\n if (senderId !== currentUserId) return null;\n\n const seenByOthers = readBy\n .filter((id) => id !== currentUserId && id !== senderId)\n .map((id) => participants.find((p) => p.userId === id))\n .filter((p): p is Participant => !!p);\n\n if (seenByOthers.length === 0) return null;\n\n const displayCount = expanded ? seenByOthers.length : Math.min(3, seenByOthers.length);\n const shown = seenByOthers.slice(0, displayCount);\n const remainder = seenByOthers.length - displayCount;\n\n return (\n <div className={className} style={styles.container}>\n <span style={styles.checkmark}>✓✓</span>\n <span style={styles.label}>Seen by {shown.map((p) => p.userName ?? 'User').join(', ')}</span>\n {remainder > 0 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n setExpanded(true);\n }}\n style={styles.moreButton}\n type=\"button\"\n >\n +{remainder}\n </button>\n )}\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n marginTop: '2px',\n fontSize: '10px',\n opacity: 0.75,\n },\n checkmark: {\n fontSize: '10px',\n color: '#60a5fa',\n },\n label: {\n fontSize: '10px',\n color: 'inherit',\n },\n moreButton: {\n fontSize: '10px',\n fontWeight: 600,\n color: 'inherit',\n backgroundColor: 'transparent',\n border: 'none',\n padding: 0,\n cursor: 'pointer',\n textDecoration: 'underline',\n },\n};\n","import React from 'react';\nimport type { Message } from '../core/types';\n\ninterface MessageActionsMenuProps {\n message: Message;\n onReply: (message: Message) => void;\n onPin: (messageId: string) => void;\n onUnpin: (messageId: string) => void;\n onCopy?: (text: string) => void;\n /** True when the menu should show (hover / open state managed by parent) */\n visible: boolean;\n /** Whether we've hit the pin limit — if true, pin is disabled */\n pinDisabled?: boolean;\n className?: string;\n}\n\n/**\n * Inline action menu for a single message.\n * Parent controls visibility (typically via hover state in MessageBubble).\n */\nexport function MessageActionsMenu({\n message,\n onReply,\n onPin,\n onUnpin,\n onCopy,\n visible,\n pinDisabled = false,\n className,\n}: MessageActionsMenuProps) {\n if (!visible) return null;\n\n const isPinned = !!message.isPinned;\n const canCopy = message.type === 'text' && !!message.body;\n\n const handleCopy = () => {\n if (!onCopy) return;\n onCopy(message.body);\n };\n\n return (\n <div className={className} style={styles.container}>\n <button\n onClick={() => onReply(message)}\n style={styles.button}\n title=\"Reply\"\n type=\"button\"\n >\n ↩\n </button>\n\n {isPinned ? (\n <button\n onClick={() => onUnpin(message.id)}\n style={styles.button}\n title=\"Unpin\"\n type=\"button\"\n >\n 📌\n </button>\n ) : (\n <button\n onClick={() => onPin(message.id)}\n style={{\n ...styles.button,\n opacity: pinDisabled ? 0.4 : 1,\n cursor: pinDisabled ? 'not-allowed' : 'pointer',\n }}\n disabled={pinDisabled}\n title={pinDisabled ? 'Pin limit reached (max 3)' : 'Pin'}\n type=\"button\"\n >\n 📌\n </button>\n )}\n\n {canCopy && onCopy && (\n <button\n onClick={handleCopy}\n style={styles.button}\n title=\"Copy text\"\n type=\"button\"\n >\n ⎘\n </button>\n )}\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n gap: '2px',\n padding: '2px',\n backgroundColor: '#ffffff',\n border: '1px solid #e5e7eb',\n borderRadius: '20px',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)',\n },\n button: {\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '12px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n },\n};\n","import React from 'react';\n\nexport function FileIcon({ size = 18, color = 'currentColor' }: { size?: number; color?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill={color}\n aria-hidden=\"true\"\n >\n <path d=\"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z\" />\n </svg>\n );\n}\n","import React from 'react';\n\nexport function PinIcon({ size = 14, color = 'currentColor' }: { size?: number; color?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill={color}\n aria-hidden=\"true\"\n >\n <path d=\"M16 9V4l1 0c.55 0 1-.45 1-1s-.45-1-1-1H7c-.55 0-1 .45-1 1s.45 1 1 1l1 0v5c0 1.66-1.34 3-3 3v2h5.97v7l1 1 1-1v-7H19v-2c-1.66 0-3-1.34-3-3z\" />\n </svg>\n );\n}\n","import React, { useState } from 'react';\nimport { ReplyQuoteBlock } from './ReplyQuoteBlock';\nimport { SeenByIndicator } from './SeenByIndicator';\nimport { MessageActionsMenu } from './MessageActionsMenu';\nimport { FileIcon } from './icons/FileIcon';\nimport { PinIcon } from './icons/PinIcon';\nimport type { Message, Participant, UserRole } from '../core/types';\nimport { DEEP_LINK_PREFIX } from '../core/constants';\n\nconst ROLE_LABELS: Record<UserRole, string> = {\n radiologist: 'Radiologist',\n lab: 'Imaging Center',\n physician: 'Physician',\n admin: 'Admin',\n};\n\ninterface MessageBubbleProps {\n message: Message;\n isOwn: boolean;\n /** Participants list — needed for SeenByIndicator */\n participants?: Participant[];\n /** Current user ID — needed for SeenByIndicator */\n currentUserId?: string;\n /** Show \"seen by\" indicator under own messages (default true — inline disables this) */\n showSeenBy?: boolean;\n onDeepLinkClick?: (link: string) => void;\n onReply?: (message: Message) => void;\n onPin?: (messageId: string) => void;\n onUnpin?: (messageId: string) => void;\n onCopy?: (text: string) => void;\n onReplyJumpTo?: (messageId: string) => void;\n /** True if pin limit reached — disables pin action */\n pinDisabled?: boolean;\n className?: string;\n}\n\nexport function MessageBubble({\n message,\n isOwn,\n participants = [],\n currentUserId = '',\n showSeenBy = true,\n onDeepLinkClick,\n onReply,\n onPin,\n onUnpin,\n onCopy,\n onReplyJumpTo,\n pinDisabled = false,\n className,\n}: MessageBubbleProps) {\n const [isHovered, setIsHovered] = useState(false);\n\n if (message.type === 'system') {\n return <SystemBubble message={message} />;\n }\n\n const hasActions = !!(onReply || onPin || onUnpin || onCopy);\n\n return (\n <div\n className={className}\n style={{\n ...styles.wrapper,\n justifyContent: isOwn ? 'flex-end' : 'flex-start',\n }}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n <div style={styles.bubbleWrapper}>\n <div\n style={{\n ...styles.bubble,\n ...(isOwn ? styles.ownBubble : styles.otherBubble),\n }}\n >\n {/* Pinned indicator */}\n {message.isPinned && (\n <div style={styles.pinnedBadge}>\n <PinIcon size={12} />\n <span>Pinned</span>\n </div>\n )}\n\n {/* Reply quote (when this message is a reply) */}\n {message.replyToSnapshot && (\n <ReplyQuoteBlock\n snapshot={message.replyToSnapshot}\n inOwnBubble={isOwn}\n onClick={onReplyJumpTo}\n />\n )}\n\n {/* Sender info for others' messages */}\n {!isOwn && (\n <div style={styles.senderRow}>\n <span style={styles.senderName}>{message.senderName}</span>\n <RoleBadge role={message.senderRole} />\n </div>\n )}\n\n {/* Message content by type */}\n {message.type === 'text' && <TextContent body={message.body} onDeepLinkClick={onDeepLinkClick} />}\n {message.type === 'audio' && <AudioContent mediaUrl={message.mediaUrl} duration={message.mediaDuration} />}\n {message.type === 'image' && <ImageContent mediaUrl={message.mediaUrl} fileName={message.fileName} />}\n {message.type === 'file' && <FileContent mediaUrl={message.mediaUrl} fileName={message.fileName} />}\n {message.type === 'deep_link' && (\n <DeepLinkContent body={message.body} metadata={message.metadata} onDeepLinkClick={onDeepLinkClick} />\n )}\n\n {/* Timestamp */}\n <div style={styles.timestamp}>{formatTime(message.insertedAt)}</div>\n\n {/* Seen by indicator (own messages only) */}\n {showSeenBy && isOwn && (\n <SeenByIndicator\n readBy={message.readBy ?? []}\n participants={participants}\n currentUserId={currentUserId}\n senderId={message.senderId}\n />\n )}\n </div>\n\n {/* Actions menu (hover) */}\n {hasActions && (\n <div\n style={{\n ...styles.actionsWrapper,\n [isOwn ? 'right' : 'left']: '100%',\n [isOwn ? 'marginRight' : 'marginLeft']: '6px',\n }}\n >\n <MessageActionsMenu\n message={message}\n onReply={onReply ?? (() => {})}\n onPin={onPin ?? (() => {})}\n onUnpin={onUnpin ?? (() => {})}\n onCopy={onCopy}\n visible={isHovered}\n pinDisabled={pinDisabled}\n />\n </div>\n )}\n </div>\n </div>\n );\n}\n\n// ── Sub-components ──\n\nfunction TextContent({ body, onDeepLinkClick }: { body: string; onDeepLinkClick?: (link: string) => void }) {\n if (body.includes(DEEP_LINK_PREFIX)) {\n const parts = body.split(new RegExp(`(${escapeRegex(DEEP_LINK_PREFIX)}[\\\\w/.-]+)`, 'g'));\n return (\n <p style={styles.textBody}>\n {parts.map((part, i) =>\n part.startsWith(DEEP_LINK_PREFIX) ? (\n <a\n key={i}\n onClick={(e) => {\n e.preventDefault();\n onDeepLinkClick?.(part);\n }}\n href=\"#\"\n style={styles.deepLink}\n >\n {part}\n </a>\n ) : (\n <span key={i}>{part}</span>\n )\n )}\n </p>\n );\n }\n\n return <p style={styles.textBody}>{body}</p>;\n}\n\nfunction AudioContent({ mediaUrl, duration }: { mediaUrl?: string; duration?: number }) {\n if (!mediaUrl) return null;\n\n return (\n <div style={styles.audioContainer}>\n <audio controls preload=\"metadata\" style={styles.audioPlayer}>\n <source src={mediaUrl} />\n </audio>\n {duration != null && <span style={styles.audioDuration}>{formatDuration(duration)}</span>}\n </div>\n );\n}\n\nfunction ImageContent({ mediaUrl, fileName }: { mediaUrl?: string; fileName?: string }) {\n if (!mediaUrl) return null;\n\n return (\n <a href={mediaUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n <img src={mediaUrl} alt={fileName || 'Image'} style={styles.imagePreview} />\n </a>\n );\n}\n\nfunction FileContent({ mediaUrl, fileName }: { mediaUrl?: string; fileName?: string }) {\n if (!mediaUrl) return null;\n\n return (\n <a href={mediaUrl} target=\"_blank\" rel=\"noopener noreferrer\" style={styles.fileLink}>\n <FileIcon size={20} />\n <span style={styles.fileName}>{fileName || 'Download file'}</span>\n </a>\n );\n}\n\nfunction DeepLinkContent({\n body,\n metadata,\n onDeepLinkClick,\n}: {\n body: string;\n metadata?: Record<string, unknown>;\n onDeepLinkClick?: (link: string) => void;\n}) {\n const path = metadata?.path as string | undefined;\n\n return (\n <div\n style={styles.deepLinkCard}\n onClick={() => path && onDeepLinkClick?.(`${DEEP_LINK_PREFIX}${path}`)}\n >\n <span style={styles.deepLinkLabel}>{body}</span>\n {path && <span style={styles.deepLinkPath}>{DEEP_LINK_PREFIX}{path}</span>}\n </div>\n );\n}\n\nfunction SystemBubble({ message }: { message: Message }) {\n return (\n <div style={styles.systemMessage}>\n <span>{message.body}</span>\n <span style={styles.systemTime}>{formatTime(message.insertedAt)}</span>\n </div>\n );\n}\n\nfunction RoleBadge({ role }: { role: UserRole }) {\n const colors: Record<UserRole, string> = {\n radiologist: '#7c3aed',\n lab: '#2563eb',\n physician: '#059669',\n admin: '#dc2626',\n };\n\n return (\n <span style={{ ...styles.roleBadge, backgroundColor: `${colors[role]}15`, color: colors[role] }}>\n {ROLE_LABELS[role] ?? role}\n </span>\n );\n}\n\n// ── Helpers ──\n\nfunction formatTime(iso: string): string {\n try {\n return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n } catch {\n return '';\n }\n}\n\nfunction formatDuration(seconds: number): string {\n const m = Math.floor(seconds / 60);\n const s = seconds % 60;\n return `${m}:${s.toString().padStart(2, '0')}`;\n}\n\nfunction escapeRegex(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n// ── Styles ──\n\nconst styles: Record<string, React.CSSProperties> = {\n wrapper: {\n display: 'flex',\n marginBottom: '8px',\n paddingLeft: '16px',\n paddingRight: '16px',\n },\n bubbleWrapper: {\n position: 'relative',\n maxWidth: '75%',\n },\n bubble: {\n padding: '10px 14px',\n borderRadius: '12px',\n wordBreak: 'break-word',\n },\n ownBubble: {\n backgroundColor: '#2563eb',\n color: '#ffffff',\n borderBottomRightRadius: '4px',\n },\n otherBubble: {\n backgroundColor: '#f3f4f6',\n color: '#111827',\n borderBottomLeftRadius: '4px',\n },\n pinnedBadge: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '4px',\n fontSize: '12px',\n fontWeight: 600,\n marginBottom: '4px',\n color: '#6b7280',\n },\n senderRow: {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n marginBottom: '4px',\n },\n senderName: {\n fontSize: '13px',\n fontWeight: 600,\n color: '#374151',\n },\n roleBadge: {\n fontSize: '11px',\n fontWeight: 600,\n padding: '2px 8px',\n borderRadius: '4px',\n },\n textBody: {\n margin: 0,\n fontSize: '15px',\n lineHeight: '1.45',\n },\n timestamp: {\n fontSize: '12px',\n color: 'inherit',\n opacity: 0.8,\n marginTop: '4px',\n textAlign: 'right' as const,\n },\n actionsWrapper: {\n position: 'absolute' as const,\n top: '50%',\n transform: 'translateY(-50%)',\n zIndex: 10,\n },\n audioContainer: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n },\n audioPlayer: {\n height: '32px',\n maxWidth: '220px',\n },\n audioDuration: {\n fontSize: '12px',\n opacity: 0.7,\n whiteSpace: 'nowrap' as const,\n },\n imagePreview: {\n maxWidth: '240px',\n maxHeight: '180px',\n borderRadius: '8px',\n objectFit: 'cover' as const,\n cursor: 'pointer',\n },\n fileLink: {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n textDecoration: 'none',\n color: 'inherit',\n padding: '6px 0',\n },\n fileIcon: {\n fontSize: '18px',\n },\n fileName: {\n fontSize: '13px',\n textDecoration: 'underline',\n },\n deepLink: {\n color: '#3b82f6',\n textDecoration: 'underline',\n cursor: 'pointer',\n },\n deepLinkCard: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '2px',\n padding: '8px',\n backgroundColor: '#eff6ff',\n borderRadius: '8px',\n border: '1px solid #bfdbfe',\n cursor: 'pointer',\n },\n deepLinkLabel: {\n fontSize: '13px',\n fontWeight: 500,\n color: '#1d4ed8',\n },\n deepLinkPath: {\n fontSize: '11px',\n color: '#6b7280',\n fontFamily: 'monospace',\n },\n systemMessage: {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n gap: '8px',\n padding: '6px 16px',\n fontSize: '13px',\n color: '#6b7280',\n },\n systemTime: {\n fontSize: '12px',\n color: '#9ca3af',\n },\n};\n","/**\n * Shared date/time labels for the chat UI.\n *\n * Two surfaces consume these:\n * - The inbox row's right-side timestamp ({@link formatInboxTimestamp})\n * - The in-chat day divider pill ({@link formatDayDivider})\n *\n * Bucketing is identical between them, so a conversation labeled \"Tuesday\"\n * in the inbox is grouped under a \"Tuesday\" pill inside its chat — no\n * drift between surfaces.\n *\n * Format choices:\n * - Full date: \"15 May 2026\" (fixed English short month, day, year)\n * - Weekday: \"Tuesday\" (fixed English long weekday)\n * - Time: locale-defaulted (respects the user's OS region)\n */\n\nconst SHORT_MONTHS = [\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\n];\n\nconst LONG_WEEKDAYS = [\n 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',\n];\n\nconst ONE_DAY_MS = 86_400_000;\n\nfunction parseSafe(iso: string): Date | null {\n const d = new Date(iso);\n return Number.isNaN(d.getTime()) ? null : d;\n}\n\n/** Returns the start of the day for the given date (local time). */\nfunction startOfDay(d: Date): Date {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate());\n}\n\n/** Number of calendar days between two dates (local time). Negative if a < b. */\nfunction daysBetween(a: Date, b: Date): number {\n return Math.floor((startOfDay(a).getTime() - startOfDay(b).getTime()) / ONE_DAY_MS);\n}\n\nfunction formatFullDate(d: Date): string {\n return `${d.getDate()} ${SHORT_MONTHS[d.getMonth()]} ${d.getFullYear()}`;\n}\n\nfunction formatLocaleTime(d: Date): string {\n // Locale-default time. Tries to match the user's OS preference for 12h vs\n // 24h. Falls back to a manual 12h format if Intl is unavailable.\n try {\n return d.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });\n } catch {\n const h = d.getHours();\n const m = d.getMinutes().toString().padStart(2, '0');\n const suffix = h >= 12 ? 'PM' : 'AM';\n const h12 = ((h + 11) % 12) + 1;\n return `${h12}:${m} ${suffix}`;\n }\n}\n\n/**\n * Inbox row timestamp (right-edge of each conversation row).\n *\n * today → \"9:42 PM\"\n * yesterday → \"Yesterday\"\n * last 7 days → weekday name (\"Tuesday\")\n * older → \"15 May 2026\"\n */\nexport function formatInboxTimestamp(iso: string | null | undefined): string {\n if (!iso) return '';\n const d = parseSafe(iso);\n if (!d) return '';\n\n const diffDays = daysBetween(new Date(), d);\n\n if (diffDays === 0) return formatLocaleTime(d);\n if (diffDays === 1) return 'Yesterday';\n if (diffDays > 1 && diffDays < 7) return LONG_WEEKDAYS[d.getDay()];\n return formatFullDate(d);\n}\n\n/**\n * In-chat day divider pill text.\n *\n * today → \"Today\"\n * yesterday → \"Yesterday\"\n * last 7 days → weekday name (\"Tuesday\")\n * older → \"15 May 2026\"\n */\nexport function formatDayDivider(iso: string | null | undefined): string {\n if (!iso) return '';\n const d = parseSafe(iso);\n if (!d) return '';\n\n const diffDays = daysBetween(new Date(), d);\n\n if (diffDays === 0) return 'Today';\n if (diffDays === 1) return 'Yesterday';\n if (diffDays > 1 && diffDays < 7) return LONG_WEEKDAYS[d.getDay()];\n return formatFullDate(d);\n}\n\n/**\n * Stable day-bucket key for grouping messages. Two messages with the same\n * key belong under the same day divider.\n */\nexport function dayBucketKey(iso: string | null | undefined): string {\n if (!iso) return '';\n const d = parseSafe(iso);\n if (!d) return '';\n return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;\n}\n","import React, { useEffect, useRef, useCallback, useImperativeHandle, forwardRef } from 'react';\nimport { MessageBubble } from './MessageBubble';\nimport { dayBucketKey, formatDayDivider } from '../core/dateLabels';\nimport type { Message, Participant, TypingEvent } from '../core/types';\n\nexport interface MessageListHandle {\n /** Scroll to a specific message by ID (used by pin jump-to) */\n scrollToMessage: (messageId: string) => void;\n}\n\ninterface MessageListProps {\n messages: Message[];\n currentUserId: string;\n participants?: Participant[];\n showSeenBy?: boolean;\n typingUsers: TypingEvent[];\n hasMore: boolean;\n isLoading: boolean;\n onLoadMore: () => void;\n onDeepLinkClick?: (link: string) => void;\n onMessageVisible?: (messageId: string) => void;\n onReply?: (message: Message) => void;\n onPin?: (messageId: string) => void;\n onUnpin?: (messageId: string) => void;\n onCopy?: (text: string) => void;\n pinDisabled?: boolean;\n className?: string;\n}\n\nexport const MessageList = forwardRef<MessageListHandle, MessageListProps>(function MessageList(\n {\n messages,\n currentUserId,\n participants = [],\n showSeenBy = true,\n typingUsers,\n hasMore,\n isLoading,\n onLoadMore,\n onDeepLinkClick,\n onMessageVisible,\n onReply,\n onPin,\n onUnpin,\n onCopy,\n pinDisabled,\n className,\n },\n ref\n) {\n const containerRef = useRef<HTMLDivElement>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const prevMessageCount = useRef(messages.length);\n\n useImperativeHandle(\n ref,\n () => ({\n scrollToMessage: (messageId: string) => {\n const element = containerRef.current?.querySelector(`[data-message-id=\"${messageId}\"]`);\n if (element) {\n element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n // Brief flash to draw attention\n (element as HTMLElement).style.transition = 'background-color 200ms';\n (element as HTMLElement).style.backgroundColor = '#fef3c7';\n setTimeout(() => {\n (element as HTMLElement).style.backgroundColor = '';\n }, 800);\n }\n },\n }),\n []\n );\n\n // Auto-scroll to bottom on new messages\n useEffect(() => {\n if (messages.length > prevMessageCount.current) {\n const lastMessage = messages[messages.length - 1];\n const isOwnMessage = lastMessage?.senderId === currentUserId;\n\n // Always scroll for own messages, or if already near bottom\n if (isOwnMessage || isNearBottom(containerRef.current)) {\n bottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n }\n }\n prevMessageCount.current = messages.length;\n }, [messages, currentUserId]);\n\n // Intersection observer for marking messages as read\n useEffect(() => {\n if (!onMessageVisible || !containerRef.current) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n const messageId = (entry.target as HTMLElement).dataset.messageId;\n if (messageId) onMessageVisible(messageId);\n }\n });\n },\n { root: containerRef.current, threshold: 0.5 }\n );\n\n const messageElements = containerRef.current.querySelectorAll('[data-message-id]');\n messageElements.forEach((el) => observer.observe(el));\n\n return () => observer.disconnect();\n }, [messages, onMessageVisible]);\n\n // Scroll-to-top detection for loading more messages\n const handleScroll = useCallback(() => {\n if (!containerRef.current || !hasMore || isLoading) return;\n\n if (containerRef.current.scrollTop < 50) {\n onLoadMore();\n }\n }, [hasMore, isLoading, onLoadMore]);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={styles.container}\n onScroll={handleScroll}\n >\n {/* Load more indicator */}\n {isLoading && (\n <div style={styles.loadingMore}>Loading earlier messages...</div>\n )}\n\n {hasMore && !isLoading && messages.length > 0 && (\n <button onClick={onLoadMore} style={styles.loadMoreButton} type=\"button\">\n Load earlier messages\n </button>\n )}\n\n {/* Empty state */}\n {messages.length === 0 && !isLoading && (\n <div style={styles.empty}>\n <p style={styles.emptyTitle}>No messages yet</p>\n <p style={styles.emptySubtitle}>Start the conversation about this study</p>\n </div>\n )}\n\n {/* Message list — day dividers inserted when the bucket key changes.\n Messages arrive sorted oldest → newest, so we walk forward and\n emit a pill before any message whose day differs from the prior. */}\n {messages.map((message, index) => {\n const currentBucket = dayBucketKey(message.insertedAt);\n const prevBucket =\n index === 0 ? null : dayBucketKey(messages[index - 1].insertedAt);\n const showDivider = currentBucket && currentBucket !== prevBucket;\n\n return (\n <React.Fragment key={message.id}>\n {showDivider && (\n <div style={styles.dayDivider} role=\"separator\" aria-label=\"Date\">\n <span style={styles.dayDividerPill}>\n {formatDayDivider(message.insertedAt)}\n </span>\n </div>\n )}\n <div data-message-id={message.id}>\n <MessageBubble\n message={message}\n isOwn={message.senderId === currentUserId}\n participants={participants}\n currentUserId={currentUserId}\n showSeenBy={showSeenBy}\n onDeepLinkClick={onDeepLinkClick}\n onReply={onReply}\n onPin={onPin}\n onUnpin={onUnpin}\n onCopy={onCopy}\n pinDisabled={pinDisabled}\n />\n </div>\n </React.Fragment>\n );\n })}\n\n {/* Typing indicators */}\n {typingUsers.length > 0 && (\n <div style={styles.typingIndicator}>\n {typingUsers.map((t) => t.userName ?? 'Someone').join(', ')}\n {typingUsers.length === 1 ? ' is ' : ' are '}typing...\n </div>\n )}\n\n <div ref={bottomRef} />\n </div>\n );\n});\n\nfunction isNearBottom(container: HTMLDivElement | null): boolean {\n if (!container) return true;\n const threshold = 150;\n return container.scrollHeight - container.scrollTop - container.clientHeight < threshold;\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n flex: 1,\n overflowY: 'auto',\n paddingTop: '12px',\n paddingBottom: '8px',\n },\n loadingMore: {\n textAlign: 'center',\n padding: '12px',\n fontSize: '14px',\n color: '#6b7280',\n },\n loadMoreButton: {\n display: 'block',\n margin: '0 auto 12px',\n minHeight: '36px',\n padding: '8px 18px',\n fontSize: '13px',\n color: '#374151',\n backgroundColor: 'transparent',\n border: '1px solid #d1d5db',\n borderRadius: '18px',\n cursor: 'pointer',\n },\n empty: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '48px 16px',\n color: '#6b7280',\n },\n emptyTitle: {\n fontSize: '16px',\n fontWeight: 600,\n color: '#374151',\n margin: '0 0 4px',\n },\n emptySubtitle: {\n fontSize: '14px',\n margin: 0,\n },\n typingIndicator: {\n padding: '4px 16px 8px',\n fontSize: '13px',\n color: '#6b7280',\n fontStyle: 'italic',\n },\n dayDivider: {\n display: 'flex',\n justifyContent: 'center',\n margin: '12px 0 8px',\n },\n dayDividerPill: {\n display: 'inline-block',\n padding: '5px 14px',\n fontSize: '13px',\n fontWeight: 500,\n color: '#334155',\n backgroundColor: '#e2e8f0',\n borderRadius: '12px',\n letterSpacing: '0.2px',\n },\n};\n","import React from 'react';\nimport type { Message } from '../core/types';\n\ninterface ReplyPreviewProps {\n /** The message being replied to */\n message: Message;\n /** Called when user cancels the reply */\n onCancel: () => void;\n className?: string;\n}\n\n/**\n * Shown above the MessageInput when the user is composing a reply.\n * Displays the quoted message with a cancel button.\n */\nexport function ReplyPreview({ message, onCancel, className }: ReplyPreviewProps) {\n const preview = renderQuotedPreview(message);\n\n return (\n <div className={className} style={styles.container}>\n <div style={styles.bar} />\n <div style={styles.content}>\n <div style={styles.senderLine}>\n <span style={styles.senderIcon}>↩</span>\n <span style={styles.senderName}>Replying to {message.senderName}</span>\n </div>\n <div style={styles.preview}>{preview}</div>\n </div>\n <button onClick={onCancel} style={styles.cancelButton} title=\"Cancel reply\" type=\"button\">\n ✕\n </button>\n </div>\n );\n}\n\nfunction renderQuotedPreview(message: Message): string {\n switch (message.type) {\n case 'audio':\n return '🎤 Voice message';\n case 'image':\n return `📷 ${message.fileName || 'Image'}`;\n case 'file':\n return `📎 ${message.fileName || 'File'}`;\n case 'deep_link':\n return `🔗 ${message.body}`;\n default: {\n const body = message.body || '';\n return body.length > 120 ? `${body.slice(0, 120)}…` : body;\n }\n }\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n alignItems: 'stretch',\n gap: '8px',\n padding: '8px 12px',\n backgroundColor: '#f9fafb',\n borderTop: '1px solid #e5e7eb',\n },\n bar: {\n width: '3px',\n backgroundColor: '#2563eb',\n borderRadius: '2px',\n flexShrink: 0,\n },\n content: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n minWidth: 0,\n },\n senderLine: {\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n },\n senderIcon: {\n fontSize: '11px',\n color: '#2563eb',\n },\n senderName: {\n fontSize: '12px',\n fontWeight: 600,\n color: '#2563eb',\n },\n preview: {\n fontSize: '12px',\n color: '#6b7280',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n cancelButton: {\n alignSelf: 'center',\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#6b7280',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '12px',\n flexShrink: 0,\n },\n};\n","import React from 'react';\n\nexport function AttachIcon({ size = 20, color = 'currentColor' }: { size?: number; color?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill={color}\n aria-hidden=\"true\"\n >\n <path d=\"M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z\" />\n </svg>\n );\n}\n","import React from 'react';\n\nexport function SendIcon({ size = 20, color = 'currentColor' }: { size?: number; color?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill={color}\n aria-hidden=\"true\"\n >\n <path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\" />\n </svg>\n );\n}\n","import React from 'react';\n\nexport function CloseIcon({ size = 18, color = 'currentColor' }: { size?: number; color?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill={color}\n aria-hidden=\"true\"\n >\n <path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\" />\n </svg>\n );\n}\n","import React, { useState, useRef, useCallback, useEffect } from 'react';\n// MIC DISABLED — voice messaging temporarily removed. Imports kept for easy re-enable.\n// import { useAudioRecorder } from '../hooks/useAudioRecorder';\n// import { MicIcon } from './icons/MicIcon';\nimport { ReplyPreview } from './ReplyPreview';\nimport { AttachIcon } from './icons/AttachIcon';\nimport { SendIcon } from './icons/SendIcon';\nimport { CloseIcon } from './icons/CloseIcon';\nimport { MAX_FILE_SIZE, SUPPORTED_IMAGE_TYPES } from '../core/constants';\nimport type { Message } from '../core/types';\n\ninterface MessageInputProps {\n onSendText: (body: string) => Promise<void>;\n /** @deprecated MIC DISABLED — kept in the prop signature for backward compat. */\n onSendAudio?: (blob: Blob, duration: number) => Promise<void>;\n onSendFile: (file: File) => Promise<void>;\n onTyping: (isTyping: boolean) => void;\n /** When set, shows a ReplyPreview above the input */\n replyTo?: Message | null;\n /** Called when user cancels the reply */\n onCancelReply?: () => void;\n disabled?: boolean;\n placeholder?: string;\n className?: string;\n}\n\nexport function MessageInput({\n onSendText,\n // MIC DISABLED — onSendAudio still accepted but unused.\n // onSendAudio,\n onSendFile,\n onTyping,\n replyTo,\n onCancelReply,\n disabled = false,\n placeholder = 'Type a message...',\n className,\n}: MessageInputProps) {\n const [text, setText] = useState('');\n const [isSending, setIsSending] = useState(false);\n const [fileError, setFileError] = useState<string | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const typingTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const isTypingRef = useRef(false);\n // Synchronous guard — useState's async update can't block a second click\n // that lands before React re-renders. The ref flips immediately.\n const sendingRef = useRef(false);\n\n // MIC DISABLED — voice recorder hook is not invoked. Restore by uncommenting\n // the original destructure below (and the import at the top of the file).\n // const { isRecording, duration, start: startRecording, stop: stopRecording, cancel: cancelRecording, isSupported: micSupported, error: micError } = useAudioRecorder();\n\n // Rising-edge only — fire once when the user starts typing, then a single\n // \"stopped\" event after 2s of idle. Previously this called onTyping(true)\n // on EVERY keystroke, flooding the socket with redundant events.\n const handleTyping = useCallback(() => {\n if (!isTypingRef.current) {\n isTypingRef.current = true;\n onTyping(true);\n }\n\n if (typingTimeoutRef.current) {\n clearTimeout(typingTimeoutRef.current);\n }\n\n typingTimeoutRef.current = setTimeout(() => {\n isTypingRef.current = false;\n onTyping(false);\n }, 2000);\n }, [onTyping]);\n\n useEffect(() => {\n return () => {\n if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);\n };\n }, []);\n\n const handleSendText = useCallback(async () => {\n const trimmed = text.trim();\n if (!trimmed || sendingRef.current) return;\n\n sendingRef.current = true;\n setIsSending(true);\n if (isTypingRef.current) {\n isTypingRef.current = false;\n onTyping(false);\n }\n if (typingTimeoutRef.current) {\n clearTimeout(typingTimeoutRef.current);\n typingTimeoutRef.current = null;\n }\n\n try {\n await onSendText(trimmed);\n setText('');\n } finally {\n sendingRef.current = false;\n setIsSending(false);\n }\n }, [text, onSendText, onTyping]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSendText();\n }\n },\n [handleSendText]\n );\n\n // MIC DISABLED — audio stop handler unused. Restore alongside useAudioRecorder.\n // const handleAudioStop = useCallback(async () => {\n // const result = await stopRecording();\n // if (result) {\n // setIsSending(true);\n // try {\n // await onSendAudio(result.blob, result.duration);\n // } finally {\n // setIsSending(false);\n // }\n // }\n // }, [stopRecording, onSendAudio]);\n\n const handleFileSelect = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n setFileError(null);\n\n if (file.size > MAX_FILE_SIZE) {\n setFileError(`File too large. Maximum size is ${MAX_FILE_SIZE / (1024 * 1024)}MB.`);\n return;\n }\n\n setIsSending(true);\n try {\n await onSendFile(file);\n } finally {\n setIsSending(false);\n // Reset file input\n if (fileInputRef.current) fileInputRef.current.value = '';\n }\n },\n [onSendFile]\n );\n\n return (\n <div className={className} style={styles.container}>\n {/* Reply preview */}\n {replyTo && onCancelReply && (\n <ReplyPreview message={replyTo} onCancel={onCancelReply} />\n )}\n\n {/* Error messages */}\n {fileError && (\n <div style={styles.error} role=\"alert\">\n <span style={styles.errorText}>{fileError}</span>\n <button\n type=\"button\"\n onClick={() => setFileError(null)}\n aria-label=\"Dismiss error\"\n style={styles.errorDismiss}\n >\n <CloseIcon size={16} />\n </button>\n </div>\n )}\n\n {/* MIC DISABLED — recording bar and mic button removed.\n Original blocks kept here for easy re-enable:\n\n {isRecording ? (\n <div style={styles.recordingBar}>\n <div style={styles.recordingIndicator}>\n <span style={styles.recordingDot} />\n Recording {formatDuration(duration)}\n </div>\n <div style={styles.recordingActions}>\n <button onClick={cancelRecording} style={styles.cancelButton} type=\"button\">Cancel</button>\n <button onClick={handleAudioStop} style={styles.stopButton} type=\"button\">Send</button>\n </div>\n </div>\n ) : (\n ...input bar with mic button...\n )}\n */}\n <div style={styles.inputBar}>\n {/* MIC DISABLED — mic button hidden.\n {micSupported && (\n <button onClick={startRecording} disabled={disabled || isSending} style={styles.iconButton} title=\"Record voice message\" type=\"button\">\n <MicIcon size={20} color=\"#374151\" />\n </button>\n )}\n */}\n\n {/* File attach */}\n <button\n onClick={() => fileInputRef.current?.click()}\n disabled={disabled || isSending}\n style={styles.iconButton}\n aria-label=\"Attach file\"\n title=\"Attach file\"\n type=\"button\"\n >\n <AttachIcon size={22} color=\"#374151\" />\n </button>\n\n <input\n ref={fileInputRef}\n type=\"file\"\n onChange={handleFileSelect}\n style={{ display: 'none' }}\n accept={[...SUPPORTED_IMAGE_TYPES, 'application/pdf', '.doc', '.docx'].join(',')}\n />\n\n {/* Text input */}\n <textarea\n value={text}\n onChange={(e) => {\n setText(e.target.value);\n handleTyping();\n }}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled || isSending}\n rows={1}\n style={styles.textarea}\n />\n\n {/* Send button */}\n <button\n onClick={handleSendText}\n disabled={disabled || isSending || !text.trim()}\n aria-label=\"Send message\"\n title=\"Send message\"\n style={{\n ...styles.sendButton,\n opacity: text.trim() ? 1 : 0.4,\n }}\n type=\"button\"\n >\n <SendIcon size={20} color=\"#ffffff\" />\n </button>\n </div>\n </div>\n );\n}\n\n// MIC DISABLED — formatDuration was only used by the recording UI.\n// Kept here for easy restore when mic is re-enabled.\n// function formatDuration(seconds: number): string {\n// const m = Math.floor(seconds / 60);\n// const s = seconds % 60;\n// return `${m}:${s.toString().padStart(2, '0')}`;\n// }\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n borderTop: '1px solid #e5e7eb',\n backgroundColor: '#ffffff',\n },\n error: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '8px',\n padding: '8px 12px 8px 16px',\n fontSize: '13px',\n color: '#b91c1c',\n backgroundColor: '#fef2f2',\n borderTop: '1px solid #fecaca',\n },\n errorText: {\n flex: 1,\n minWidth: 0,\n },\n errorDismiss: {\n width: '28px',\n height: '28px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n color: '#b91c1c',\n borderRadius: '4px',\n cursor: 'pointer',\n flexShrink: 0,\n },\n inputBar: {\n display: 'flex',\n alignItems: 'flex-end',\n gap: '6px',\n padding: '10px 12px',\n },\n iconButton: {\n width: '44px',\n height: '44px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n flexShrink: 0,\n },\n textarea: {\n flex: 1,\n padding: '10px 14px',\n fontSize: '15px',\n lineHeight: '1.45',\n border: '1px solid #d1d5db',\n borderRadius: '22px',\n resize: 'none',\n outline: 'none',\n fontFamily: 'inherit',\n maxHeight: '120px',\n minHeight: '44px',\n },\n sendButton: {\n width: '44px',\n height: '44px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: '#2563eb',\n color: '#ffffff',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n flexShrink: 0,\n },\n recordingBar: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '12px 16px',\n backgroundColor: '#fef2f2',\n },\n recordingIndicator: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n fontSize: '14px',\n color: '#dc2626',\n fontWeight: 500,\n },\n recordingDot: {\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: '#dc2626',\n animation: 'pulse 1.5s infinite',\n },\n recordingActions: {\n display: 'flex',\n gap: '8px',\n },\n cancelButton: {\n padding: '6px 14px',\n fontSize: '13px',\n color: '#6b7280',\n backgroundColor: '#ffffff',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n stopButton: {\n padding: '6px 14px',\n fontSize: '13px',\n fontWeight: 500,\n color: '#ffffff',\n backgroundColor: '#dc2626',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n};\n","import React from 'react';\nimport type { Participant, UserRole } from '../core/types';\n\ninterface ParticipantsListProps {\n participants: Participant[];\n currentUserId: string;\n isAdmin: boolean;\n onRemoveUser: (userId: string) => Promise<void>;\n className?: string;\n}\n\nexport function ParticipantsList({\n participants,\n currentUserId,\n isAdmin,\n onRemoveUser,\n className,\n}: ParticipantsListProps) {\n return (\n <div className={className} style={styles.list}>\n {participants.map((participant) => (\n <div key={participant.userId} style={styles.item}>\n {/* Avatar */}\n <div style={styles.avatar}>\n {participant.avatar ? (\n <img src={participant.avatar} alt=\"\" style={styles.avatarImg} />\n ) : (\n <span style={styles.avatarFallback}>\n {(participant.userName ?? '?').charAt(0).toUpperCase()}\n </span>\n )}\n {/* Online indicator */}\n <span\n style={{\n ...styles.statusDot,\n backgroundColor: participant.isOnline ? '#22c55e' : '#d1d5db',\n }}\n />\n </div>\n\n {/* Info */}\n <div style={styles.info}>\n <span style={styles.name}>\n {participant.userName ?? fallbackName(participant.userRole)}\n {participant.userId === currentUserId && (\n <span style={styles.youBadge}> (you)</span>\n )}\n </span>\n <RoleBadge role={participant.userRole} />\n </div>\n\n {/* Remove button (admin only, can't remove self) */}\n {isAdmin && participant.userId !== currentUserId && (\n <button\n onClick={() => onRemoveUser(participant.userId)}\n style={styles.removeButton}\n title={`Remove ${participant.userName ?? fallbackName(participant.userRole)}`}\n type=\"button\"\n >\n ✕\n </button>\n )}\n </div>\n ))}\n </div>\n );\n}\n\nfunction fallbackName(role: UserRole): string {\n switch (role) {\n case 'lab':\n return 'Imaging Center';\n case 'radiologist':\n return 'Radiologist';\n case 'physician':\n return 'Physician';\n case 'admin':\n return 'Natoe Admin';\n default:\n return 'User';\n }\n}\n\nfunction RoleBadge({ role }: { role: UserRole }) {\n const colors: Record<UserRole, { bg: string; text: string }> = {\n radiologist: { bg: '#f5f3ff', text: '#7c3aed' },\n lab: { bg: '#eff6ff', text: '#2563eb' },\n physician: { bg: '#ecfdf5', text: '#059669' },\n admin: { bg: '#fef2f2', text: '#dc2626' },\n };\n\n const color = colors[role];\n\n return (\n <span style={{ ...styles.roleBadge, backgroundColor: color.bg, color: color.text }}>\n {role}\n </span>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n list: {\n display: 'flex',\n flexDirection: 'column',\n },\n item: {\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n padding: '8px 0',\n borderBottom: '1px solid #f9fafb',\n },\n avatar: {\n position: 'relative',\n width: '32px',\n height: '32px',\n flexShrink: 0,\n },\n avatarImg: {\n width: '32px',\n height: '32px',\n borderRadius: '50%',\n objectFit: 'cover' as const,\n },\n avatarFallback: {\n width: '32px',\n height: '32px',\n borderRadius: '50%',\n backgroundColor: '#e5e7eb',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '13px',\n fontWeight: 600,\n color: '#6b7280',\n },\n statusDot: {\n position: 'absolute' as const,\n bottom: '0',\n right: '0',\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n border: '2px solid #ffffff',\n },\n info: {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n flex: 1,\n minWidth: 0,\n },\n name: {\n fontSize: '13px',\n fontWeight: 500,\n color: '#111827',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap' as const,\n },\n youBadge: {\n fontSize: '11px',\n fontWeight: 400,\n color: '#9ca3af',\n },\n roleBadge: {\n fontSize: '10px',\n fontWeight: 500,\n padding: '1px 6px',\n borderRadius: '4px',\n whiteSpace: 'nowrap' as const,\n },\n removeButton: {\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '11px',\n color: '#9ca3af',\n flexShrink: 0,\n },\n};\n","import React, { useState } from 'react';\nimport { ParticipantsList } from './ParticipantsList';\nimport type { Participant, InviteUserPayload, UserRole, CollabError } from '../core/types';\n\ninterface ChannelSettingsProps {\n conversationId: string;\n channelName: string;\n channelPicture?: string;\n participants: Participant[];\n currentUserId: string;\n isAdmin: boolean;\n isUpdating: boolean;\n error: CollabError | null;\n onUpdateChannel: (payload: { name?: string; picture?: string }) => Promise<void>;\n onInviteUser: (payload: InviteUserPayload) => Promise<void>;\n onRemoveUser: (userId: string) => Promise<void>;\n onLeaveChannel: () => Promise<void>;\n onDeleteChannel: () => Promise<void>;\n onClose: () => void;\n className?: string;\n}\n\nexport function ChannelSettings({\n channelName,\n participants,\n currentUserId,\n isAdmin,\n isUpdating,\n error,\n onUpdateChannel,\n onInviteUser,\n onRemoveUser,\n onLeaveChannel,\n onDeleteChannel,\n onClose,\n className,\n}: ChannelSettingsProps) {\n const [editingName, setEditingName] = useState(false);\n const [nameValue, setNameValue] = useState(channelName);\n const [showInvite, setShowInvite] = useState(false);\n const [inviteId, setInviteId] = useState('');\n const [inviteName, setInviteName] = useState('');\n const [inviteRole, setInviteRole] = useState<UserRole>('radiologist');\n const [confirmDelete, setConfirmDelete] = useState(false);\n\n const handleSaveName = async () => {\n if (nameValue.trim() && nameValue !== channelName) {\n await onUpdateChannel({ name: nameValue.trim() });\n }\n setEditingName(false);\n };\n\n const handleInvite = async () => {\n if (!inviteId.trim() || !inviteName.trim()) return;\n await onInviteUser({\n userId: inviteId.trim(),\n userName: inviteName.trim(),\n userRole: inviteRole,\n });\n setInviteId('');\n setInviteName('');\n setShowInvite(false);\n };\n\n const handleDelete = async () => {\n if (!confirmDelete) {\n setConfirmDelete(true);\n return;\n }\n await onDeleteChannel();\n };\n\n return (\n <div className={className} style={styles.container}>\n {/* Header */}\n <div style={styles.header}>\n <h3 style={styles.title}>Channel Settings</h3>\n <button onClick={onClose} style={styles.closeButton} type=\"button\">\n ✕\n </button>\n </div>\n\n {/* Error */}\n {error && (\n <div style={styles.error}>{error.message}</div>\n )}\n\n {/* Channel name */}\n <div style={styles.section}>\n <label style={styles.label}>Channel Name</label>\n {editingName ? (\n <div style={styles.editRow}>\n <input\n value={nameValue}\n onChange={(e) => setNameValue(e.target.value)}\n style={styles.input}\n autoFocus\n />\n <button onClick={handleSaveName} disabled={isUpdating} style={styles.saveButton} type=\"button\">\n Save\n </button>\n <button onClick={() => setEditingName(false)} style={styles.cancelButton} type=\"button\">\n Cancel\n </button>\n </div>\n ) : (\n <div style={styles.editRow}>\n <span style={styles.channelName}>{channelName}</span>\n <button onClick={() => setEditingName(true)} style={styles.editButton} type=\"button\">\n Edit\n </button>\n </div>\n )}\n </div>\n\n {/* Participants */}\n <div style={styles.section}>\n <div style={styles.sectionHeader}>\n <label style={styles.label}>Participants ({participants.length})</label>\n <button onClick={() => setShowInvite(!showInvite)} style={styles.addButton} type=\"button\">\n + Add\n </button>\n </div>\n\n {/* Invite form */}\n {showInvite && (\n <div style={styles.inviteForm}>\n <input\n value={inviteId}\n onChange={(e) => setInviteId(e.target.value)}\n placeholder=\"User ID\"\n style={styles.input}\n />\n <input\n value={inviteName}\n onChange={(e) => setInviteName(e.target.value)}\n placeholder=\"User Name\"\n style={styles.input}\n />\n <select\n value={inviteRole}\n onChange={(e) => setInviteRole(e.target.value as UserRole)}\n style={styles.input}\n >\n <option value=\"radiologist\">Radiologist</option>\n <option value=\"lab\">Lab</option>\n <option value=\"physician\">Physician</option>\n <option value=\"admin\">Admin</option>\n </select>\n <div style={styles.inviteActions}>\n <button onClick={handleInvite} disabled={isUpdating} style={styles.saveButton} type=\"button\">\n Invite\n </button>\n <button onClick={() => setShowInvite(false)} style={styles.cancelButton} type=\"button\">\n Cancel\n </button>\n </div>\n </div>\n )}\n\n <ParticipantsList\n participants={participants}\n currentUserId={currentUserId}\n isAdmin={isAdmin}\n onRemoveUser={onRemoveUser}\n />\n </div>\n\n {/* Actions */}\n <div style={styles.dangerZone}>\n <button onClick={onLeaveChannel} disabled={isUpdating} style={styles.leaveButton} type=\"button\">\n Leave Channel\n </button>\n\n {isAdmin && (\n <button\n onClick={handleDelete}\n disabled={isUpdating}\n style={confirmDelete ? styles.confirmDeleteButton : styles.deleteButton}\n type=\"button\"\n >\n {confirmDelete ? 'Confirm Delete' : 'Delete Channel'}\n </button>\n )}\n </div>\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n backgroundColor: '#ffffff',\n },\n header: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '12px 16px',\n borderBottom: '1px solid #e5e7eb',\n },\n title: {\n margin: 0,\n fontSize: '16px',\n fontWeight: 600,\n },\n closeButton: {\n width: '28px',\n height: '28px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '14px',\n color: '#6b7280',\n },\n error: {\n padding: '8px 16px',\n fontSize: '13px',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n },\n section: {\n padding: '16px',\n borderBottom: '1px solid #f3f4f6',\n },\n sectionHeader: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n marginBottom: '8px',\n },\n label: {\n fontSize: '12px',\n fontWeight: 600,\n color: '#6b7280',\n textTransform: 'uppercase' as const,\n letterSpacing: '0.05em',\n },\n channelName: {\n fontSize: '14px',\n color: '#111827',\n },\n editRow: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginTop: '6px',\n },\n input: {\n padding: '6px 10px',\n fontSize: '13px',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n outline: 'none',\n width: '100%',\n },\n editButton: {\n padding: '4px 10px',\n fontSize: '12px',\n color: '#2563eb',\n backgroundColor: 'transparent',\n border: 'none',\n cursor: 'pointer',\n },\n saveButton: {\n padding: '6px 12px',\n fontSize: '12px',\n fontWeight: 500,\n color: '#ffffff',\n backgroundColor: '#2563eb',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n whiteSpace: 'nowrap' as const,\n },\n cancelButton: {\n padding: '6px 12px',\n fontSize: '12px',\n color: '#6b7280',\n backgroundColor: 'transparent',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n cursor: 'pointer',\n whiteSpace: 'nowrap' as const,\n },\n addButton: {\n padding: '4px 10px',\n fontSize: '12px',\n fontWeight: 500,\n color: '#2563eb',\n backgroundColor: '#eff6ff',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n },\n inviteForm: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '8px',\n padding: '12px',\n marginBottom: '12px',\n backgroundColor: '#f9fafb',\n borderRadius: '8px',\n },\n inviteActions: {\n display: 'flex',\n gap: '8px',\n },\n dangerZone: {\n padding: '16px',\n marginTop: 'auto',\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '8px',\n },\n leaveButton: {\n padding: '8px',\n fontSize: '13px',\n fontWeight: 500,\n color: '#b45309',\n backgroundColor: '#fffbeb',\n border: '1px solid #fde68a',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n deleteButton: {\n padding: '8px',\n fontSize: '13px',\n fontWeight: 500,\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n confirmDeleteButton: {\n padding: '8px',\n fontSize: '13px',\n fontWeight: 600,\n color: '#ffffff',\n backgroundColor: '#dc2626',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n};\n","import React, { useState } from 'react';\nimport type { Message } from '../core/types';\n\ninterface PinnedMessagesBarProps {\n pinnedMessages: Message[];\n /** Clicking a pinned message scrolls to it in the thread */\n onJumpTo: (messageId: string) => void;\n /** Called when user unpins a message */\n onUnpin: (messageId: string) => void;\n className?: string;\n}\n\n/**\n * Horizontal strip at the top of the thread showing pinned messages (max 3).\n * Cycles through them on click if more than one.\n */\nexport function PinnedMessagesBar({\n pinnedMessages,\n onJumpTo,\n onUnpin,\n className,\n}: PinnedMessagesBarProps) {\n const [index, setIndex] = useState(0);\n\n if (pinnedMessages.length === 0) return null;\n\n const safeIndex = Math.min(index, pinnedMessages.length - 1);\n const current = pinnedMessages[safeIndex];\n const preview = renderPinPreview(current);\n\n const handleClick = () => {\n onJumpTo(current.id);\n if (pinnedMessages.length > 1) {\n setIndex((prev) => (prev + 1) % pinnedMessages.length);\n }\n };\n\n return (\n <div className={className} style={styles.container}>\n <div style={styles.indicator}>\n <span style={styles.pinIcon}>📌</span>\n {pinnedMessages.length > 1 && (\n <div style={styles.segments}>\n {pinnedMessages.map((_, i) => (\n <span\n key={i}\n style={{\n ...styles.segment,\n backgroundColor: i === safeIndex ? '#2563eb' : '#d1d5db',\n }}\n />\n ))}\n </div>\n )}\n </div>\n\n <button\n onClick={handleClick}\n style={styles.contentButton}\n type=\"button\"\n title=\"Click to jump to message\"\n >\n <div style={styles.label}>\n Pinned {pinnedMessages.length > 1 ? `(${safeIndex + 1}/${pinnedMessages.length})` : ''}\n </div>\n <div style={styles.preview}>\n <span style={styles.sender}>{current.senderName}:</span> {preview}\n </div>\n </button>\n\n <button\n onClick={(e) => {\n e.stopPropagation();\n onUnpin(current.id);\n }}\n style={styles.unpinButton}\n title=\"Unpin this message\"\n type=\"button\"\n >\n ✕\n </button>\n </div>\n );\n}\n\nfunction renderPinPreview(message: Message): string {\n switch (message.type) {\n case 'audio':\n return '🎤 Voice message';\n case 'image':\n return `📷 ${message.fileName || 'Image'}`;\n case 'file':\n return `📎 ${message.fileName || 'File'}`;\n case 'deep_link':\n return `🔗 ${message.body}`;\n default: {\n const body = message.body || '';\n return body.length > 100 ? `${body.slice(0, 100)}…` : body;\n }\n }\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '6px 12px',\n backgroundColor: '#eff6ff',\n borderBottom: '1px solid #dbeafe',\n },\n indicator: {\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n flexShrink: 0,\n },\n pinIcon: {\n fontSize: '13px',\n },\n segments: {\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n },\n segment: {\n width: '3px',\n height: '6px',\n borderRadius: '1px',\n },\n contentButton: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n padding: '2px 0',\n backgroundColor: 'transparent',\n border: 'none',\n textAlign: 'left',\n cursor: 'pointer',\n minWidth: 0,\n overflow: 'hidden',\n },\n label: {\n fontSize: '11px',\n fontWeight: 600,\n color: '#2563eb',\n },\n preview: {\n fontSize: '12px',\n color: '#374151',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n sender: {\n fontWeight: 600,\n },\n unpinButton: {\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: '#6b7280',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '11px',\n flexShrink: 0,\n },\n};\n","import React, { useRef, useState } from 'react';\nimport { useConversation } from '../hooks/useConversation';\nimport { useChannelSettings } from '../hooks/useChannelSettings';\nimport { useDeepLinks } from '../hooks/useDeepLinks';\nimport { useCollab } from '../context/CollabProvider';\nimport { PatientHeader } from './PatientHeader';\nimport { MessageList, type MessageListHandle } from './MessageList';\nimport { MessageInput } from './MessageInput';\nimport { ChannelSettings } from './ChannelSettings';\nimport { PinnedMessagesBar } from './PinnedMessagesBar';\nimport { MAX_PINNED_MESSAGES } from '../core/constants';\nimport type { PatientData } from '../core/types';\n\ninterface CollabPanelProps {\n /** Order ID — one conversation per study */\n orderId: string;\n /** Patient/study data displayed in the header */\n patientData: PatientData;\n /** Participant user IDs — only used when creating a brand-new conversation */\n participantIds?: string[];\n /** Show \"seen by\" indicator under own messages (default true) */\n showSeenBy?: boolean;\n /** Custom class name for the outer container */\n className?: string;\n /** Custom inline styles for the outer container */\n style?: React.CSSProperties;\n}\n\n/**\n * Full collaboration panel: patient header + pinned bar + message thread + input.\n * Supports reply, pin/unpin, and (optionally) seen-by indicators.\n */\nexport function CollabPanel({\n orderId,\n patientData,\n participantIds,\n showSeenBy = true,\n className,\n style,\n}: CollabPanelProps) {\n const { config } = useCollab();\n const [showSettings, setShowSettings] = useState(false);\n const messageListRef = useRef<MessageListHandle>(null);\n\n const {\n conversation,\n messages,\n pinnedMessages,\n participants,\n typingUsers,\n isLoading,\n hasMore,\n error,\n replyTo,\n setReplyTo,\n sendMessage,\n sendAudioMessage,\n sendFileMessage,\n sendTyping,\n markAsRead,\n loadMoreMessages,\n pinMessage,\n unpinMessage,\n } = useConversation({ orderId, patientData, participantIds });\n\n const channelSettings = useChannelSettings({\n conversationId: conversation?.id ?? null,\n });\n\n const { handleDeepLink } = useDeepLinks();\n\n const handleOpenDicom = () => {\n if (patientData.studyId && patientData.storageId && config.onOpenDicom) {\n config.onOpenDicom(patientData.studyId, patientData.storageId);\n }\n };\n\n const handleJumpToMessage = (messageId: string) => {\n messageListRef.current?.scrollToMessage(messageId);\n };\n\n const handleCopy = async (text: string) => {\n try {\n if (navigator.clipboard) {\n await navigator.clipboard.writeText(text);\n }\n } catch {\n // Silent fail — clipboard not available\n }\n };\n\n const pinDisabled = pinnedMessages.length >= MAX_PINNED_MESSAGES;\n\n if (error) {\n return (\n <div className={className} style={{ ...panelStyles.container, ...style }}>\n <div style={panelStyles.errorState}>\n <p style={panelStyles.errorTitle}>Unable to load conversation</p>\n <p style={panelStyles.errorMessage}>{error}</p>\n </div>\n </div>\n );\n }\n\n if (isLoading && !conversation) {\n return (\n <div className={className} style={{ ...panelStyles.container, ...style }}>\n <div style={panelStyles.loadingState}>Loading conversation...</div>\n </div>\n );\n }\n\n return (\n <div className={className} style={{ ...panelStyles.container, ...style }}>\n {showSettings && conversation ? (\n <ChannelSettings\n conversationId={conversation.id}\n channelName={conversation.name}\n channelPicture={conversation.picture}\n participants={participants}\n currentUserId={config.userId}\n isAdmin={channelSettings.isAdmin}\n isUpdating={channelSettings.isUpdating}\n error={channelSettings.error}\n onUpdateChannel={channelSettings.updateChannel}\n onInviteUser={channelSettings.inviteUser}\n onRemoveUser={channelSettings.removeUser}\n onLeaveChannel={channelSettings.leaveChannel}\n onDeleteChannel={channelSettings.deleteChannel}\n onClose={() => setShowSettings(false)}\n />\n ) : (\n <>\n <PatientHeader\n patientData={patientData}\n participants={participants}\n onOpenDicom={handleOpenDicom}\n onOpenSettings={() => setShowSettings(true)}\n />\n\n {pinnedMessages.length > 0 && (\n <PinnedMessagesBar\n pinnedMessages={pinnedMessages}\n onJumpTo={handleJumpToMessage}\n onUnpin={unpinMessage}\n />\n )}\n\n <MessageList\n ref={messageListRef}\n messages={messages}\n currentUserId={config.userId}\n participants={participants}\n showSeenBy={showSeenBy}\n typingUsers={typingUsers}\n hasMore={hasMore}\n isLoading={isLoading}\n onLoadMore={loadMoreMessages}\n onDeepLinkClick={handleDeepLink}\n onMessageVisible={markAsRead}\n onReply={setReplyTo}\n onPin={pinMessage}\n onUnpin={unpinMessage}\n onCopy={handleCopy}\n pinDisabled={pinDisabled}\n />\n\n <MessageInput\n onSendText={sendMessage}\n onSendAudio={sendAudioMessage}\n onSendFile={sendFileMessage}\n onTyping={sendTyping}\n replyTo={replyTo}\n onCancelReply={() => setReplyTo(null)}\n />\n </>\n )}\n </div>\n );\n}\n\nconst panelStyles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n backgroundColor: '#ffffff',\n borderRadius: '8px',\n overflow: 'hidden',\n border: '1px solid #e5e7eb',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n },\n loadingState: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n fontSize: '14px',\n color: '#9ca3af',\n },\n errorState: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n padding: '24px',\n textAlign: 'center',\n },\n errorTitle: {\n fontSize: '15px',\n fontWeight: 500,\n color: '#dc2626',\n margin: '0 0 4px',\n },\n errorMessage: {\n fontSize: '13px',\n color: '#6b7280',\n margin: 0,\n },\n};\n","import React from 'react';\n\nexport function MinimizeIcon({ size = 18, color = 'currentColor' }: { size?: number; color?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill={color}\n aria-hidden=\"true\"\n >\n <path d=\"M6 19h12v2H6z\" />\n </svg>\n );\n}\n\nexport function ExpandIcon({ size = 18, color = 'currentColor' }: { size?: number; color?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill={color}\n aria-hidden=\"true\"\n >\n <path d=\"M4 4h16v16H4V4zm2 4v10h12V8H6z\" />\n </svg>\n );\n}\n","import React, { useState, useRef, useCallback, useEffect } from 'react';\nimport { CollabPanel } from './CollabPanel';\nimport { buildChannelName } from '../core/channelName';\nimport { CloseIcon } from './icons/CloseIcon';\nimport { MinimizeIcon, ExpandIcon } from './icons/MinimizeIcon';\nimport type { PatientData } from '../core/types';\n\ninterface CollabPopupProps {\n /** Order ID for this conversation */\n orderId: string;\n /** Patient/study data */\n patientData: PatientData;\n /** Participant user IDs — only used when creating a brand-new conversation */\n participantIds?: string[];\n /** Whether the popup is open */\n isOpen: boolean;\n /** Close the popup */\n onClose: () => void;\n /** Initial position (defaults to bottom-right) */\n initialPosition?: { x: number; y: number };\n /** Width of the popup */\n width?: number;\n /** Height of the popup */\n height?: number;\n className?: string;\n}\n\n/**\n * Draggable floating chat popup — drop-in replacement for DraggableChatPopup.\n * Renders a CollabPanel inside a movable, resizable container.\n */\nexport function CollabPopup({\n orderId,\n patientData,\n participantIds,\n isOpen,\n onClose,\n initialPosition,\n width = 380,\n height = 520,\n className,\n}: CollabPopupProps) {\n // Default spawn: anchored bottom-right but offset vertically by enough\n // to clear a standard FAB (56px) + its 24px margin + visual breathing room\n // so the popup never lands on top of a host-app launcher button.\n const [position, setPosition] = useState(\n initialPosition || {\n x: window.innerWidth - width - 24,\n y: Math.max(24, window.innerHeight - height - 104),\n }\n );\n const [isDragging, setIsDragging] = useState(false);\n const [isMinimized, setIsMinimized] = useState(false);\n const dragOffset = useRef({ x: 0, y: 0 });\n const containerRef = useRef<HTMLDivElement>(null);\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n // Only allow dragging from the drag handle area\n if (!(e.target as HTMLElement).closest('[data-drag-handle]')) return;\n\n setIsDragging(true);\n dragOffset.current = {\n x: e.clientX - position.x,\n y: e.clientY - position.y,\n };\n e.preventDefault();\n },\n [position]\n );\n\n // ESC key to close — works only when popup is open\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose();\n }\n };\n\n window.addEventListener('keydown', handleKey);\n return () => window.removeEventListener('keydown', handleKey);\n }, [isOpen, onClose]);\n\n useEffect(() => {\n if (!isDragging) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n setPosition({\n x: Math.max(0, Math.min(e.clientX - dragOffset.current.x, window.innerWidth - width)),\n y: Math.max(0, Math.min(e.clientY - dragOffset.current.y, window.innerHeight - (isMinimized ? 52 : height))),\n });\n };\n\n const handleMouseUp = () => {\n setIsDragging(false);\n };\n\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n };\n }, [isDragging, width, height, isMinimized]);\n\n if (!isOpen) return null;\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{\n ...styles.container,\n left: position.x,\n top: position.y,\n width,\n height: isMinimized ? 52 : height,\n cursor: isDragging ? 'grabbing' : 'default',\n }}\n onMouseDown={handleMouseDown}\n >\n {/* Drag handle / title bar */}\n <div data-drag-handle style={styles.titleBar}>\n <span style={styles.titleText}>{buildChannelName(patientData)}</span>\n <div style={styles.titleActions}>\n <button\n onClick={() => setIsMinimized(!isMinimized)}\n style={styles.titleButton}\n aria-label={isMinimized ? 'Expand chat' : 'Minimize chat'}\n title={isMinimized ? 'Expand' : 'Minimize'}\n type=\"button\"\n >\n {isMinimized ? <ExpandIcon size={16} color=\"#cbd5e1\" /> : <MinimizeIcon size={16} color=\"#cbd5e1\" />}\n </button>\n <button\n onClick={onClose}\n style={styles.titleButton}\n aria-label=\"Close chat\"\n title=\"Close\"\n type=\"button\"\n >\n <CloseIcon size={16} color=\"#cbd5e1\" />\n </button>\n </div>\n </div>\n\n {/* Panel content */}\n {!isMinimized && (\n <div style={styles.panelWrapper}>\n <CollabPanel orderId={orderId} patientData={patientData} participantIds={participantIds} />\n </div>\n )}\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n position: 'fixed',\n zIndex: 9999,\n borderRadius: '12px',\n boxShadow: '0 8px 30px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08)',\n overflow: 'hidden',\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: '#ffffff',\n border: '1px solid #e5e7eb',\n transition: 'height 0.2s ease',\n },\n titleBar: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '0 8px 0 14px',\n height: '52px',\n backgroundColor: '#1e293b',\n cursor: 'grab',\n userSelect: 'none',\n flexShrink: 0,\n },\n titleText: {\n fontSize: '15px',\n fontWeight: 500,\n color: '#ffffff',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n titleActions: {\n display: 'flex',\n gap: '4px',\n flexShrink: 0,\n },\n titleButton: {\n width: '40px',\n height: '40px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n color: '#cbd5e1',\n },\n panelWrapper: {\n flex: 1,\n overflow: 'hidden',\n },\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type {\n ConversationPreview,\n Message,\n Participant,\n PatientData,\n SendMessagePayload,\n} from '../core/types';\nimport { buildChannelName } from '../core/channelName';\n\ninterface UseInlineCollabOptions {\n orderId: string;\n patientData: PatientData;\n /** Participant IDs passed to the backend only when creating a new conversation */\n participantIds?: string[];\n /** Max messages to keep in inline state (default 5) */\n messageLimit?: number;\n}\n\ninterface UseInlineCollabReturn {\n hasConversation: boolean;\n messages: Message[];\n participants: Participant[];\n unreadCount: number;\n isLoading: boolean;\n isSubscribed: boolean;\n error: string | null;\n sendMessage: (body: string) => Promise<void>;\n /** Send a voice message — uploads the blob via config.onUploadFile first */\n sendAudioMessage: (audioBlob: Blob, duration: number) => Promise<void>;\n /** Attach to the DOM element that represents the row — drives lazy socket subscription */\n containerRef: (element: HTMLElement | null) => void;\n}\n\n/**\n * Lightweight hook for inline chat in table rows.\n *\n * Behavior:\n * - On mount: fetches preview (batched) — no socket work\n * - If conversation exists AND row becomes visible: joins Phoenix channel (real-time)\n * - If row scrolls out of view: leaves channel (frees resources)\n * - First sendMessage creates conversation atomically + starts real-time flow\n * - Subsequent sends go through the socket\n */\nexport function useInlineCollab({\n orderId,\n patientData,\n participantIds = [],\n messageLimit = 5,\n}: UseInlineCollabOptions): UseInlineCollabReturn {\n const {\n socket,\n config,\n requestPreview,\n invalidatePreview,\n createConversationWithMessage,\n } = useCollab();\n\n const [preview, setPreview] = useState<ConversationPreview | null>(null);\n const [messages, setMessages] = useState<Message[]>([]);\n const [participants, setParticipants] = useState<Participant[]>([]);\n const [unreadCount, setUnreadCount] = useState(0);\n const [isLoading, setIsLoading] = useState(true);\n const [isSubscribed, setIsSubscribed] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const elementRef = useRef<HTMLElement | null>(null);\n const observerRef = useRef<IntersectionObserver | null>(null);\n const subscribedConversationIdRef = useRef<string | null>(null);\n\n const trimToLimit = useCallback(\n (msgs: Message[]): Message[] =>\n msgs.length > messageLimit ? msgs.slice(msgs.length - messageLimit) : msgs,\n [messageLimit]\n );\n\n const buildName = useCallback(\n (): string => buildChannelName(patientData),\n [patientData]\n );\n\n // ── Fetch preview on mount (batched) ──\n useEffect(() => {\n let cancelled = false;\n\n const load = async () => {\n setIsLoading(true);\n setError(null);\n try {\n const result = await requestPreview(orderId);\n if (cancelled) return;\n setPreview(result);\n if (result) {\n setMessages(trimToLimit(result.lastMessages));\n setParticipants(result.participants);\n setUnreadCount(result.unreadCount);\n }\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err.message : 'Failed to load preview');\n } finally {\n if (!cancelled) setIsLoading(false);\n }\n };\n\n load();\n return () => {\n cancelled = true;\n };\n }, [orderId, requestPreview, trimToLimit]);\n\n // ── Subscribe/unsubscribe socket based on visibility ──\n const subscribe = useCallback(\n (conversationId: string) => {\n if (subscribedConversationIdRef.current === conversationId) return;\n\n socket.joinConversation(conversationId, {\n onMessage: (msg) => {\n setMessages((prev) => trimToLimit([...prev, msg]));\n if (msg.senderId !== config.userId) {\n setUnreadCount((prev) => prev + 1);\n }\n },\n onUserJoined: (participant) => {\n setParticipants((prev) =>\n prev.some((p) => p.userId === participant.userId) ? prev : [...prev, participant]\n );\n },\n onUserLeft: (participant) => {\n setParticipants((prev) => prev.filter((p) => p.userId !== participant.userId));\n },\n });\n\n subscribedConversationIdRef.current = conversationId;\n setIsSubscribed(true);\n },\n [socket, trimToLimit, config.userId]\n );\n\n const unsubscribe = useCallback(() => {\n const convId = subscribedConversationIdRef.current;\n if (convId) {\n socket.leaveConversation(convId);\n subscribedConversationIdRef.current = null;\n setIsSubscribed(false);\n }\n }, [socket]);\n\n // ── IntersectionObserver lifecycle ──\n const containerRef = useCallback(\n (element: HTMLElement | null) => {\n // Teardown old observer\n if (observerRef.current) {\n observerRef.current.disconnect();\n observerRef.current = null;\n }\n\n elementRef.current = element;\n if (!element) return;\n\n observerRef.current = new IntersectionObserver(\n (entries) => {\n const entry = entries[0];\n if (!entry) return;\n\n const convId = preview?.conversationId;\n if (!convId) return;\n\n if (entry.isIntersecting) {\n subscribe(convId);\n } else {\n unsubscribe();\n }\n },\n { threshold: 0.1 }\n );\n\n observerRef.current.observe(element);\n },\n [preview, subscribe, unsubscribe]\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (observerRef.current) observerRef.current.disconnect();\n unsubscribe();\n };\n }, [unsubscribe]);\n\n // Re-attach observer when preview becomes available after element is mounted\n useEffect(() => {\n if (preview?.conversationId && elementRef.current && !observerRef.current) {\n containerRef(elementRef.current);\n }\n }, [preview, containerRef]);\n\n // ── Internal: send a message payload, lazy-creating the conversation on the first send ──\n const dispatchSend = useCallback(\n async (payload: SendMessagePayload) => {\n if (!preview) {\n // First message — create conversation + send atomically\n try {\n const result = await createConversationWithMessage(orderId, payload, {\n name: buildName(),\n participantIds,\n });\n\n const newPreview: ConversationPreview = {\n conversationId: result.conversation.id,\n orderId,\n messageCount: 1,\n unreadCount: 0,\n lastMessages: [result.message],\n participants: result.conversation.participants,\n name: result.conversation.name,\n };\n\n setPreview(newPreview);\n setMessages([result.message]);\n setParticipants(result.conversation.participants);\n invalidatePreview(orderId);\n\n if (elementRef.current) {\n subscribe(result.conversation.id);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to send message');\n config.onError?.({\n code: 'SEND_ERROR',\n message: 'Failed to send first message',\n details: err,\n });\n }\n return;\n }\n\n try {\n await socket.sendMessage(preview.conversationId, payload);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to send message');\n config.onError?.({\n code: 'SEND_ERROR',\n message: 'Failed to send message',\n details: err,\n });\n }\n },\n [\n preview,\n orderId,\n buildName,\n participantIds,\n createConversationWithMessage,\n invalidatePreview,\n subscribe,\n socket,\n config,\n ]\n );\n\n const sendMessage = useCallback(\n async (body: string) => {\n const trimmed = body.trim();\n if (!trimmed) return;\n await dispatchSend({ body: trimmed, type: 'text' });\n },\n [dispatchSend]\n );\n\n const sendAudioMessage = useCallback(\n async (audioBlob: Blob, duration: number) => {\n if (!config.onUploadFile) {\n setError('File upload is not configured');\n return;\n }\n try {\n const url = await config.onUploadFile(audioBlob, 'voice-message.webm');\n await dispatchSend({\n body: 'Voice message',\n type: 'audio',\n mediaUrl: url,\n mediaDuration: duration,\n });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to send voice message');\n config.onError?.({\n code: 'SEND_ERROR',\n message: 'Failed to send voice message',\n details: err,\n });\n }\n },\n [config, dispatchSend]\n );\n\n return {\n hasConversation: !!preview,\n messages,\n participants,\n unreadCount,\n isLoading,\n isSubscribed,\n error,\n sendMessage,\n sendAudioMessage,\n containerRef,\n };\n}\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { useInlineCollab } from '../hooks/useInlineCollab';\n// MIC DISABLED — voice messaging temporarily removed. Imports kept for easy re-enable.\n// import { useAudioRecorder } from '../hooks/useAudioRecorder';\n// import { MicIcon } from './icons/MicIcon';\nimport type { Message, PatientData, UserRole } from '../core/types';\n\ninterface CollabInlineProps {\n orderId: string;\n patientData: PatientData;\n /** User IDs to invite when the first message creates the conversation */\n participantIds?: string[];\n /** Called when user clicks the expand button — host opens the floating popup */\n onExpand?: () => void;\n /** Max inline messages to show (default 5) */\n messageLimit?: number;\n /** Placeholder text for the input */\n placeholder?: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Inline chat for table rows.\n *\n * Two states:\n * - No conversation yet: just an input bar (no socket, no preview)\n * - Conversation exists: last N messages + input + expand button\n *\n * Supports text and voice messages. File attachments and full chat features\n * stay in the floating popup / inbox.\n */\nexport function CollabInline({\n orderId,\n patientData,\n participantIds,\n onExpand,\n messageLimit = 5,\n placeholder = 'Type a message about this case...',\n className,\n style,\n}: CollabInlineProps) {\n const {\n hasConversation,\n messages,\n unreadCount,\n isLoading,\n isSubscribed,\n error,\n sendMessage,\n sendAudioMessage,\n containerRef,\n } = useInlineCollab({ orderId, patientData, participantIds, messageLimit });\n\n if (isLoading && !hasConversation) {\n return (\n <div className={className} style={{ ...styles.container, ...style }}>\n <div style={styles.loadingState}>Loading...</div>\n </div>\n );\n }\n\n return (\n <div ref={containerRef} className={className} style={{ ...styles.container, ...style }}>\n {hasConversation && messages.length > 0 && (\n <div style={styles.preview}>\n {messages.slice(-messageLimit).map((message) => (\n <InlineMessageRow key={message.id} message={message} />\n ))}\n </div>\n )}\n\n {error && <div style={styles.error}>{error}</div>}\n\n <InlineInputBar\n onSend={sendMessage}\n onSendAudio={sendAudioMessage}\n placeholder={placeholder}\n unreadCount={hasConversation ? unreadCount : 0}\n isLive={isSubscribed}\n showExpand={hasConversation && !!onExpand}\n onExpand={onExpand}\n />\n </div>\n );\n}\n\n// ─────────────────────────────────────────\n// Sub-components\n// ─────────────────────────────────────────\n\nfunction InlineMessageRow({ message }: { message: Message }) {\n if (message.type === 'system') {\n return (\n <div style={styles.systemRow}>\n <span style={styles.systemText}>{message.body}</span>\n </div>\n );\n }\n\n // Audio gets a compact play/pause + duration player inline\n if (message.type === 'audio' && message.mediaUrl) {\n return (\n <div style={styles.messageRow}>\n <RoleDot role={message.senderRole} />\n <span style={styles.senderName}>{message.senderName}:</span>\n <InlineAudioPlayer url={message.mediaUrl} duration={message.mediaDuration} />\n </div>\n );\n }\n\n const preview = renderMessagePreview(message);\n\n return (\n <div style={styles.messageRow}>\n <RoleDot role={message.senderRole} />\n <span style={styles.senderName}>{message.senderName}:</span>\n <span style={styles.messageText}>{preview}</span>\n </div>\n );\n}\n\nfunction RoleDot({ role }: { role: UserRole }) {\n const colors: Record<UserRole, string> = {\n radiologist: '#7c3aed',\n lab: '#2563eb',\n physician: '#059669',\n admin: '#dc2626',\n };\n\n return <span style={{ ...styles.roleDot, backgroundColor: colors[role] }} />;\n}\n\n/**\n * Compact audio player designed to fit in a single inline row.\n * Shows just a play/pause toggle + duration. No scrubber.\n */\nfunction InlineAudioPlayer({ url, duration }: { url: string; duration?: number }) {\n const audioRef = useRef<HTMLAudioElement>(null);\n const [isPlaying, setIsPlaying] = useState(false);\n const [currentTime, setCurrentTime] = useState(0);\n\n const toggle = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n const audio = audioRef.current;\n if (!audio) return;\n if (isPlaying) {\n audio.pause();\n } else {\n audio.play().catch(() => {\n // Silent fail — autoplay blocked, etc.\n });\n }\n },\n [isPlaying]\n );\n\n useEffect(() => {\n const audio = audioRef.current;\n if (!audio) return;\n\n const onPlay = () => setIsPlaying(true);\n const onPause = () => setIsPlaying(false);\n const onEnded = () => {\n setIsPlaying(false);\n setCurrentTime(0);\n };\n const onTimeUpdate = () => setCurrentTime(audio.currentTime);\n\n audio.addEventListener('play', onPlay);\n audio.addEventListener('pause', onPause);\n audio.addEventListener('ended', onEnded);\n audio.addEventListener('timeupdate', onTimeUpdate);\n\n return () => {\n audio.removeEventListener('play', onPlay);\n audio.removeEventListener('pause', onPause);\n audio.removeEventListener('ended', onEnded);\n audio.removeEventListener('timeupdate', onTimeUpdate);\n };\n }, []);\n\n const total = duration ?? 0;\n const remaining = Math.max(0, total - Math.floor(currentTime));\n const displayTime = isPlaying ? remaining : total;\n\n return (\n <span style={styles.audioPlayer}>\n <button\n onClick={toggle}\n style={styles.audioButton}\n title={isPlaying ? 'Pause' : 'Play'}\n type=\"button\"\n >\n {isPlaying ? '⏸' : '▶'}\n </button>\n <span style={styles.audioWaveform}>\n {/* Purely decorative bars */}\n <span style={{ ...styles.waveBar, height: '40%' }} />\n <span style={{ ...styles.waveBar, height: '80%' }} />\n <span style={{ ...styles.waveBar, height: '60%' }} />\n <span style={{ ...styles.waveBar, height: '90%' }} />\n <span style={{ ...styles.waveBar, height: '50%' }} />\n <span style={{ ...styles.waveBar, height: '70%' }} />\n <span style={{ ...styles.waveBar, height: '40%' }} />\n </span>\n <span style={styles.audioDuration}>{formatDuration(displayTime)}</span>\n <audio ref={audioRef} src={url} preload=\"metadata\" />\n </span>\n );\n}\n\nfunction renderMessagePreview(message: Message): string {\n switch (message.type) {\n case 'image':\n return `📷 ${message.fileName || 'Image'}`;\n case 'file':\n return `📎 ${message.fileName || 'File'}`;\n case 'deep_link':\n return `🔗 ${message.body}`;\n default:\n return message.body;\n }\n}\n\nfunction formatDuration(seconds: number): string {\n const safe = Math.max(0, Math.floor(seconds));\n const m = Math.floor(safe / 60);\n const s = safe % 60;\n return `${m}:${s.toString().padStart(2, '0')}`;\n}\n\ninterface InlineInputBarProps {\n onSend: (body: string) => Promise<void>;\n /** @deprecated MIC DISABLED — kept in prop signature for backward compat. */\n onSendAudio?: (blob: Blob, duration: number) => Promise<void>;\n placeholder: string;\n unreadCount: number;\n isLive: boolean;\n showExpand: boolean;\n onExpand?: () => void;\n}\n\nfunction InlineInputBar({\n onSend,\n // MIC DISABLED — onSendAudio accepted but unused.\n // onSendAudio,\n placeholder,\n unreadCount,\n isLive,\n showExpand,\n onExpand,\n}: InlineInputBarProps) {\n const [text, setText] = useState('');\n const [isSending, setIsSending] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n\n // MIC DISABLED — voice recorder hook + handlers not invoked. Restore by\n // uncommenting the destructure and handleStopRecording below (and the\n // imports at the top of the file).\n // const {\n // isRecording,\n // duration,\n // start: startRecording,\n // stop: stopRecording,\n // cancel: cancelRecording,\n // isSupported: micSupported,\n // error: micError,\n // } = useAudioRecorder();\n\n const handleSend = useCallback(async () => {\n const trimmed = text.trim();\n if (!trimmed || isSending) return;\n\n setIsSending(true);\n try {\n await onSend(trimmed);\n setText('');\n inputRef.current?.focus();\n } finally {\n setIsSending(false);\n }\n }, [text, isSending, onSend]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n },\n [handleSend]\n );\n\n // MIC DISABLED — audio stop handler unused. Restore alongside useAudioRecorder.\n // const handleStopRecording = useCallback(async () => {\n // const result = await stopRecording();\n // if (result) {\n // setIsSending(true);\n // try {\n // await onSendAudio(result.blob, result.duration);\n // } finally {\n // setIsSending(false);\n // }\n // }\n // }, [stopRecording, onSendAudio]);\n\n /* MIC DISABLED — recording mode branch removed. Original block kept here\n for easy re-enable when mic is restored:\n\n if (isRecording) {\n return (\n <div style={styles.recordingBar}>\n <span style={styles.recordingDot} />\n <span style={styles.recordingLabel}>Recording {formatDuration(duration)}</span>\n <button onClick={cancelRecording} style={styles.recordingCancel} title=\"Cancel recording\" type=\"button\">Cancel</button>\n <button onClick={handleStopRecording} style={styles.recordingSend} title=\"Send voice message\" type=\"button\">Send</button>\n </div>\n );\n }\n */\n\n return (\n <div style={styles.inputBar}>\n <input\n ref={inputRef}\n type=\"text\"\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={isSending}\n style={styles.input}\n />\n\n {unreadCount > 0 && (\n <span style={styles.unreadBadge} title={`${unreadCount} unread`}>\n {unreadCount > 99 ? '99+' : unreadCount}\n </span>\n )}\n\n {isLive && <span style={styles.liveDot} title=\"Live updates active\" />}\n\n {/* MIC DISABLED — mic button hidden. Original block:\n {micSupported && !text.trim() && (\n <button onClick={startRecording} disabled={isSending} style={styles.micButton} title=\"Record voice message\" type=\"button\">\n <MicIcon size={16} color=\"#374151\" />\n </button>\n )}\n */}\n\n {/* Send button — shown when there's text to send */}\n {text.trim() && (\n <button\n onClick={handleSend}\n disabled={isSending}\n style={styles.sendButton}\n title=\"Send message\"\n type=\"button\"\n >\n ➤\n </button>\n )}\n\n {showExpand && onExpand && (\n <button\n onClick={onExpand}\n style={styles.expandButton}\n title=\"Expand to full chat\"\n type=\"button\"\n >\n ⛶\n </button>\n )}\n </div>\n );\n}\n\n// ─────────────────────────────────────────\n// Styles\n// ─────────────────────────────────────────\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n flexDirection: 'column',\n width: '100%',\n padding: '6px 8px',\n backgroundColor: '#ffffff',\n border: '1px solid #e5e7eb',\n borderRadius: '8px',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n },\n loadingState: {\n padding: '8px',\n fontSize: '12px',\n color: '#9ca3af',\n textAlign: 'center',\n },\n error: {\n padding: '4px 8px',\n marginBottom: '4px',\n fontSize: '11px',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n borderRadius: '4px',\n },\n preview: {\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n marginBottom: '6px',\n paddingBottom: '6px',\n borderBottom: '1px solid #f3f4f6',\n },\n messageRow: {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n fontSize: '12px',\n lineHeight: '1.4',\n overflow: 'hidden',\n },\n roleDot: {\n flexShrink: 0,\n width: '6px',\n height: '6px',\n borderRadius: '50%',\n },\n senderName: {\n flexShrink: 0,\n fontWeight: 600,\n color: '#374151',\n },\n messageText: {\n color: '#4b5563',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n minWidth: 0,\n flex: 1,\n },\n systemRow: {\n fontSize: '11px',\n color: '#9ca3af',\n fontStyle: 'italic',\n textAlign: 'center',\n padding: '2px 0',\n },\n systemText: {\n opacity: 0.8,\n },\n // ── Audio player (inline) ──\n audioPlayer: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px',\n padding: '2px 8px',\n borderRadius: '12px',\n backgroundColor: '#eff6ff',\n border: '1px solid #dbeafe',\n flex: 1,\n minWidth: 0,\n },\n audioButton: {\n width: '20px',\n height: '20px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '10px',\n color: '#ffffff',\n backgroundColor: '#2563eb',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n flexShrink: 0,\n },\n audioWaveform: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '2px',\n height: '16px',\n flex: 1,\n minWidth: 0,\n },\n waveBar: {\n display: 'inline-block',\n width: '2px',\n borderRadius: '1px',\n backgroundColor: '#60a5fa',\n },\n audioDuration: {\n fontSize: '11px',\n color: '#2563eb',\n fontVariantNumeric: 'tabular-nums',\n fontWeight: 500,\n flexShrink: 0,\n },\n // ── Input bar ──\n inputBar: {\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n },\n input: {\n flex: 1,\n padding: '6px 10px',\n fontSize: '13px',\n border: '1px solid #e5e7eb',\n borderRadius: '16px',\n outline: 'none',\n fontFamily: 'inherit',\n minWidth: 0,\n },\n unreadBadge: {\n flexShrink: 0,\n minWidth: '18px',\n height: '18px',\n padding: '0 5px',\n fontSize: '10px',\n fontWeight: 600,\n color: '#ffffff',\n backgroundColor: '#dc2626',\n borderRadius: '10px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n liveDot: {\n flexShrink: 0,\n width: '6px',\n height: '6px',\n borderRadius: '50%',\n backgroundColor: '#22c55e',\n },\n micButton: {\n flexShrink: 0,\n width: '28px',\n height: '28px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '13px',\n backgroundColor: '#f3f4f6',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n },\n sendButton: {\n flexShrink: 0,\n width: '28px',\n height: '28px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '13px',\n color: '#ffffff',\n backgroundColor: '#2563eb',\n border: 'none',\n borderRadius: '50%',\n cursor: 'pointer',\n },\n expandButton: {\n flexShrink: 0,\n width: '28px',\n height: '28px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '12px',\n color: '#6b7280',\n backgroundColor: 'transparent',\n border: '1px solid #e5e7eb',\n borderRadius: '50%',\n cursor: 'pointer',\n },\n // ── Recording mode ──\n recordingBar: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '6px 10px',\n backgroundColor: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: '16px',\n },\n recordingDot: {\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: '#dc2626',\n flexShrink: 0,\n animation: 'pulse 1.5s infinite',\n },\n recordingLabel: {\n flex: 1,\n fontSize: '12px',\n fontWeight: 500,\n color: '#dc2626',\n fontVariantNumeric: 'tabular-nums',\n },\n recordingCancel: {\n padding: '4px 10px',\n fontSize: '11px',\n color: '#6b7280',\n backgroundColor: '#ffffff',\n border: '1px solid #d1d5db',\n borderRadius: '12px',\n cursor: 'pointer',\n flexShrink: 0,\n },\n recordingSend: {\n padding: '4px 10px',\n fontSize: '11px',\n fontWeight: 500,\n color: '#ffffff',\n backgroundColor: '#dc2626',\n border: 'none',\n borderRadius: '12px',\n cursor: 'pointer',\n flexShrink: 0,\n },\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type { ConversationListItem } from '../core/types';\n\ninterface UseConversationListOptions {\n /**\n * When false, skips the initial auto-fetch. The caller can still invoke\n * `refresh()` manually (e.g. on user interaction). Defaults to true.\n */\n enabled?: boolean;\n}\n\ninterface UseConversationListReturn {\n conversations: ConversationListItem[];\n isLoading: boolean;\n error: string | null;\n refresh: () => Promise<void>;\n /** Filter conversations by query string (matches channel name + patient name) */\n filter: (query: string) => ConversationListItem[];\n /** Total unread across all conversations */\n totalUnread: number;\n}\n\n/**\n * Fetches the current user's full conversation list for the inbox.\n * Conversations are returned sorted by last activity (backend-sorted).\n *\n * Pass `{ enabled: false }` for lazy mode — useful when the list is behind\n * a click (e.g. a collapsed FAB panel) and you don't want to hit the API\n * until the user opens it.\n */\nexport function useConversationList(\n options?: UseConversationListOptions\n): UseConversationListReturn {\n const enabled = options?.enabled ?? true;\n const { fetchConversationList, config, totalUnread: serverTotalUnread } =\n useCollab();\n const [conversations, setConversations] = useState<ConversationListItem[]>([]);\n const [isLoading, setIsLoading] = useState(enabled);\n const [error, setError] = useState<string | null>(null);\n\n // Silent refresh (no spinner flash) — used for socket-driven resyncs so a\n // background update doesn't blink the list.\n const silentRefresh = useCallback(async () => {\n try {\n const list = await fetchConversationList();\n setConversations(list);\n } catch (err) {\n config.onError?.({\n code: 'LIST_ERROR',\n message: err instanceof Error ? err.message : 'Failed to load conversations',\n details: err,\n });\n }\n }, [fetchConversationList, config]);\n\n const refresh = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n try {\n const list = await fetchConversationList();\n setConversations(list);\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to load conversations';\n setError(msg);\n config.onError?.({\n code: 'LIST_ERROR',\n message: msg,\n details: err,\n });\n } finally {\n setIsLoading(false);\n }\n }, [fetchConversationList, config]);\n\n useEffect(() => {\n if (!enabled) return;\n refresh();\n }, [enabled, refresh]);\n\n // Live resync: the server pushes an `unread_update` event on the user\n // notifications channel any time a message arrives, gets read, etc.\n // CollabProvider surfaces that as `serverTotalUnread`. When it changes\n // and the list is currently showing, pull fresh data silently so the\n // last-message / activity order / unread badges all stay in sync without\n // the user having to close and reopen the panel.\n //\n // Skip the first run — the main effect above already handled mount,\n // firing a silent refetch here on top would double-fetch.\n const hasHandledInitialUnreadRef = useRef(false);\n useEffect(() => {\n if (!enabled) return;\n if (!hasHandledInitialUnreadRef.current) {\n hasHandledInitialUnreadRef.current = true;\n return;\n }\n silentRefresh();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [serverTotalUnread, enabled]);\n\n const filter = useCallback(\n (query: string): ConversationListItem[] => {\n const q = query.trim().toLowerCase();\n if (!q) return conversations;\n return conversations.filter((c) => {\n const patient = c.patientSnapshot?.patientName?.toLowerCase() || '';\n const name = c.name.toLowerCase();\n return name.includes(q) || patient.includes(q);\n });\n },\n [conversations]\n );\n\n const totalUnread = conversations.reduce((sum, c) => sum + c.unreadCount, 0);\n\n return {\n conversations,\n isLoading,\n error,\n refresh,\n filter,\n totalUnread,\n };\n}\n","import React from 'react';\nimport type { ConversationListItem as ListItem, Message } from '../core/types';\nimport { formatInboxTimestamp } from '../core/dateLabels';\n\ninterface ConversationListItemProps {\n item: ListItem;\n isSelected: boolean;\n onClick: () => void;\n className?: string;\n}\n\n/**\n * Single row in the inbox sidebar — shows patient/channel name, last message\n * preview, timestamp, and unread badge.\n */\nexport function ConversationListItem({\n item,\n isSelected,\n onClick,\n className,\n}: ConversationListItemProps) {\n const hasUnread = item.unreadCount > 0;\n // Prefer the channel name (patient - lab - last4) so labels are consistent\n // everywhere a channel is shown.\n const displayName = item.name || item.patientSnapshot?.patientName || 'Unknown';\n\n return (\n <button\n className={className}\n onClick={onClick}\n style={{\n ...styles.container,\n ...(isSelected ? styles.selected : {}),\n ...(hasUnread ? styles.unread : {}),\n }}\n type=\"button\"\n >\n {/* Avatar / unread dot */}\n <div style={styles.avatarWrapper}>\n {item.picture ? (\n <img src={item.picture} alt=\"\" style={styles.avatar} />\n ) : (\n <div style={styles.avatarFallback}>{(displayName || '?').charAt(0).toUpperCase()}</div>\n )}\n {hasUnread && <span style={styles.unreadDot} />}\n </div>\n\n {/* Main content */}\n <div style={styles.content}>\n <div style={styles.topRow}>\n <span\n style={{\n ...styles.name,\n ...(hasUnread ? styles.nameUnread : {}),\n }}\n >\n {displayName}\n </span>\n <span\n style={{\n ...styles.time,\n ...(hasUnread ? styles.timeUnread : {}),\n }}\n >\n {formatInboxTimestamp(item.lastActivityAt)}\n </span>\n </div>\n\n <div style={styles.bottomRow}>\n <span\n style={{\n ...styles.preview,\n ...(hasUnread ? styles.previewUnread : {}),\n }}\n >\n {renderLastMessagePreview(item.lastMessage)}\n </span>\n {hasUnread && (\n <span style={styles.badge}>\n {item.unreadCount > 99 ? '99+' : item.unreadCount}\n </span>\n )}\n </div>\n </div>\n </button>\n );\n}\n\nfunction renderLastMessagePreview(message?: Message): string {\n if (!message) return 'No messages yet';\n\n const prefix = message.senderName ? `${message.senderName}: ` : '';\n\n switch (message.type) {\n case 'audio':\n return `${prefix}🎤 Voice message`;\n case 'image':\n return `${prefix}📷 ${message.fileName || 'Image'}`;\n case 'file':\n return `${prefix}📎 ${message.fileName || 'File'}`;\n case 'deep_link':\n return `${prefix}🔗 ${message.body}`;\n case 'system':\n return message.body;\n default: {\n const body = message.body || '';\n const preview = body.length > 60 ? `${body.slice(0, 60)}…` : body;\n return `${prefix}${preview}`;\n }\n }\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '10px 12px',\n width: '100%',\n backgroundColor: 'transparent',\n border: 'none',\n borderBottom: '1px solid #f3f4f6',\n cursor: 'pointer',\n textAlign: 'left',\n },\n selected: {\n backgroundColor: '#eff6ff',\n },\n unread: {},\n avatarWrapper: {\n position: 'relative',\n width: '40px',\n height: '40px',\n flexShrink: 0,\n },\n avatar: {\n width: '40px',\n height: '40px',\n borderRadius: '50%',\n objectFit: 'cover',\n },\n avatarFallback: {\n width: '40px',\n height: '40px',\n borderRadius: '50%',\n backgroundColor: '#e5e7eb',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '15px',\n fontWeight: 600,\n color: '#6b7280',\n },\n unreadDot: {\n position: 'absolute',\n top: '0',\n left: '0',\n width: '10px',\n height: '10px',\n borderRadius: '50%',\n backgroundColor: '#2563eb',\n border: '2px solid #ffffff',\n },\n content: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n gap: '2px',\n minWidth: 0,\n },\n topRow: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'baseline',\n gap: '8px',\n },\n name: {\n fontSize: '15px',\n fontWeight: 500,\n color: '#111827',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n flex: 1,\n minWidth: 0,\n },\n nameUnread: {\n fontWeight: 700,\n },\n studyType: {\n fontSize: '12px',\n fontWeight: 400,\n color: '#6b7280',\n },\n time: {\n fontSize: '12px',\n color: '#6b7280',\n flexShrink: 0,\n },\n timeUnread: {\n color: '#2563eb',\n fontWeight: 600,\n },\n bottomRow: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n gap: '8px',\n },\n preview: {\n fontSize: '14px',\n color: '#4b5563',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n flex: 1,\n minWidth: 0,\n },\n previewUnread: {\n color: '#111827',\n fontWeight: 500,\n },\n badge: {\n minWidth: '20px',\n height: '20px',\n padding: '0 6px',\n fontSize: '11px',\n fontWeight: 600,\n color: '#ffffff',\n backgroundColor: '#2563eb',\n borderRadius: '10px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n },\n};\n","import React, { useMemo, useState } from 'react';\nimport { ConversationListItem } from './ConversationListItem';\nimport type { ConversationListItem as ListItem } from '../core/types';\n\ninterface ConversationListProps {\n conversations: ListItem[];\n selectedId: string | null;\n isLoading: boolean;\n error: string | null;\n onSelect: (item: ListItem) => void;\n /** Optional title shown above the list */\n title?: string;\n className?: string;\n}\n\n/**\n * Scrollable sidebar list of conversations with search and unread filter.\n */\nexport function ConversationList({\n conversations,\n selectedId,\n isLoading,\n error,\n onSelect,\n title = 'Conversations',\n className,\n}: ConversationListProps) {\n const [query, setQuery] = useState('');\n const [showUnreadOnly, setShowUnreadOnly] = useState(false);\n\n const filtered = useMemo(() => {\n let result = conversations;\n\n if (showUnreadOnly) {\n result = result.filter((c) => c.unreadCount > 0);\n }\n\n const q = query.trim().toLowerCase();\n if (q) {\n result = result.filter((c) => {\n const patient = c.patientSnapshot?.patientName?.toLowerCase() || '';\n const name = c.name.toLowerCase();\n return name.includes(q) || patient.includes(q);\n });\n }\n\n return result;\n }, [conversations, query, showUnreadOnly]);\n\n const totalUnread = conversations.reduce((sum, c) => sum + c.unreadCount, 0);\n\n return (\n <div className={className} style={styles.container}>\n <div style={styles.header}>\n <div style={styles.titleRow}>\n <h3 style={styles.title}>{title}</h3>\n {totalUnread > 0 && <span style={styles.totalBadge}>{totalUnread}</span>}\n </div>\n\n <div style={styles.searchRow}>\n <input\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search patients or channels...\"\n style={styles.searchInput}\n />\n </div>\n\n <div style={styles.filterRow}>\n <button\n onClick={() => setShowUnreadOnly(false)}\n style={{\n ...styles.filterButton,\n ...(!showUnreadOnly ? styles.filterButtonActive : {}),\n }}\n type=\"button\"\n >\n All\n </button>\n <button\n onClick={() => setShowUnreadOnly(true)}\n style={{\n ...styles.filterButton,\n ...(showUnreadOnly ? styles.filterButtonActive : {}),\n }}\n type=\"button\"\n >\n Unread {totalUnread > 0 && `(${totalUnread})`}\n </button>\n </div>\n </div>\n\n <div style={styles.list}>\n {isLoading && <div style={styles.state}>Loading conversations...</div>}\n {error && <div style={styles.errorState}>{error}</div>}\n\n {!isLoading && !error && filtered.length === 0 && (\n <div style={styles.state}>\n {query ? 'No matching conversations' : 'No conversations yet'}\n </div>\n )}\n\n {filtered.map((item) => (\n <ConversationListItem\n key={item.id}\n item={item}\n isSelected={selectedId === item.id}\n onClick={() => onSelect(item)}\n />\n ))}\n </div>\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n backgroundColor: '#ffffff',\n borderRight: '1px solid #e5e7eb',\n },\n header: {\n padding: '12px',\n borderBottom: '1px solid #e5e7eb',\n backgroundColor: '#f9fafb',\n flexShrink: 0,\n },\n titleRow: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginBottom: '8px',\n },\n title: {\n margin: 0,\n fontSize: '15px',\n fontWeight: 600,\n color: '#111827',\n },\n totalBadge: {\n minWidth: '20px',\n height: '20px',\n padding: '0 6px',\n fontSize: '11px',\n fontWeight: 600,\n color: '#ffffff',\n backgroundColor: '#2563eb',\n borderRadius: '10px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n searchRow: {\n marginBottom: '8px',\n },\n searchInput: {\n width: '100%',\n padding: '6px 10px',\n fontSize: '13px',\n border: '1px solid #e5e7eb',\n borderRadius: '6px',\n outline: 'none',\n fontFamily: 'inherit',\n },\n filterRow: {\n display: 'flex',\n gap: '4px',\n },\n filterButton: {\n flex: 1,\n padding: '5px 8px',\n fontSize: '12px',\n color: '#6b7280',\n backgroundColor: '#ffffff',\n border: '1px solid #e5e7eb',\n borderRadius: '6px',\n cursor: 'pointer',\n },\n filterButtonActive: {\n color: '#ffffff',\n backgroundColor: '#2563eb',\n borderColor: '#2563eb',\n fontWeight: 500,\n },\n list: {\n flex: 1,\n overflowY: 'auto',\n },\n state: {\n padding: '24px 16px',\n fontSize: '13px',\n color: '#9ca3af',\n textAlign: 'center',\n },\n errorState: {\n padding: '16px',\n fontSize: '13px',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n margin: '12px',\n borderRadius: '6px',\n textAlign: 'center',\n },\n};\n","import React, { useState } from 'react';\nimport { useConversationList } from '../hooks/useConversationList';\nimport { ConversationList } from './ConversationList';\nimport { CollabPanel } from './CollabPanel';\nimport type { ConversationListItem, PatientData } from '../core/types';\n\ninterface CollabInboxProps {\n /** Optional: preselect a specific conversation (by conversation ID) */\n initialConversationId?: string;\n /** Optional callback when the user selects a conversation */\n onSelectConversation?: (item: ConversationListItem) => void;\n /** Title for the sidebar */\n title?: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/**\n * Full-page inbox — WhatsApp-style sidebar of all user's conversations\n * with the selected conversation's CollabPanel on the right.\n *\n * Uses the same CollabPanel as the floating popup, so all features\n * (reply, pin, seen-by, DICOM, voice, attachments) are available.\n */\nexport function CollabInbox({\n initialConversationId,\n onSelectConversation,\n title,\n className,\n style,\n}: CollabInboxProps) {\n const { conversations, isLoading, error } = useConversationList();\n const [selectedId, setSelectedId] = useState<string | null>(initialConversationId ?? null);\n\n const selected = conversations.find((c) => c.id === selectedId) || null;\n\n const handleSelect = (item: ConversationListItem) => {\n setSelectedId(item.id);\n onSelectConversation?.(item);\n };\n\n return (\n <div className={className} style={{ ...styles.container, ...style }}>\n <div style={styles.sidebar}>\n <ConversationList\n conversations={conversations}\n selectedId={selectedId}\n isLoading={isLoading}\n error={error}\n onSelect={handleSelect}\n title={title}\n />\n </div>\n\n <div style={styles.main}>\n {selected ? (\n <CollabPanel\n key={selected.id}\n orderId={selected.orderId}\n patientData={buildPatientData(selected)}\n showSeenBy={true}\n style={styles.panel}\n />\n ) : (\n <EmptyState hasAny={conversations.length > 0} />\n )}\n </div>\n </div>\n );\n}\n\nfunction buildPatientData(item: ConversationListItem): PatientData {\n if (item.patientSnapshot) return item.patientSnapshot;\n\n // Fallback — build minimal PatientData from available fields\n return {\n patientName: item.name,\n orderId: item.orderId,\n };\n}\n\nfunction EmptyState({ hasAny }: { hasAny: boolean }) {\n return (\n <div style={styles.empty}>\n <div style={styles.emptyIcon}>💬</div>\n <h3 style={styles.emptyTitle}>\n {hasAny ? 'Select a conversation' : 'No conversations yet'}\n </h3>\n <p style={styles.emptySubtitle}>\n {hasAny\n ? 'Pick a patient from the list to start collaborating'\n : 'Conversations appear here once you start messaging about a case'}\n </p>\n </div>\n );\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n container: {\n display: 'flex',\n height: '100%',\n width: '100%',\n backgroundColor: '#ffffff',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n },\n sidebar: {\n width: '320px',\n minWidth: '280px',\n flexShrink: 0,\n display: 'flex',\n flexDirection: 'column',\n },\n main: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n minWidth: 0,\n padding: '12px',\n backgroundColor: '#f3f4f6',\n },\n panel: {\n height: '100%',\n width: '100%',\n },\n empty: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '48px 24px',\n textAlign: 'center',\n },\n emptyIcon: {\n fontSize: '48px',\n marginBottom: '12px',\n },\n emptyTitle: {\n margin: '0 0 6px',\n fontSize: '16px',\n fontWeight: 600,\n color: '#374151',\n },\n emptySubtitle: {\n margin: 0,\n fontSize: '13px',\n color: '#6b7280',\n maxWidth: '320px',\n },\n};\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type { Message } from '../core/types';\nimport { MESSAGES_PAGE_SIZE } from '../core/constants';\n\ninterface UseMessagesOptions {\n conversationId: string | null;\n /** Initial page size (default 30) */\n initialLimit?: number;\n}\n\ninterface UseMessagesReturn {\n messages: Message[];\n isLoading: boolean;\n hasMore: boolean;\n error: string | null;\n loadMore: () => Promise<void>;\n addMessage: (message: Message) => void;\n updateMessageReadBy: (messageId: string, userId: string) => void;\n reset: () => void;\n}\n\n/**\n * Standalone hook for message history management.\n * Use this if you need message data outside of useConversation\n * (e.g. building a completely custom UI).\n */\nexport function useMessages({\n conversationId,\n initialLimit = MESSAGES_PAGE_SIZE,\n}: UseMessagesOptions): UseMessagesReturn {\n const { fetchMessages, config } = useCollab();\n const [messages, setMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const loadedRef = useRef<string | null>(null);\n\n // Load initial messages when conversation changes\n useEffect(() => {\n if (!conversationId) {\n setMessages([]);\n setHasMore(false);\n loadedRef.current = null;\n return;\n }\n\n if (loadedRef.current === conversationId) return;\n\n let cancelled = false;\n\n const loadInitial = async () => {\n setIsLoading(true);\n setError(null);\n try {\n const initial = await fetchMessages(conversationId, { limit: initialLimit });\n if (cancelled) return;\n setMessages(initial);\n setHasMore(initial.length >= initialLimit);\n loadedRef.current = conversationId;\n } catch (err) {\n if (cancelled) return;\n const msg = err instanceof Error ? err.message : 'Failed to load messages';\n setError(msg);\n config.onError?.({\n code: 'LOAD_ERROR',\n message: 'Failed to load messages',\n details: err,\n });\n } finally {\n if (!cancelled) setIsLoading(false);\n }\n };\n\n loadInitial();\n\n return () => {\n cancelled = true;\n };\n }, [conversationId, initialLimit, fetchMessages, config]);\n\n const loadMore = useCallback(async () => {\n if (!conversationId || !hasMore || isLoading) return;\n\n const oldestId = messages[0]?.id;\n setIsLoading(true);\n try {\n const older = await fetchMessages(conversationId, {\n limit: initialLimit,\n before: oldestId,\n });\n setMessages((prev) => [...older, ...prev]);\n setHasMore(older.length >= initialLimit);\n } catch (err) {\n config.onError?.({\n code: 'LOAD_ERROR',\n message: 'Failed to load older messages',\n details: err,\n });\n } finally {\n setIsLoading(false);\n }\n }, [conversationId, hasMore, isLoading, messages, initialLimit, fetchMessages, config]);\n\n const addMessage = useCallback((message: Message) => {\n setMessages((prev) => [...prev, message]);\n }, []);\n\n const updateMessageReadBy = useCallback((messageId: string, userId: string) => {\n setMessages((prev) =>\n prev.map((msg) =>\n msg.id === messageId && !(msg.readBy ?? []).includes(userId)\n ? { ...msg, readBy: [...(msg.readBy ?? []), userId] }\n : msg\n )\n );\n }, []);\n\n const reset = useCallback(() => {\n setMessages([]);\n setHasMore(true);\n setError(null);\n loadedRef.current = null;\n }, []);\n\n return {\n messages,\n isLoading,\n hasMore,\n error,\n loadMore,\n addMessage,\n updateMessageReadBy,\n reset,\n };\n}\n","import { useState, useRef, useCallback } from 'react';\nimport { AUDIO_MIME_TYPE } from '../core/constants';\n\ninterface UseAudioRecorderReturn {\n /** Whether the mic is currently recording */\n isRecording: boolean;\n /** Recording duration in seconds (updates every second while recording) */\n duration: number;\n /** Start recording from the microphone */\n start: () => Promise<void>;\n /** Stop recording and return the audio blob */\n stop: () => Promise<{ blob: Blob; duration: number } | null>;\n /** Cancel recording without producing output */\n cancel: () => void;\n /** Whether the browser supports audio recording */\n isSupported: boolean;\n /** Error message if recording fails */\n error: string | null;\n}\n\n/**\n * Wraps the browser MediaRecorder API for voice message recording.\n * Returns a blob suitable for uploading via config.onUploadFile.\n */\nexport function useAudioRecorder(): UseAudioRecorderReturn {\n const [isRecording, setIsRecording] = useState(false);\n const [duration, setDuration] = useState(0);\n const [error, setError] = useState<string | null>(null);\n\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const chunksRef = useRef<Blob[]>([]);\n const streamRef = useRef<MediaStream | null>(null);\n const timerRef = useRef<NodeJS.Timeout | null>(null);\n const startTimeRef = useRef<number>(0);\n const resolveRef = useRef<((value: { blob: Blob; duration: number } | null) => void) | null>(null);\n\n const isSupported =\n typeof window !== 'undefined' &&\n typeof navigator !== 'undefined' &&\n !!navigator.mediaDevices?.getUserMedia &&\n !!window.MediaRecorder;\n\n const cleanup = useCallback(() => {\n if (timerRef.current) {\n clearInterval(timerRef.current);\n timerRef.current = null;\n }\n\n if (streamRef.current) {\n streamRef.current.getTracks().forEach((track) => track.stop());\n streamRef.current = null;\n }\n\n mediaRecorderRef.current = null;\n chunksRef.current = [];\n setIsRecording(false);\n setDuration(0);\n }, []);\n\n const start = useCallback(async () => {\n if (!isSupported) {\n setError('Audio recording is not supported in this browser');\n return;\n }\n\n try {\n setError(null);\n chunksRef.current = [];\n\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n streamRef.current = stream;\n\n // Pick the best supported MIME type\n const mimeType = MediaRecorder.isTypeSupported(AUDIO_MIME_TYPE)\n ? AUDIO_MIME_TYPE\n : MediaRecorder.isTypeSupported('audio/webm')\n ? 'audio/webm'\n : 'audio/mp4';\n\n const recorder = new MediaRecorder(stream, { mimeType });\n mediaRecorderRef.current = recorder;\n\n recorder.ondataavailable = (event) => {\n if (event.data.size > 0) {\n chunksRef.current.push(event.data);\n }\n };\n\n recorder.onerror = () => {\n setError('Recording failed');\n cleanup();\n resolveRef.current?.(null);\n resolveRef.current = null;\n };\n\n recorder.onstop = () => {\n const finalDuration = Math.round((Date.now() - startTimeRef.current) / 1000);\n const blob = new Blob(chunksRef.current, { type: mimeType });\n\n cleanup();\n resolveRef.current?.({ blob, duration: finalDuration });\n resolveRef.current = null;\n };\n\n recorder.start(250); // collect data every 250ms\n startTimeRef.current = Date.now();\n setIsRecording(true);\n\n // Update duration counter every second\n timerRef.current = setInterval(() => {\n const elapsed = Math.round((Date.now() - startTimeRef.current) / 1000);\n setDuration(elapsed);\n }, 1000);\n } catch (err) {\n if (err instanceof DOMException && err.name === 'NotAllowedError') {\n setError('Microphone access denied. Please allow microphone permissions.');\n } else {\n setError('Failed to start recording');\n }\n cleanup();\n }\n }, [isSupported, cleanup]);\n\n const stop = useCallback(async (): Promise<{ blob: Blob; duration: number } | null> => {\n return new Promise((resolve) => {\n if (!mediaRecorderRef.current || mediaRecorderRef.current.state === 'inactive') {\n resolve(null);\n return;\n }\n\n resolveRef.current = resolve;\n mediaRecorderRef.current.stop();\n });\n }, []);\n\n const cancel = useCallback(() => {\n if (mediaRecorderRef.current && mediaRecorderRef.current.state !== 'inactive') {\n // Remove onstop handler to avoid producing output\n mediaRecorderRef.current.onstop = null;\n mediaRecorderRef.current.stop();\n }\n cleanup();\n resolveRef.current?.(null);\n resolveRef.current = null;\n }, [cleanup]);\n\n return {\n isRecording,\n duration,\n start,\n stop,\n cancel,\n isSupported,\n error,\n };\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { useCollab } from '../context/CollabProvider';\n\ninterface UseUnreadCountReturn {\n /** Total unread messages across all conversations */\n totalUnread: number;\n /** Get unread count for a specific conversation */\n getCountForConversation: (conversationId: string) => number;\n /** Manually clear unread count for a conversation (e.g. when user opens it) */\n clearForConversation: (conversationId: string) => void;\n}\n\n/**\n * Tracks unread message counts.\n * Counts are pushed from the server via the user channel (no polling).\n */\nexport function useUnreadCount(): UseUnreadCountReturn {\n const { socket, totalUnread } = useCollab();\n const [counts, setCounts] = useState<Record<string, number>>({});\n\n useEffect(() => {\n socket.onUnreadCountUpdate((serverCounts) => {\n setCounts(serverCounts);\n });\n }, [socket]);\n\n const getCountForConversation = useCallback(\n (conversationId: string): number => {\n return counts[conversationId] ?? 0;\n },\n [counts]\n );\n\n const clearForConversation = useCallback((conversationId: string) => {\n setCounts((prev) => {\n const next = { ...prev };\n delete next[conversationId];\n return next;\n });\n }, []);\n\n return {\n totalUnread,\n getCountForConversation,\n clearForConversation,\n };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { useCollab } from '../context/CollabProvider';\nimport type { Message } from '../core/types';\n\ninterface UsePinnedMessagesOptions {\n conversationId: string | null;\n /** Initial pinned messages from preview/initial load (avoids extra fetch) */\n initial?: Message[];\n}\n\ninterface UsePinnedMessagesReturn {\n pinnedMessages: Message[];\n isLoading: boolean;\n error: string | null;\n pin: (messageId: string) => Promise<void>;\n unpin: (messageId: string) => Promise<void>;\n /** Handlers to wire to socket pin/unpin events */\n handlePinned: (message: Message) => void;\n handleUnpinned: (messageId: string) => void;\n refresh: () => Promise<void>;\n}\n\n/**\n * Manages pinned messages for a conversation.\n * Backend enforces MAX_PINNED_MESSAGES (3) — attempting to pin a 4th returns an error.\n */\nexport function usePinnedMessages({\n conversationId,\n initial = [],\n}: UsePinnedMessagesOptions): UsePinnedMessagesReturn {\n const { pinMessage, unpinMessage, fetchPinnedMessages, config } = useCollab();\n const [pinnedMessages, setPinnedMessages] = useState<Message[]>(initial);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const refresh = useCallback(async () => {\n if (!conversationId) return;\n setIsLoading(true);\n setError(null);\n try {\n const pinned = await fetchPinnedMessages(conversationId);\n setPinnedMessages(pinned);\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to load pinned messages';\n setError(msg);\n } finally {\n setIsLoading(false);\n }\n }, [conversationId, fetchPinnedMessages]);\n\n // Only auto-fetch if we don't have initial data\n useEffect(() => {\n if (conversationId && initial.length === 0) {\n refresh();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [conversationId]);\n\n const pin = useCallback(\n async (messageId: string) => {\n if (!conversationId) return;\n setError(null);\n try {\n await pinMessage(conversationId, messageId);\n // Server broadcasts message:pinned — handled via handlePinned\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to pin message';\n setError(msg);\n config.onError?.({\n code: 'PIN_ERROR',\n message: msg,\n details: err,\n });\n }\n },\n [conversationId, pinMessage, config]\n );\n\n const unpin = useCallback(\n async (messageId: string) => {\n if (!conversationId) return;\n setError(null);\n try {\n await unpinMessage(conversationId, messageId);\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to unpin message';\n setError(msg);\n config.onError?.({\n code: 'UNPIN_ERROR',\n message: msg,\n details: err,\n });\n }\n },\n [conversationId, unpinMessage, config]\n );\n\n const handlePinned = useCallback((message: Message) => {\n setPinnedMessages((prev) => {\n if (prev.some((m) => m.id === message.id)) return prev;\n return [...prev, message];\n });\n }, []);\n\n const handleUnpinned = useCallback((messageId: string) => {\n setPinnedMessages((prev) => prev.filter((m) => m.id !== messageId));\n }, []);\n\n return {\n pinnedMessages,\n isLoading,\n error,\n pin,\n unpin,\n handlePinned,\n handleUnpinned,\n refresh,\n };\n}\n"]}