/** * OpportunityPrioritizer - v1.0 * * Redesigned Opportunity Matrix that clearly shows: * 1. WHERE are the opportunities (ranked list with context) * 2. WHERE to START (highlighted #1 with full justification) * 3. WHY this prioritization (tier-based rationale + metrics) * * Design principles: * - Scannable in 5 seconds (executive summary) * - Actionable in 30 seconds (clear next steps) * - Deep-dive available (expandable details) */ import React, { useState, useMemo } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { useTranslation } from 'react-i18next'; import { Opportunity, DrilldownDataPoint, AgenticTier } from '../types'; import { ChevronRight, ChevronDown, TrendingUp, Zap, Clock, Users, Bot, Headphones, BookOpen, AlertTriangle, CheckCircle2, ArrowRight, Info, Target, DollarSign, BarChart3, Sparkles } from 'lucide-react'; interface OpportunityPrioritizerProps { opportunities: Opportunity[]; drilldownData?: DrilldownDataPoint[]; costPerHour?: number; } interface EnrichedOpportunity extends Opportunity { rank: number; tier: AgenticTier; volume: number; cv_aht: number; transfer_rate: number; fcr_rate: number; agenticScore: number; timelineMonths: number; effortLevel: 'low' | 'medium' | 'high'; riskLevel: 'low' | 'medium' | 'high'; whyPrioritized: string[]; nextSteps: string[]; annualCost?: number; } // Tier configuration const TIER_CONFIG: Record = { 'AUTOMATE': { icon: , label: 'Automatizar', color: 'text-emerald-700', bgColor: 'bg-emerald-50', borderColor: 'border-emerald-300', savingsRate: '70%', timeline: '3-6 meses', description: 'Automatización completa con agentes IA' }, 'ASSIST': { icon: , label: 'Asistir', color: 'text-blue-700', bgColor: 'bg-blue-50', borderColor: 'border-blue-300', savingsRate: '30%', timeline: '6-9 meses', description: 'Copilot IA para agentes humanos' }, 'AUGMENT': { icon: , label: 'Optimizar', color: 'text-amber-700', bgColor: 'bg-amber-50', borderColor: 'border-amber-300', savingsRate: '15%', timeline: '9-12 meses', description: 'Estandarización y mejora de procesos' }, 'HUMAN-ONLY': { icon: , label: 'Humano', color: 'text-slate-600', bgColor: 'bg-slate-50', borderColor: 'border-slate-300', savingsRate: '0%', timeline: 'N/A', description: 'Requiere intervención humana' } }; const OpportunityPrioritizer: React.FC = ({ opportunities, drilldownData, costPerHour = 20 }) => { const { t } = useTranslation(); const [expandedId, setExpandedId] = useState(null); const [showAllOpportunities, setShowAllOpportunities] = useState(false); // Enrich opportunities with drilldown data const enrichedOpportunities = useMemo((): EnrichedOpportunity[] => { if (!opportunities || opportunities.length === 0) return []; // Create a lookup map from drilldown data const queueLookup = new Map(); if (drilldownData) { drilldownData.forEach(skill => { skill.originalQueues?.forEach(q => { queueLookup.set(q.original_queue_id.toLowerCase(), { tier: q.tier || 'HUMAN-ONLY', volume: q.volume, cv_aht: q.cv_aht, transfer_rate: q.transfer_rate, fcr_rate: q.fcr_rate, agenticScore: q.agenticScore, annualCost: q.annualCost }); }); }); } return opportunities.map((opp, index) => { // Extract queue name (remove tier emoji prefix) const cleanName = opp.name.replace(/^[^\w\s]+\s*/, '').toLowerCase(); const lookupData = queueLookup.get(cleanName); // Determine tier from emoji prefix or lookup let tier: AgenticTier = 'ASSIST'; if (opp.name.startsWith('🤖')) tier = 'AUTOMATE'; else if (opp.name.startsWith('🤝')) tier = 'ASSIST'; else if (opp.name.startsWith('📚')) tier = 'AUGMENT'; else if (lookupData) tier = lookupData.tier; // Calculate effort and risk based on metrics const cv = lookupData?.cv_aht || 50; const transfer = lookupData?.transfer_rate || 15; const effortLevel: 'low' | 'medium' | 'high' = tier === 'AUTOMATE' && cv < 60 ? 'low' : tier === 'ASSIST' || cv < 80 ? 'medium' : 'high'; const riskLevel: 'low' | 'medium' | 'high' = cv < 50 && transfer < 15 ? 'low' : cv < 80 && transfer < 30 ? 'medium' : 'high'; // Timeline based on tier const timelineMonths = tier === 'AUTOMATE' ? 4 : tier === 'ASSIST' ? 7 : 10; // Generate "why" explanation const whyPrioritized: string[] = []; if (opp.savings > 50000) whyPrioritized.push(`Alto ahorro potencial (€${(opp.savings / 1000).toFixed(0)}K/año)`); if (lookupData?.volume && lookupData.volume > 1000) whyPrioritized.push(`Alto volumen (${lookupData.volume.toLocaleString()} interacciones)`); if (tier === 'AUTOMATE') whyPrioritized.push('Proceso altamente predecible y repetitivo'); if (cv < 60) whyPrioritized.push('Baja variabilidad en tiempos de gestión'); if (transfer < 15) whyPrioritized.push('Baja tasa de transferencias'); if (opp.feasibility >= 7) whyPrioritized.push('Alta factibilidad técnica'); // Generate next steps const nextSteps: string[] = []; if (tier === 'AUTOMATE') { nextSteps.push('Definir flujos conversacionales principales'); nextSteps.push('Identificar integraciones necesarias (CRM, APIs)'); nextSteps.push('Crear piloto con 10% del volumen'); } else if (tier === 'ASSIST') { nextSteps.push('Mapear puntos de fricción del agente'); nextSteps.push('Diseñar sugerencias contextuales'); nextSteps.push('Piloto con equipo seleccionado'); } else { nextSteps.push('Analizar causa raíz de variabilidad'); nextSteps.push('Estandarizar procesos y scripts'); nextSteps.push('Capacitar equipo en mejores prácticas'); } return { ...opp, rank: index + 1, tier, volume: lookupData?.volume || Math.round(opp.savings / 10), cv_aht: cv, transfer_rate: transfer, fcr_rate: lookupData?.fcr_rate || 75, agenticScore: lookupData?.agenticScore || opp.feasibility, timelineMonths, effortLevel, riskLevel, whyPrioritized, nextSteps, annualCost: lookupData?.annualCost }; }); }, [opportunities, drilldownData]); // Summary stats const summary = useMemo(() => { const totalSavings = enrichedOpportunities.reduce((sum, o) => sum + o.savings, 0); const byTier = { AUTOMATE: enrichedOpportunities.filter(o => o.tier === 'AUTOMATE'), ASSIST: enrichedOpportunities.filter(o => o.tier === 'ASSIST'), AUGMENT: enrichedOpportunities.filter(o => o.tier === 'AUGMENT') }; const quickWins = enrichedOpportunities.filter(o => o.tier === 'AUTOMATE' && o.effortLevel === 'low'); return { totalSavings, totalVolume: enrichedOpportunities.reduce((sum, o) => sum + o.volume, 0), byTier, quickWinsCount: quickWins.length, quickWinsSavings: quickWins.reduce((sum, o) => sum + o.savings, 0) }; }, [enrichedOpportunities]); const displayedOpportunities = showAllOpportunities ? enrichedOpportunities : enrichedOpportunities.slice(0, 5); const topOpportunity = enrichedOpportunities[0]; if (!enrichedOpportunities.length) { return (

No hay oportunidades identificadas

Los datos actuales no muestran oportunidades de automatización viables.

); } return (
{/* Header - matching app's visual style */}

{t('opportunityPrioritizer.title')}

{t('opportunityPrioritizer.subtitle', { count: enrichedOpportunities.length })}

{/* Executive Summary - Answer "Where are opportunities?" in 5 seconds */}
{t('opportunityPrioritizer.totalSavingsIdentified')}
€{(summary.totalSavings / 1000).toFixed(0)}K
{t('opportunityPrioritizer.annual')}
{t('opportunityPrioritizer.quickWins')}
{summary.byTier.AUTOMATE.length}
€{(summary.byTier.AUTOMATE.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { count: '3-6' })}
{t('opportunityPrioritizer.assistance')}
{summary.byTier.ASSIST.length}
€{(summary.byTier.ASSIST.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { count: '6-9' })}
{t('opportunityPrioritizer.optimization')}
{summary.byTier.AUGMENT.length}
€{(summary.byTier.AUGMENT.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { count: '9-12' })}
{/* START HERE - Answer "Where do I start?" */} {topOpportunity && (
{t('opportunityPrioritizer.startHere')} {t('opportunityPrioritizer.priority1')}
{/* Left: Main info */}
{TIER_CONFIG[topOpportunity.tier].icon}

{topOpportunity.name.replace(/^[^\w\s]+\s*/, '')}

{t(`opportunityPrioritizer.tierLabels.${topOpportunity.tier.toLowerCase()}`)} • {TIER_CONFIG[topOpportunity.tier].description}
{/* Key metrics */}
{t('opportunityPrioritizer.annualSavings')}
€{(topOpportunity.savings / 1000).toFixed(0)}K
{t('opportunityPrioritizer.volume')}
{topOpportunity.volume.toLocaleString()}
{t('opportunityPrioritizer.timeline')}
{topOpportunity.timelineMonths} {t('opportunityPrioritizer.months')}
Agentic Score
{topOpportunity.agenticScore.toFixed(1)}/10
{/* Why this is #1 */}

¿Por qué es la prioridad #1?

    {topOpportunity.whyPrioritized.slice(0, 4).map((reason, i) => (
  • {reason}
  • ))}
{/* Right: Next steps */}

t("opportunityPrioritizer.nextSteps")

    {topOpportunity.nextSteps.map((step, i) => (
  1. {i + 1} {step}
  2. ))}
)} {/* Full Opportunity List - Answer "What else?" */}

{t('opportunityPrioritizer.allOpportunities')}

{displayedOpportunities.slice(1).map((opp) => ( {/* Collapsed view */}
setExpandedId(expandedId === opp.id ? null : opp.id)} >
{/* Rank */}
#{opp.rank}
{/* Tier icon and name */}
{TIER_CONFIG[opp.tier].icon}

{opp.name.replace(/^[^\w\s]+\s*/, '')}

{t(`opportunityPrioritizer.tierLabels.${opp.tier.toLowerCase()}`)} • {t(`opportunityPrioritizer.timelines.${opp.tier.toLowerCase()}`)}
{/* Quick stats */}
{t('opportunityPrioritizer.savings')}
€{(opp.savings / 1000).toFixed(0)}K
{t('opportunityPrioritizer.volume')}
{opp.volume.toLocaleString()}
Score
{opp.agenticScore.toFixed(1)}
{/* Visual bar: Value vs Effort */}
{t('opportunityPrioritizer.valueEffort')}
Valor Esfuerzo
{/* Expand icon */}
{/* Expanded details */} {expandedId === opp.id && (
{/* Why prioritized */}
¿Por qué esta posición?
    {opp.whyPrioritized.map((reason, i) => (
  • {reason}
  • ))}
{/* Metrics */}
Métricas Clave
CV AHT
{opp.cv_aht.toFixed(1)}%
Transfer Rate
{opp.transfer_rate.toFixed(1)}%
FCR
{opp.fcr_rate.toFixed(1)}%
Riesgo
{opp.riskLevel === 'low' ? 'Bajo' : opp.riskLevel === 'medium' ? 'Medio' : 'Alto'}
{/* Next steps */}
{t('opportunityPrioritizer.nextSteps')}
{opp.nextSteps.map((step, i) => ( {i + 1}. {step} ))}
)}
))}
{/* Show more button */} {enrichedOpportunities.length > 5 && ( )}
{/* Methodology note */}
{t('opportunityPrioritizer.methodology')} Las oportunidades se ordenan por potencial de ahorro TCO (volumen × tasa de contención × diferencial CPI). La clasificación de tier (AUTOMATE/ASSIST/AUGMENT) se basa en el Agentic Readiness Score considerando predictibilidad (CV AHT), resolutividad (FCR + Transfer), volumen, calidad de datos y simplicidad del proceso.
); }; export default OpportunityPrioritizer;