diff --git a/frontend/components/OpportunityPrioritizer.tsx b/frontend/components/OpportunityPrioritizer.tsx index 2b3f5dd..aa5c29e 100644 --- a/frontend/components/OpportunityPrioritizer.tsx +++ b/frontend/components/OpportunityPrioritizer.tsx @@ -58,56 +58,56 @@ interface EnrichedOpportunity extends Opportunity { annualCost?: number; } -// Tier configuration +// Tier configuration - labels and descriptions will be translated at usage time const TIER_CONFIG: Record = { 'AUTOMATE': { icon: , - label: 'Automatizar', + labelKey: 'opportunityPrioritizer.tierLabels.automate', 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' + timelineKey: 'opportunityPrioritizer.timelines.automate', + descriptionKey: 'opportunityPrioritizer.tierDescriptions.automate' }, 'ASSIST': { icon: , - label: 'Asistir', + labelKey: 'opportunityPrioritizer.tierLabels.assist', color: 'text-blue-700', bgColor: 'bg-blue-50', borderColor: 'border-blue-300', savingsRate: '30%', - timeline: '6-9 meses', - description: 'Copilot IA para agentes humanos' + timelineKey: 'opportunityPrioritizer.timelines.assist', + descriptionKey: 'opportunityPrioritizer.tierDescriptions.assist' }, 'AUGMENT': { icon: , - label: 'Optimizar', + labelKey: 'opportunityPrioritizer.tierLabels.augment', 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' + timelineKey: 'opportunityPrioritizer.timelines.augment', + descriptionKey: 'opportunityPrioritizer.tierDescriptions.augment' }, 'HUMAN-ONLY': { icon: , - label: 'Humano', + labelKey: 'opportunityPrioritizer.tierLabels.human', color: 'text-slate-600', bgColor: 'bg-slate-50', borderColor: 'border-slate-300', savingsRate: '0%', - timeline: 'N/A', - description: 'Requiere intervención humana' + timelineKey: 'N/A', + descriptionKey: 'opportunityPrioritizer.tierDescriptions.humanOnly' } }; @@ -177,29 +177,23 @@ const OpportunityPrioritizer: React.FC = ({ // 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 "why" explanation - store keys for translation + const whyPrioritized: { key: string; params?: any }[] = []; + if (opp.savings > 50000) whyPrioritized.push({ key: 'reasons.highSavingsPotential', params: { amount: (opp.savings / 1000).toFixed(0) } }); + if (lookupData?.volume && lookupData.volume > 1000) whyPrioritized.push({ key: 'reasons.highVolume', params: { volume: lookupData.volume.toLocaleString() } }); + if (tier === 'AUTOMATE') whyPrioritized.push({ key: 'reasons.highlyPredictable' }); + if (cv < 60) whyPrioritized.push({ key: 'reasons.lowVariability' }); + if (transfer < 15) whyPrioritized.push({ key: 'reasons.lowTransferRate' }); + if (opp.feasibility >= 7) whyPrioritized.push({ key: 'reasons.highFeasibility' }); - // Generate next steps + // Generate next steps - store keys for translation 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'); + nextSteps.push('steps.automate1', 'steps.automate2', 'steps.automate3'); } 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'); + nextSteps.push('steps.assist1', 'steps.assist2', 'steps.assist3'); } else { - nextSteps.push('Analizar causa raíz de variabilidad'); - nextSteps.push('Estandarizar procesos y scripts'); - nextSteps.push('Capacitar equipo en mejores prácticas'); + nextSteps.push('steps.augment1', 'steps.augment2', 'steps.augment3'); } return { @@ -250,8 +244,8 @@ const OpportunityPrioritizer: React.FC = ({ return (
-

No hay oportunidades identificadas

-

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

+

{t('opportunityPrioritizer.noOpportunitiesTitle')}

+

{t('opportunityPrioritizer.noOpportunitiesDescription')}

); } @@ -292,7 +286,7 @@ const OpportunityPrioritizer: React.FC = ({ {summary.byTier.AUTOMATE.length}
- €{(summary.byTier.AUTOMATE.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { count: '3-6' })} + €{(summary.byTier.AUTOMATE.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { months: '3-6' })}
@@ -305,7 +299,7 @@ const OpportunityPrioritizer: React.FC = ({ {summary.byTier.ASSIST.length}
- €{(summary.byTier.ASSIST.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { count: '6-9' })} + €{(summary.byTier.ASSIST.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { months: '6-9' })}
@@ -318,7 +312,7 @@ const OpportunityPrioritizer: React.FC = ({ {summary.byTier.AUGMENT.length}
- €{(summary.byTier.AUGMENT.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { count: '9-12' })} + €{(summary.byTier.AUGMENT.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { months: '9-12' })}
@@ -345,7 +339,7 @@ const OpportunityPrioritizer: React.FC = ({ {topOpportunity.name.replace(/^[^\w\s]+\s*/, '')} - {t(`opportunityPrioritizer.tierLabels.${topOpportunity.tier.toLowerCase()}`)} • {TIER_CONFIG[topOpportunity.tier].description} + {t(TIER_CONFIG[topOpportunity.tier].labelKey)} • {t(TIER_CONFIG[topOpportunity.tier].descriptionKey)} @@ -371,7 +365,7 @@ const OpportunityPrioritizer: React.FC = ({
-
Agentic Score
+
{t('opportunityPrioritizer.agenticScore')}
{topOpportunity.agenticScore.toFixed(1)}/10
@@ -382,13 +376,13 @@ const OpportunityPrioritizer: React.FC = ({

- ¿Por qué es la prioridad #1? + {t('opportunityPrioritizer.whyPriority1')}

    {topOpportunity.whyPrioritized.slice(0, 4).map((reason, i) => (
  • - {reason} + {t(`opportunityPrioritizer.${reason.key}`, reason.params)}
  • ))}
@@ -399,7 +393,7 @@ const OpportunityPrioritizer: React.FC = ({

- t("opportunityPrioritizer.nextSteps") + {t('opportunityPrioritizer.nextSteps')}

    {topOpportunity.nextSteps.map((step, i) => ( @@ -407,12 +401,12 @@ const OpportunityPrioritizer: React.FC = ({ {i + 1} - {step} + {t(`opportunityPrioritizer.${step}`)} ))}
@@ -462,7 +456,7 @@ const OpportunityPrioritizer: React.FC = ({ {opp.name.replace(/^[^\w\s]+\s*/, '')} - {t(`opportunityPrioritizer.tierLabels.${opp.tier.toLowerCase()}`)} • {t(`opportunityPrioritizer.timelines.${opp.tier.toLowerCase()}`)} + {t(TIER_CONFIG[opp.tier].labelKey)} • {t(TIER_CONFIG[opp.tier].timelineKey)}
@@ -496,8 +490,8 @@ const OpportunityPrioritizer: React.FC = ({ />
- Valor - Esfuerzo + {t('opportunityPrioritizer.value')} + {t('opportunityPrioritizer.effort')}
@@ -525,12 +519,12 @@ const OpportunityPrioritizer: React.FC = ({
{/* Why prioritized */}
-
¿Por qué esta posición?
+
{t('opportunityPrioritizer.whyThisPosition')}
    {opp.whyPrioritized.map((reason, i) => (
  • - {reason} + {t(`opportunityPrioritizer.${reason.key}`, reason.params)}
  • ))}
@@ -538,7 +532,7 @@ const OpportunityPrioritizer: React.FC = ({ {/* Metrics */}
-
Métricas Clave
+
{t('opportunityPrioritizer.keyMetrics')}
CV AHT
@@ -553,12 +547,12 @@ const OpportunityPrioritizer: React.FC = ({
{opp.fcr_rate.toFixed(1)}%
-
Riesgo
+
{t('roadmap.risk')}
- {opp.riskLevel === 'low' ? 'Bajo' : opp.riskLevel === 'medium' ? 'Medio' : 'Alto'} + {t(`roadmap.risk${opp.riskLevel.charAt(0).toUpperCase() + opp.riskLevel.slice(1)}`)}
@@ -571,7 +565,7 @@ const OpportunityPrioritizer: React.FC = ({
{opp.nextSteps.map((step, i) => ( - {i + 1}. {step} + {i + 1}. {t(`opportunityPrioritizer.${step}`)} ))}
@@ -593,12 +587,12 @@ const OpportunityPrioritizer: React.FC = ({ {showAllOpportunities ? ( <> - Mostrar menos + {t('opportunityPrioritizer.showLess')} ) : ( <> - Ver {enrichedOpportunities.length - 5} oportunidades más + {t('opportunityPrioritizer.viewMore', { count: enrichedOpportunities.length - 5 })} )} @@ -611,9 +605,7 @@ const OpportunityPrioritizer: React.FC = ({
- {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. + {t('opportunityPrioritizer.methodology')} {t('opportunityPrioritizer.methodologyDescription')}
diff --git a/frontend/components/tabs/AgenticReadinessTab.tsx b/frontend/components/tabs/AgenticReadinessTab.tsx index 80a2e2c..3305e84 100644 --- a/frontend/components/tabs/AgenticReadinessTab.tsx +++ b/frontend/components/tabs/AgenticReadinessTab.tsx @@ -1558,10 +1558,10 @@ function AgenticReadinessHeader({ {/* Footer con totales */}
- Total: {formatVolume(totalVolume)} interacciones + Total: {formatVolume(totalVolume)} {t('agenticReadiness.summary.interactions')} - {totalQueues} colas analizadas + {totalQueues} {t('agenticReadiness.summary.queuesAnalyzed')}
@@ -2565,7 +2565,7 @@ function TierQueueSection({ {/* Footer */}
- Click en un skill para ver el detalle de colas individuales + {t('agenticReadiness.table.clickToExpand')}
); @@ -2618,9 +2618,9 @@ function HumanOnlyByReasonSection({ drilldownData, redFlagConfigs, t }: { drilld const flagConfig = redFlagConfigs.find(c => c.id === reasonId); return { reasonId, - reason: flagConfig?.label || 'Sin Red Flags específicos', - description: flagConfig?.description || 'Colas que no cumplen criterios de automatización', - action: flagConfig ? getActionForFlag(flagConfig.id) : 'Revisar manualmente', + reason: flagConfig?.label || t('agenticReadiness.redFlagsActions.noSpecificFlags'), + description: flagConfig?.description || t('agenticReadiness.redFlagsActions.noFlagsDesc'), + action: flagConfig ? getActionForFlag(flagConfig.id) : t('agenticReadiness.redFlagsActions.reviewManually'), queues, totalVolume: queues.reduce((s, q) => s + q.volume, 0), queueCount: queues.length @@ -2643,11 +2643,11 @@ function HumanOnlyByReasonSection({ drilldownData, redFlagConfigs, t }: { drilld function getActionForFlag(flagId: string): string { switch (flagId) { - case 'cv_high': return 'Estandarizar procesos y scripts'; - case 'transfer_high': return 'Simplificar flujo, capacitar agentes'; - case 'volume_low': return 'Consolidar con colas similares'; - case 'valid_low': return 'Mejorar captura de datos'; - default: return 'Revisar manualmente'; + case 'cv_high': return t('agenticReadiness.redFlagsActions.standardizeProcesses'); + case 'transfer_high': return t('agenticReadiness.redFlagsActions.simplifyFlow'); + case 'volume_low': return t('agenticReadiness.redFlagsActions.consolidate'); + case 'valid_low': return t('agenticReadiness.redFlagsActions.improveDataCapture'); + default: return t('agenticReadiness.redFlagsActions.reviewManually'); } } @@ -3020,16 +3020,16 @@ function HumanOnlyRedFlagsSection({ drilldownData, redFlagConfigs }: { drilldown let action = ''; switch (config.id) { case 'cv_high': - action = 'Estandarizar procesos'; + action = t('agenticReadiness.redFlagsActions.standardizeProcesses'); break; case 'transfer_high': - action = 'Simplificar flujo / capacitar'; + action = t('agenticReadiness.redFlagsActions.simplifyFlow'); break; case 'volume_low': - action = 'Consolidar con similar'; + action = t('agenticReadiness.redFlagsActions.consolidate'); break; case 'valid_low': - action = 'Mejorar captura datos'; + action = t('agenticReadiness.redFlagsActions.improveDataCapture'); break; } @@ -3057,10 +3057,10 @@ function HumanOnlyRedFlagsSection({ drilldownData, redFlagConfigs }: { drilldown

- Skills con Red Flags + {t('agenticReadiness.redFlagsActions.skillsWithRedFlags')}

- Colas que requieren intervención antes de automatizar + {t('agenticReadiness.redFlagsActions.queuesRequireIntervention')}

👉 - Ver pestaña Roadmap para plan detallado + {t('agenticReadiness.redFlagsActions.viewRoadmapTab')} @@ -3755,7 +3755,7 @@ export function AgenticReadinessTab({ data, onTabChange }: AgenticReadinessTabPr onClick={() => onTabChange('roadmap')} className="text-sm text-blue-600 hover:text-blue-800 hover:underline" > - Ver pestaña Roadmap para plan detallado → + {t('agenticReadiness.redFlagsActions.viewRoadmapLink')} )} diff --git a/frontend/locales/en.json b/frontend/locales/en.json index 0da6f71..8b5367c 100644 --- a/frontend/locales/en.json +++ b/frontend/locales/en.json @@ -1097,7 +1097,11 @@ "standardizeProcesses": "Standardize processes and scripts", "simplifyFlow": "Simplify flow, train agents", "consolidate": "Consolidate with similar queues", - "improveDataCapture": "Improve data capture" + "improveDataCapture": "Improve data capture", + "skillsWithRedFlags": "Skills with Red Flags", + "queuesRequireIntervention": "Queues that require intervention before automating", + "viewRoadmapTab": "View Roadmap tab for detailed plan", + "viewRoadmapLink": "View Roadmap tab for detailed plan →" }, "factorsExtended": { "volumeMethodology": "Score = normalized log10(Volume). >5000 → 10, <100 → 2", @@ -1849,12 +1853,46 @@ "tierLabels": { "automate": "Automate", "assist": "Assist", - "augment": "Augment" + "augment": "Augment", + "human": "Human" }, "timelines": { "automate": "3-6 months", "assist": "6-9 months", "augment": "9-12 months" + }, + "tierDescriptions": { + "automate": "Full automation with AI agents", + "assist": "AI Copilot for human agents", + "augment": "Process standardization and improvement", + "humanOnly": "Requires human intervention" + }, + "agenticScore": "Agentic Score", + "whyPriority1": "Why is this priority #1?", + "viewCompleteDetail": "View Complete Detail", + "showLess": "Show less", + "whyThisPosition": "Why this position?", + "keyMetrics": "Key Metrics", + "noOpportunitiesTitle": "No opportunities identified", + "noOpportunitiesDescription": "Current data doesn't show viable automation opportunities.", + "reasons": { + "highSavingsPotential": "High savings potential (€{{amount}}K/year)", + "highVolume": "High volume ({{volume}} interactions)", + "highlyPredictable": "Highly predictable and repetitive process", + "lowVariability": "Low variability in handling times", + "lowTransferRate": "Low transfer rate", + "highFeasibility": "High technical feasibility" + }, + "steps": { + "automate1": "Define main conversational flows", + "automate2": "Identify necessary integrations (CRM, APIs)", + "automate3": "Create pilot with 10% of volume", + "assist1": "Map agent friction points", + "assist2": "Design contextual suggestions", + "assist3": "Pilot with selected team", + "augment1": "Analyze root cause of variability", + "augment2": "Standardize processes and scripts", + "augment3": "Train team on best practices" } } } \ No newline at end of file diff --git a/frontend/locales/es.json b/frontend/locales/es.json index 986343e..f5c4450 100644 --- a/frontend/locales/es.json +++ b/frontend/locales/es.json @@ -1128,7 +1128,11 @@ "standardizeProcesses": "Estandarizar procesos y scripts", "simplifyFlow": "Simplificar flujo, capacitar agentes", "consolidate": "Consolidar con colas similares", - "improveDataCapture": "Mejorar captura de datos" + "improveDataCapture": "Mejorar captura de datos", + "skillsWithRedFlags": "Skills con Red Flags", + "queuesRequireIntervention": "Colas que requieren intervención antes de automatizar", + "viewRoadmapTab": "Ver pestaña Roadmap para plan detallado", + "viewRoadmapLink": "Ver pestaña Roadmap para plan detallado →" }, "factorsExtended": { "volumeMethodology": "Score = log10(Volumen) normalizado. >5000 → 10, <100 → 2", @@ -1833,12 +1837,46 @@ "tierLabels": { "automate": "Automatizar", "assist": "Asistir", - "augment": "Aumentar" + "augment": "Aumentar", + "human": "Humano" }, "timelines": { "automate": "3-6 meses", "assist": "6-9 meses", "augment": "9-12 meses" + }, + "tierDescriptions": { + "automate": "Automatización completa con agentes IA", + "assist": "Copilot IA para agentes humanos", + "augment": "Estandarización y mejora de procesos", + "humanOnly": "Requiere intervención humana" + }, + "agenticScore": "Puntuación Agéntica", + "whyPriority1": "¿Por qué es la prioridad #1?", + "viewCompleteDetail": "Ver Detalle Completo", + "showLess": "Mostrar menos", + "whyThisPosition": "¿Por qué esta posición?", + "keyMetrics": "Métricas Clave", + "noOpportunitiesTitle": "No hay oportunidades identificadas", + "noOpportunitiesDescription": "Los datos actuales no muestran oportunidades de automatización viables.", + "reasons": { + "highSavingsPotential": "Alto ahorro potencial (€{{amount}}K/año)", + "highVolume": "Alto volumen ({{volume}} interacciones)", + "highlyPredictable": "Proceso altamente predecible y repetitivo", + "lowVariability": "Baja variabilidad en tiempos de gestión", + "lowTransferRate": "Baja tasa de transferencias", + "highFeasibility": "Alta factibilidad técnica" + }, + "steps": { + "automate1": "Definir flujos conversacionales principales", + "automate2": "Identificar integraciones necesarias (CRM, APIs)", + "automate3": "Crear piloto con 10% del volumen", + "assist1": "Mapear puntos de fricción del agente", + "assist2": "Diseñar sugerencias contextuales", + "assist3": "Piloto con equipo seleccionado", + "augment1": "Analizar causa raíz de variabilidad", + "augment2": "Estandarizar procesos y scripts", + "augment3": "Capacitar equipo en mejores prácticas" } } } \ No newline at end of file