import React, { useState, useEffect, useCallback } from 'react'; import { fetchAiInsights, dismissAiInsight, } from '../../service/agent-analytics/agent-analytics.service'; import { createCampaign } from '../../service/campaigns/campaigns.service'; import type { IInsightReport, IInsightsResponse, IInsight, IInsightMetric, ISuggestedCampaign, } from '../../service/agent-analytics/agent-analytics.interface'; interface InsightsTabProps { onInsightCountChange?: (count: number) => void; } const PRIORITY_STYLES: Record< string, { dot: string; badge: string; badgeText: string } > = { high: { dot: 'bg-red-500', badge: 'bg-red-50 text-red-700 ring-red-600/10', badgeText: 'high', }, medium: { dot: 'bg-yellow-500', badge: 'bg-yellow-50 text-yellow-700 ring-yellow-600/10', badgeText: 'medium', }, low: { dot: 'bg-green-500', badge: 'bg-green-50 text-green-700 ring-green-600/10', badgeText: 'low', }, }; const InsightsTab = ({ onInsightCountChange, }: InsightsTabProps): JSX.Element => { const [report, setReport] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [expandedId, setExpandedId] = useState(null); const [creatingCampaign, setCreatingCampaign] = useState(null); const [campaignSuccess, setCampaignSuccess] = useState>( new Set() ); const [campaignError, setCampaignError] = useState(null); const fetchInsights = useCallback(() => { setLoading(true); setError(null); fetchAiInsights() .then((data: IInsightsResponse | null) => { const nextReport: IInsightReport | null = data?.report ?? null; setReport(nextReport); const activeInsights: IInsight[] = (nextReport?.insights || []).filter( (insight: IInsight) => !insight.dismissed ); onInsightCountChange?.(activeInsights.length); setLoading(false); }) .catch((err: Error) => { setError(err.message || 'Failed to load insights'); setLoading(false); }); }, [onInsightCountChange]); useEffect(() => { fetchInsights(); }, [fetchInsights]); const handleDismiss = async (insightId: string) => { if (!report) return; try { await dismissAiInsight(report.report_id, insightId); setReport((prev: IInsightReport | null) => { if (!prev) return prev; const updated: IInsightReport = { ...prev, insights: prev.insights.map((insight: IInsight) => insight.id === insightId ? { ...insight, dismissed: true } : insight ), }; const activeInsights: IInsight[] = updated.insights.filter( (insight: IInsight) => !insight.dismissed ); onInsightCountChange?.(activeInsights.length); return updated; }); } catch { // Silent fail — insight stays visible } }; const handleCreateCampaign = async (insight: IInsight) => { const suggestedCampaign: ISuggestedCampaign | undefined = insight.suggested_campaign; if (!suggestedCampaign) return; setCreatingCampaign(insight.id); setCampaignError(null); try { await createCampaign({ name: suggestedCampaign.name, goal: suggestedCampaign.goal, target_categories: suggestedCampaign.target_categories, tone_of_voice: suggestedCampaign.tone_of_voice, priority: suggestedCampaign.priority, description: suggestedCampaign.description, }); setCampaignSuccess(prev => new Set(prev).add(insight.id)); } catch (err: unknown) { setCampaignError( err instanceof Error ? err.message : 'Failed to create campaign' ); } finally { setCreatingCampaign(null); } }; if (loading) { return (
{[1, 2, 3].map(i => (
))}
); } if (error) { return (

{error}

); } const activeInsights: IInsight[] = (report?.insights || []).filter( (insight: IInsight) => !insight.dismissed ); if (!report || activeInsights.length === 0) { return (

Insights are on their way

AI-powered insights are generated weekly based on your conversation data. Once you have at least 7 days of conversations, your first report will appear here automatically.

); } const periodLabel = report.period_start && report.period_end ? `${report.period_start} — ${report.period_end}` : ''; return (
{/* Summary banner */}

AI Insights

{report.summary}

{periodLabel && (

Based on data from {periodLabel}

)}
{/* Section header */}

Recommended Actions

{campaignError && (

{campaignError}

)} {/* Insight cards */}
{activeInsights.map(insight => { const isExpanded = expandedId === insight.id; const style = PRIORITY_STYLES[insight.priority] || PRIORITY_STYLES.low; const isCampaignCreated = campaignSuccess.has(insight.id); const isCreating = creatingCampaign === insight.id; return (
{/* Collapsed header */} {/* Expanded content */} {isExpanded && (
{/* Metrics */} {insight.metrics?.length > 0 && (
{insight.metrics.map( (metric: IInsightMetric, index: number) => (

{metric.label}

{metric.value}

) )}
)} {/* Suggested campaign */} {insight.suggested_campaign && (

Suggested action: Create a targeted campaign

Campaign name

{insight.suggested_campaign.name}

Goal

{insight.suggested_campaign.goal}

Target categories

{insight.suggested_campaign.target_categories?.join( ', ' ) || '—'}

Tone

{insight.suggested_campaign.tone_of_voice}
{isCampaignCreated ? (
Campaign created
) : ( )}
)} {/* Dismiss */}
)}
); })}
); }; export default InsightsTab;