// Copyright: © 2026 TWWIM UG. All rights reserved. (www.twwim.com) /** * Wait-time + SLA helpers for the Communication Center. * * "Reply time" = gap between the visitor's most recent message and the next * outbound message (assistant or operator). When the gap exceeds the * threshold the row gets a visual urgency cue. * * Thresholds: 60 s warn (amber), 180 s breach (red + pulse). */ import type { ConversationListItem, ConversationDetail } from './types'; export type WaitUrgency = 'none' | 'warn' | 'breach'; const WARN_THRESHOLD_MS = 60_000; const BREACH_THRESHOLD_MS = 180_000; export function visitorWaitMsItem(conv: ConversationListItem, now: Date = new Date()): number { if (conv.status === 'closed') return 0; if (!conv.lastMessage) return 0; if (conv.lastMessage.role !== 'user') return 0; return now.getTime() - new Date(conv.lastMessage.createdAt).getTime(); } export function visitorWaitMsDetail(conv: ConversationDetail, now: Date = new Date()): number { if (conv.status === 'closed') return 0; const last = conv.messages[conv.messages.length - 1]; if (!last || last.role !== 'user') return 0; return now.getTime() - new Date(last.createdAt).getTime(); } export function urgencyFor(waitMs: number): WaitUrgency { if (waitMs >= BREACH_THRESHOLD_MS) return 'breach'; if (waitMs >= WARN_THRESHOLD_MS) return 'warn'; return 'none'; } export function urgencyOfConversationItem(conv: ConversationListItem, now: Date = new Date()): WaitUrgency { return urgencyFor(visitorWaitMsItem(conv, now)); } export function formatWait(waitMs: number): string { const seconds = Math.floor(waitMs / 1000); if (seconds < 60) return `${seconds}s`; const minutes = Math.floor(seconds / 60); if (minutes < 60) return `${minutes}m`; const hours = Math.floor(minutes / 60); return `${hours}h`; }