mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
feat: call desk redesign — 2-panel layout, collapsible sidebar, inline AI, ringtone
- Collapsible sidebar with Jotai atom (icon-only mode, persisted to localStorage) - 2-panel call desk: worklist (60%) + context panel (40%) with AI + Lead 360 tabs - Inline AI call prep card — known lead summary or unknown caller script - Active call card with compact Answer/Decline buttons - Worklist panel with human-readable labels, priority badges, click-to-select - Context panel auto-switches to Lead 360 when lead selected or call incoming - Browser ringtone via Web Audio API on incoming calls - Sonner + Untitled UI IconNotification for toast system - apiClient pattern: centralized post/get/graphql with auto-toast on errors - Remove duplicate avatar from top bar, hide floating widget on call desk - Fix Link routing in collapsed sidebar (was using <a> causing full page reload) - Fix GraphQL field names: adStatus→status, platformUrl needs subfield selection - Silent mode for DataProvider queries to prevent toast spam Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,25 +1,43 @@
|
||||
import { useState } from 'react';
|
||||
import { Phone01 } from '@untitledui/icons';
|
||||
import { Button } from '@/components/base/buttons/button';
|
||||
import { useSip } from '@/providers/sip-provider';
|
||||
import { apiClient } from '@/lib/api-client';
|
||||
import { notify } from '@/lib/toast';
|
||||
|
||||
interface ClickToCallButtonProps {
|
||||
phoneNumber: string;
|
||||
leadId?: string;
|
||||
label?: string;
|
||||
size?: 'sm' | 'md';
|
||||
}
|
||||
|
||||
export const ClickToCallButton = ({ phoneNumber, label, size = 'sm' }: ClickToCallButtonProps) => {
|
||||
const { makeCall, isRegistered, isInCall } = useSip();
|
||||
export const ClickToCallButton = ({ phoneNumber, leadId, label, size = 'sm' }: ClickToCallButtonProps) => {
|
||||
const { isRegistered, isInCall } = useSip();
|
||||
const [dialing, setDialing] = useState(false);
|
||||
|
||||
const handleDial = async () => {
|
||||
setDialing(true);
|
||||
try {
|
||||
await apiClient.post('/api/ozonetel/dial', { phoneNumber, leadId });
|
||||
notify.success('Dialing', `Calling ${phoneNumber}...`);
|
||||
} catch {
|
||||
// apiClient.post already toasts the error
|
||||
} finally {
|
||||
setDialing(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
size={size}
|
||||
color="primary"
|
||||
iconLeading={Phone01}
|
||||
onClick={() => makeCall(phoneNumber)}
|
||||
isDisabled={!isRegistered || isInCall || phoneNumber === ''}
|
||||
onClick={handleDial}
|
||||
isDisabled={!isRegistered || isInCall || !phoneNumber || dialing}
|
||||
isLoading={dialing}
|
||||
>
|
||||
{label ?? 'Call'}
|
||||
{dialing ? 'Dialing...' : (label ?? 'Call')}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user