fix: notifications use real data + agent-detail follows new id scheme

1. notification-bell: drop the DEMO_ALERTS fallback (Riya Mehta etc.).
   Empty state ("No active alerts") shows when the live computation
   returns nothing — which is the truthful state until thresholds are
   set on Agent records.
2. use-performance-alerts: bucket calls by c.agentId === agent.id when
   the relation is set; fall back to legacy agentName matching only for
   un-enriched rows. Fixes conversion% calc going to 0 after backfill.
3. agent-table: Link target uses agent.id (UUID or "legacy:NAME") so
   the URL is a stable identifier instead of a display string.
4. agent-detail: parse the route param into UUID vs legacy:NAME, filter
   calls by c.agentId or c.agentName accordingly, and resolve display
   name via the platform Agents list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-15 08:47:57 +05:30
parent 8de7d7d802
commit 91a1f33d35
4 changed files with 32 additions and 41 deletions

View File

@@ -95,7 +95,7 @@ export const AgentTable = ({ calls }: AgentTableProps) => {
{(agent) => (
<Table.Row id={agent.id}>
<Table.Cell>
<Link to={`/agent/${encodeURIComponent(agent.name)}`} className="no-underline">
<Link to={`/agent/${encodeURIComponent(agent.id)}`} className="no-underline">
<div className="flex items-center gap-2">
<Avatar size="xs" initials={agent.initials} />
<span className="text-sm font-medium text-brand-secondary hover:text-brand-secondary_hover transition duration-100 ease-linear">{agent.name}</span>

View File

@@ -2,46 +2,14 @@ import { useState, useRef, useEffect } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faBell, faTriangleExclamation, faXmark, faCheck } from '@fortawesome/pro-duotone-svg-icons';
import { Badge } from '@/components/base/badges/badges';
import { usePerformanceAlerts, type PerformanceAlert } from '@/hooks/use-performance-alerts';
import { usePerformanceAlerts } from '@/hooks/use-performance-alerts';
import { cx } from '@/utils/cx';
const DEMO_ALERTS: PerformanceAlert[] = [
{ id: 'demo-1', agent: 'Riya Mehta', type: 'Excessive Idle Time', value: '120m', severity: 'error', dismissed: false },
{ id: 'demo-2', agent: 'Arjun Kapoor', type: 'Excessive Idle Time', value: '180m', severity: 'error', dismissed: false },
{ id: 'demo-3', agent: 'Sneha Iyer', type: 'Excessive Idle Time', value: '250m', severity: 'error', dismissed: false },
{ id: 'demo-4', agent: 'Vikrant Desai', type: 'Excessive Idle Time', value: '300m', severity: 'error', dismissed: false },
{ id: 'demo-5', agent: 'Vikrant Desai', type: 'Low NPS', value: '35', severity: 'warning', dismissed: false },
{ id: 'demo-6', agent: 'Vikrant Desai', type: 'Low Conversion', value: '40%', severity: 'warning', dismissed: false },
{ id: 'demo-7', agent: 'Pooja Rao', type: 'Excessive Idle Time', value: '200m', severity: 'error', dismissed: false },
{ id: 'demo-8', agent: 'Mohammed Rizwan', type: 'Excessive Idle Time', value: '80m', severity: 'error', dismissed: false },
];
export const NotificationBell = () => {
const { alerts: liveAlerts, dismiss: liveDismiss, dismissAll: liveDismissAll } = usePerformanceAlerts();
const [demoAlerts, setDemoAlerts] = useState<PerformanceAlert[]>(DEMO_ALERTS);
const [open, setOpen] = useState(true);
const { alerts, dismiss, dismissAll } = usePerformanceAlerts();
const [open, setOpen] = useState(false);
const panelRef = useRef<HTMLDivElement>(null);
// Use live alerts if available, otherwise demo
const alerts = liveAlerts.length > 0 ? liveAlerts : demoAlerts.filter(a => !a.dismissed);
const isDemo = liveAlerts.length === 0;
const dismiss = (id: string) => {
if (isDemo) {
setDemoAlerts(prev => prev.map(a => a.id === id ? { ...a, dismissed: true } : a));
} else {
liveDismiss(id);
}
};
const dismissAll = () => {
if (isDemo) {
setDemoAlerts(prev => prev.map(a => ({ ...a, dismissed: true })));
} else {
liveDismissAll();
}
};
// Close on outside click
useEffect(() => {
if (!open) return;