import { TrendingUp, TrendingDown, AlertTriangle, CheckCircle, Target, Activity, Clock, PhoneForwarded, Users } from 'lucide-react'; import type { AnalysisData, Finding } from '../../types'; interface ExecutiveSummaryTabProps { data: AnalysisData; } // Compact KPI Row Component function KeyMetricsCard({ totalInteractions, avgAHT, avgFCR, avgTransferRate, ahtBenchmark, fcrBenchmark }: { totalInteractions: number; avgAHT: number; avgFCR: number; avgTransferRate: number; ahtBenchmark?: number; fcrBenchmark?: number; }) { const formatNumber = (n: number) => n >= 1000 ? `${(n / 1000).toFixed(1)}K` : n.toString(); const getAHTStatus = (aht: number) => { if (aht <= 300) return { color: 'text-emerald-600', bg: 'bg-emerald-50', label: 'Excelente' }; if (aht <= 420) return { color: 'text-emerald-600', bg: 'bg-emerald-50', label: 'Bueno' }; if (aht <= 480) return { color: 'text-amber-600', bg: 'bg-amber-50', label: 'Aceptable' }; return { color: 'text-red-600', bg: 'bg-red-50', label: 'Alto' }; }; const getFCRStatus = (fcr: number) => { if (fcr >= 85) return { color: 'text-emerald-600', bg: 'bg-emerald-50', label: 'Excelente' }; if (fcr >= 75) return { color: 'text-emerald-600', bg: 'bg-emerald-50', label: 'Bueno' }; if (fcr >= 65) return { color: 'text-amber-600', bg: 'bg-amber-50', label: 'Mejorable' }; return { color: 'text-red-600', bg: 'bg-red-50', label: 'Crítico' }; }; const ahtStatus = getAHTStatus(avgAHT); const fcrStatus = getFCRStatus(avgFCR); const metrics = [ { icon: Users, label: 'Interacciones', value: formatNumber(totalInteractions), sublabel: 'mensuales', status: null }, { icon: Clock, label: 'AHT Promedio', value: `${Math.floor(avgAHT / 60)}:${String(avgAHT % 60).padStart(2, '0')}`, sublabel: ahtBenchmark ? `Benchmark: ${Math.floor(ahtBenchmark / 60)}:${String(Math.round(ahtBenchmark) % 60).padStart(2, '0')}` : 'min:seg', status: ahtStatus }, { icon: CheckCircle, label: 'FCR', value: `${avgFCR}%`, sublabel: fcrBenchmark ? `Benchmark: ${fcrBenchmark}%` : 'Resolución 1er contacto', status: fcrStatus }, { icon: PhoneForwarded, label: 'Transferencias', value: `${avgTransferRate}%`, sublabel: avgTransferRate > 20 ? 'Requiere atención' : 'Bajo control', status: avgTransferRate > 20 ? { color: 'text-amber-600', bg: 'bg-amber-50', label: 'Alto' } : { color: 'text-emerald-600', bg: 'bg-emerald-50', label: 'OK' } } ]; return (
{metrics.map((metric) => { const Icon = metric.icon; return (
{metric.label}
{metric.value} {metric.status && ( {metric.status.label} )}

{metric.sublabel}

); })}
); } // Health Score with Breakdown function HealthScoreDetailed({ score, avgFCR, avgAHT, avgTransferRate, avgCSAT }: { score: number; avgFCR: number; avgAHT: number; avgTransferRate: number; avgCSAT: number; }) { const getColor = (s: number) => { if (s >= 80) return '#059669'; if (s >= 60) return '#D97706'; return '#DC2626'; }; const getLabel = (s: number) => { if (s >= 80) return 'Excelente'; if (s >= 60) return 'Bueno'; if (s >= 40) return 'Regular'; return 'Crítico'; }; const color = getColor(score); const circumference = 2 * Math.PI * 40; const strokeDasharray = `${(score / 100) * circumference} ${circumference}`; // Calculate individual factor scores (0-100) const fcrScore = Math.min(100, Math.round((avgFCR / 85) * 100)); const ahtScore = Math.min(100, Math.round(Math.max(0, (1 - (avgAHT - 240) / 360) * 100))); const transferScore = Math.min(100, Math.round(Math.max(0, (1 - avgTransferRate / 30) * 100))); const csatScore = avgCSAT; const factors = [ { name: 'FCR', score: fcrScore, weight: '30%', status: fcrScore >= 80 ? 'good' : fcrScore >= 60 ? 'warning' : 'critical', insight: fcrScore >= 80 ? 'Óptimo' : fcrScore >= 60 ? 'Mejorable' : 'Requiere acción' }, { name: 'Eficiencia (AHT)', score: ahtScore, weight: '25%', status: ahtScore >= 80 ? 'good' : ahtScore >= 60 ? 'warning' : 'critical', insight: ahtScore >= 80 ? 'Óptimo' : ahtScore >= 60 ? 'En rango' : 'Muy alto' }, { name: 'Transferencias', score: transferScore, weight: '25%', status: transferScore >= 80 ? 'good' : transferScore >= 60 ? 'warning' : 'critical', insight: transferScore >= 80 ? 'Bajo' : transferScore >= 60 ? 'Moderado' : 'Excesivo' }, { name: 'CSAT', score: csatScore, weight: '20%', status: csatScore >= 80 ? 'good' : csatScore >= 60 ? 'warning' : 'critical', insight: csatScore >= 80 ? 'Óptimo' : csatScore >= 60 ? 'Aceptable' : 'Bajo' } ]; const statusColors = { good: 'bg-emerald-500', warning: 'bg-amber-500', critical: 'bg-red-500' }; const getMainInsight = () => { const weakest = factors.reduce((min, f) => f.score < min.score ? f : min, factors[0]); const strongest = factors.reduce((max, f) => f.score > max.score ? f : max, factors[0]); if (score >= 80) { return `Rendimiento destacado en ${strongest.name}. Mantener estándares actuales.`; } else if (score >= 60) { return `Oportunidad de mejora en ${weakest.name} (${weakest.insight.toLowerCase()}).`; } else { return `Priorizar mejora en ${weakest.name}: impacto directo en satisfacción del cliente.`; } }; return (
{/* Gauge */}
{score}

{getLabel(score)}

{/* Breakdown */}

Health Score - Desglose

{factors.map((factor) => (
{factor.name}
{factor.score}
{factor.insight}
))}
{/* Key Insight */}

Insight: {getMainInsight()}

); } // Top Opportunities Component function TopOpportunities({ findings, opportunities }: { findings: Finding[]; opportunities: { name: string; impact: number; savings: number }[]; }) { const items = [ ...findings .filter(f => f.type === 'critical' || f.type === 'warning') .slice(0, 3) .map((f, i) => ({ rank: i + 1, title: f.title || f.text.split(':')[0], metric: f.text.includes(':') ? f.text.split(':')[1].trim() : '', action: f.description || 'Acción requerida', type: f.type as 'critical' | 'warning' | 'info' })), ].slice(0, 3); if (items.length < 3) { const remaining = 3 - items.length; opportunities .sort((a, b) => b.savings - a.savings) .slice(0, remaining) .forEach(() => { const opp = opportunities[items.length]; if (opp) { items.push({ rank: items.length + 1, title: opp.name, metric: `€${opp.savings.toLocaleString()} ahorro potencial`, action: 'Implementar', type: 'info' as const }); } }); } const getIcon = (type: string) => { if (type === 'critical') return ; if (type === 'warning') return ; return ; }; return (

Top 3 Oportunidades

{items.map((item) => (
{item.rank}
{getIcon(item.type)} {item.title}
{item.metric && (

{item.metric}

)}

→ {item.action}

))}
); } // Economic Summary Compact function EconomicSummary({ economicModel }: { economicModel: AnalysisData['economicModel'] }) { return (

Impacto Económico

Coste Anual

€{(economicModel.currentAnnualCost / 1000).toFixed(0)}K

Ahorro Potencial

€{(economicModel.annualSavings / 1000).toFixed(0)}K

ROI 3 años

{economicModel.roi3yr}%

Payback

{economicModel.paybackMonths}m

); } export function ExecutiveSummaryTab({ data }: ExecutiveSummaryTabProps) { const totalInteractions = data.heatmapData.reduce((sum, h) => sum + h.volume, 0); const avgAHT = data.heatmapData.length > 0 ? Math.round(data.heatmapData.reduce((sum, h) => sum + h.aht_seconds, 0) / data.heatmapData.length) : 0; const avgFCR = data.heatmapData.length > 0 ? Math.round(data.heatmapData.reduce((sum, h) => sum + h.metrics.fcr, 0) / data.heatmapData.length) : 0; const avgTransferRate = data.heatmapData.length > 0 ? Math.round(data.heatmapData.reduce((sum, h) => sum + h.metrics.transfer_rate, 0) / data.heatmapData.length) : 0; const avgCSAT = data.heatmapData.length > 0 ? Math.round(data.heatmapData.reduce((sum, h) => sum + h.metrics.csat, 0) / data.heatmapData.length) : 0; const ahtBenchmark = data.benchmarkData.find(b => b.kpi.toLowerCase().includes('aht')); const fcrBenchmark = data.benchmarkData.find(b => b.kpi.toLowerCase().includes('fcr')); return (
{/* Key Metrics Bar */} {/* Health Score with Breakdown */} {/* Bottom Row */}
); } export default ExecutiveSummaryTab;