feat: worklist sorting, contextual disposition, context panel redesign, notifications

- Worklist default sort descending (newest first), sortable column headers (PRIORITY, PATIENT, SLA) via React Aria
- Contextual disposition: auto-selects based on in-call actions (appointment → APPOINTMENT_BOOKED, enquiry → INFO_PROVIDED, transfer → FOLLOW_UP_SCHEDULED)
- Context panel redesign: collapsible AI Insight, Upcoming (appointments + follow-ups + linked patient), Recent (calls + activities) sections; auto-collapse on AI chat start
- Appointments added to DataProvider with APPOINTMENTS_QUERY, Appointment type, transform
- Notification bell for admin/supervisor: performance alerts (idle time, NPS, conversion thresholds) with toast on load + bell dropdown with dismiss; demo alerts as fallback
- Slideout z-index fix: added z-50 to slideout ModalOverlay matching modal component

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 14:45:52 +05:30
parent 0477064b3e
commit c3c3f4b3d7
18 changed files with 882 additions and 389 deletions

View File

@@ -8,6 +8,7 @@ import { useSip } from '@/providers/sip-provider';
import { CallWidget } from '@/components/call-desk/call-widget';
import { MaintOtpModal } from '@/components/modals/maint-otp-modal';
import { AgentStatusToggle } from '@/components/call-desk/agent-status-toggle';
import { NotificationBell } from './notification-bell';
import { useAuth } from '@/providers/auth-provider';
import { useMaintShortcuts } from '@/hooks/use-maint-shortcuts';
import { useNetworkStatus } from '@/hooks/use-network-status';
@@ -19,7 +20,7 @@ interface AppShellProps {
export const AppShell = ({ children }: AppShellProps) => {
const { pathname } = useLocation();
const { isCCAgent } = useAuth();
const { isCCAgent, isAdmin } = useAuth();
const { isOpen, activeAction, close } = useMaintShortcuts();
const { connectionStatus, isRegistered } = useSip();
const networkQuality = useNetworkStatus();
@@ -50,23 +51,28 @@ export const AppShell = ({ children }: AppShellProps) => {
<Sidebar activeUrl={pathname} />
<div className="flex flex-1 flex-col overflow-hidden">
{/* Persistent top bar — visible on all pages */}
{hasAgentConfig && (
{(hasAgentConfig || isAdmin) && (
<div className="flex shrink-0 items-center justify-end gap-2 border-b border-secondary px-4 py-2">
<div className={cx(
'flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-medium',
networkQuality === 'good'
? 'bg-success-primary text-success-primary'
: networkQuality === 'offline'
? 'bg-error-secondary text-error-primary'
: 'bg-warning-secondary text-warning-primary',
)}>
<FontAwesomeIcon
icon={networkQuality === 'offline' ? faWifiSlash : faWifi}
className="size-3"
/>
{networkQuality === 'good' ? 'Connected' : networkQuality === 'offline' ? 'No connection' : 'Unstable'}
</div>
<AgentStatusToggle isRegistered={isRegistered} connectionStatus={connectionStatus} />
{isAdmin && <NotificationBell />}
{hasAgentConfig && (
<>
<div className={cx(
'flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-medium',
networkQuality === 'good'
? 'bg-success-primary text-success-primary'
: networkQuality === 'offline'
? 'bg-error-secondary text-error-primary'
: 'bg-warning-secondary text-warning-primary',
)}>
<FontAwesomeIcon
icon={networkQuality === 'offline' ? faWifiSlash : faWifi}
className="size-3"
/>
{networkQuality === 'good' ? 'Connected' : networkQuality === 'offline' ? 'No connection' : 'Unstable'}
</div>
<AgentStatusToggle isRegistered={isRegistered} connectionStatus={connectionStatus} />
</>
)}
</div>
)}
<main className="flex flex-1 flex-col overflow-hidden">{children}</main>