import { useState } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faCircle, faChevronDown } from '@fortawesome/pro-duotone-svg-icons'; import { useAgentState } from '@/hooks/use-agent-state'; import type { OzonetelState } from '@/hooks/use-agent-state'; import { apiClient } from '@/lib/api-client'; import { notify } from '@/lib/toast'; import { cx } from '@/utils/cx'; type ToggleableStatus = 'ready' | 'break' | 'training'; const displayConfig: Record = { ready: { label: 'Ready', color: 'text-success-primary', dotColor: 'text-fg-success-primary' }, break: { label: 'Break', color: 'text-warning-primary', dotColor: 'text-fg-warning-primary' }, training: { label: 'Training', color: 'text-brand-secondary', dotColor: 'text-fg-brand-primary' }, calling: { label: 'Calling', color: 'text-brand-secondary', dotColor: 'text-fg-brand-primary' }, 'in-call': { label: 'In Call', color: 'text-brand-secondary', dotColor: 'text-fg-brand-primary' }, acw: { label: 'Wrapping up', color: 'text-warning-primary', dotColor: 'text-fg-warning-primary' }, offline: { label: 'Offline', color: 'text-tertiary', dotColor: 'text-fg-quaternary' }, }; const toggleOptions: Array<{ key: ToggleableStatus; label: string; color: string; dotColor: string }> = [ { key: 'ready', label: 'Ready', color: 'text-success-primary', dotColor: 'text-fg-success-primary' }, { key: 'break', label: 'Break', color: 'text-warning-primary', dotColor: 'text-fg-warning-primary' }, { key: 'training', label: 'Training', color: 'text-brand-secondary', dotColor: 'text-fg-brand-primary' }, ]; type AgentStatusToggleProps = { isRegistered: boolean; connectionStatus: string; }; export const AgentStatusToggle = ({ isRegistered, connectionStatus }: AgentStatusToggleProps) => { const agentConfig = localStorage.getItem('helix_agent_config'); const agentId = agentConfig ? JSON.parse(agentConfig).ozonetelAgentId : null; const ozonetelState = useAgentState(agentId); const [menuOpen, setMenuOpen] = useState(false); const [changing, setChanging] = useState(false); const handleChange = async (newStatus: ToggleableStatus) => { setMenuOpen(false); if (newStatus === ozonetelState) return; setChanging(true); try { if (newStatus === 'ready') { console.log('[AGENT-STATE] Changing to Ready'); const res = await apiClient.post('/api/ozonetel/agent-state', { state: 'Ready' }); console.log('[AGENT-STATE] Ready response:', JSON.stringify(res)); } else { const pauseReason = newStatus === 'break' ? 'Break' : 'Training'; console.log(`[AGENT-STATE] Changing to Pause: ${pauseReason}`); const res = await apiClient.post('/api/ozonetel/agent-state', { state: 'Pause', pauseReason }); console.log('[AGENT-STATE] Pause response:', JSON.stringify(res)); } // Don't setStatus — SSE will push the real state } catch (err) { console.error('[AGENT-STATE] Status change failed:', err); notify.error('Status Change Failed', 'Could not update agent status'); } finally { setChanging(false); } }; // If SIP isn't connected, show connection status with user-friendly message if (!isRegistered) { const statusMessages: Record = { disconnected: 'Telephony unavailable', connecting: 'Connecting to telephony...', connected: 'Registering...', error: 'Telephony error — check VPN', }; return (
{statusMessages[connectionStatus] ?? connectionStatus}
); } const current = displayConfig[ozonetelState] ?? displayConfig.offline; const canToggle = ozonetelState === 'ready' || ozonetelState === 'break' || ozonetelState === 'training' || ozonetelState === 'offline'; return (
{menuOpen && ( <>
setMenuOpen(false)} />
{toggleOptions.map((opt) => ( ))}
)}
); };