refactor: implement i18n in RoadmapTab and Law10Tab (phase 5)
Refactored two major tab components to use react-i18next: RoadmapTab (2,719 lines): - Opportunity bubble chart with all quadrants and methodology - Wave cards with risk levels and strategic recommendations - Tier classification (TIER 1-4) with distribution analysis - Economic impact and feasibility axis labels - 100+ translation keys for visualization and strategy content Law10Tab (1,533 lines): - Spanish regulatory compliance (Ley 10/2025) analysis - All 12 requirements with status evaluations - Time coverage, response speed, resolution quality sections - Compliance messages and action recommendations - 80+ translation keys for regulatory content Added comprehensive translation keys to es.json and en.json: - roadmap section: 100+ keys - law10 section: 80+ keys Build verified successfully. https://claude.ai/code/session_4f888c33-8937-4db8-8a9d-ddc9ac51a725
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
ArrowRight, Info, Users, Target, Zap, Shield,
|
||||
ChevronDown, ChevronUp, BookOpen, Bot, Settings, Rocket, AlertCircle
|
||||
} from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RoadmapPhase } from '../../types';
|
||||
import type { AnalysisData, RoadmapInitiative, HeatmapDataPoint, DrilldownDataPoint, OriginalQueueMetrics, AgenticTier } from '../../types';
|
||||
import {
|
||||
@@ -450,6 +451,8 @@ function OpportunityBubbleChart({
|
||||
heatmapData: HeatmapDataPoint[];
|
||||
drilldownData?: DrilldownDataPoint[]
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
// v3.5: Usar drilldownData si está disponible para tener info de Tier por cola
|
||||
let chartData: BubbleDataPoint[] = [];
|
||||
|
||||
@@ -517,10 +520,10 @@ function OpportunityBubbleChart({
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-800 flex items-center gap-2">
|
||||
<Target className="w-5 h-5 text-[#6D84E3]" />
|
||||
Mapa de Oportunidades por Tier
|
||||
{t('roadmap.opportunityMapTitle')}
|
||||
</h3>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
Factibilidad (Score) vs Impacto Económico (Ahorro TCO) • Tamaño = Volumen • Color = Tier
|
||||
{t('roadmap.opportunityMapSubtitle')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -529,12 +532,12 @@ function OpportunityBubbleChart({
|
||||
<div className="relative" style={{ height: '340px' }}>
|
||||
{/* Y-axis label */}
|
||||
<div className="absolute -left-2 top-1/2 -translate-y-1/2 -rotate-90 text-xs text-gray-600 font-semibold whitespace-nowrap">
|
||||
IMPACTO ECONÓMICO (Ahorro TCO €/año)
|
||||
{t('roadmap.economicImpactAxis')}
|
||||
</div>
|
||||
|
||||
{/* X-axis label */}
|
||||
<div className="absolute bottom-0 left-1/2 -translate-x-1/2 text-xs text-gray-600 font-semibold">
|
||||
FACTIBILIDAD (Agentic Readiness Score 0-10)
|
||||
{t('roadmap.feasibilityAxis')}
|
||||
</div>
|
||||
|
||||
{/* Chart area */}
|
||||
@@ -553,7 +556,7 @@ function OpportunityBubbleChart({
|
||||
style={{ left: `${(7.5 / 10) * 100}%` }}
|
||||
>
|
||||
<span className="absolute -top-5 left-1/2 -translate-x-1/2 text-[9px] text-emerald-600 font-medium whitespace-nowrap">
|
||||
Tier AUTOMATE ≥7.5
|
||||
{t('roadmap.tierAutomateThreshold')}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -566,27 +569,27 @@ function OpportunityBubbleChart({
|
||||
{/* Quadrant labels - basados en Score (X) y Ahorro (Y) */}
|
||||
{/* Top-right: High Score + High Savings = QUICK WINS */}
|
||||
<div className="absolute top-2 right-2 text-xs bg-emerald-100 px-2.5 py-1.5 rounded-lg border-2 border-emerald-400 shadow-sm">
|
||||
<div className="font-bold text-emerald-700">🎯 QUICK WINS</div>
|
||||
<div className="text-[9px] text-emerald-600">Score ≥7.5 + Ahorro alto</div>
|
||||
<div className="text-[9px] text-emerald-500 font-medium">→ Prioridad 1</div>
|
||||
<div className="font-bold text-emerald-700">🎯 {t('roadmap.quadrantQuickWins')}</div>
|
||||
<div className="text-[9px] text-emerald-600">{t('roadmap.quadrantQuickWinsDesc')}</div>
|
||||
<div className="text-[9px] text-emerald-500 font-medium">{t('roadmap.quadrantQuickWinsPriority')}</div>
|
||||
</div>
|
||||
{/* Top-left: Low Score + High Savings = OPTIMIZE */}
|
||||
<div className="absolute top-2 left-2 text-xs bg-amber-100 px-2.5 py-1.5 rounded-lg border-2 border-amber-400 shadow-sm">
|
||||
<div className="font-bold text-amber-700">⚙️ OPTIMIZE</div>
|
||||
<div className="text-[9px] text-amber-600">Score <7.5 + Ahorro alto</div>
|
||||
<div className="text-[9px] text-amber-500 font-medium">→ Wave 1 primero</div>
|
||||
<div className="font-bold text-amber-700">⚙️ {t('roadmap.quadrantOptimize')}</div>
|
||||
<div className="text-[9px] text-amber-600">{t('roadmap.quadrantOptimizeDesc')}</div>
|
||||
<div className="text-[9px] text-amber-500 font-medium">{t('roadmap.quadrantOptimizePriority')}</div>
|
||||
</div>
|
||||
{/* Bottom-right: High Score + Low Savings = STRATEGIC */}
|
||||
<div className="absolute bottom-10 right-2 text-xs bg-blue-100 px-2.5 py-1.5 rounded-lg border-2 border-blue-400 shadow-sm">
|
||||
<div className="font-bold text-blue-700">📊 STRATEGIC</div>
|
||||
<div className="text-[9px] text-blue-600">Score ≥7.5 + Ahorro bajo</div>
|
||||
<div className="text-[9px] text-blue-500 font-medium">→ Evaluar ROI</div>
|
||||
<div className="font-bold text-blue-700">📊 {t('roadmap.quadrantStrategic')}</div>
|
||||
<div className="text-[9px] text-blue-600">{t('roadmap.quadrantStrategicDesc')}</div>
|
||||
<div className="text-[9px] text-blue-500 font-medium">{t('roadmap.quadrantStrategicPriority')}</div>
|
||||
</div>
|
||||
{/* Bottom-left: Low Score + Low Savings = DEFER */}
|
||||
<div className="absolute bottom-10 left-2 text-xs bg-gray-100 px-2.5 py-1.5 rounded-lg border-2 border-gray-300 shadow-sm">
|
||||
<div className="font-bold text-gray-600">📋 DEFER</div>
|
||||
<div className="text-[9px] text-gray-500">Score <7.5 + Ahorro bajo</div>
|
||||
<div className="text-[9px] text-gray-400 font-medium">→ Backlog</div>
|
||||
<div className="font-bold text-gray-600">📋 {t('roadmap.quadrantDefer')}</div>
|
||||
<div className="text-[9px] text-gray-500">{t('roadmap.quadrantDeferDesc')}</div>
|
||||
<div className="text-[9px] text-gray-400 font-medium">{t('roadmap.quadrantDeferPriority')}</div>
|
||||
</div>
|
||||
|
||||
{/* Bubbles */}
|
||||
@@ -629,19 +632,19 @@ function OpportunityBubbleChart({
|
||||
<div className="font-semibold text-sm">{item.name}</div>
|
||||
<div className="mt-1 space-y-0.5">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-gray-400">Score:</span>
|
||||
<span className="text-gray-400">{t('roadmap.tooltipScore')}</span>
|
||||
<span className="font-medium">{item.feasibility.toFixed(1)}/10</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-gray-400">Volumen:</span>
|
||||
<span className="font-medium">{item.volume.toLocaleString()}/mes</span>
|
||||
<span className="text-gray-400">{t('roadmap.tooltipVolume')}</span>
|
||||
<span className="font-medium">{item.volume.toLocaleString()}{t('roadmap.perMonth')}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-gray-400">Ahorro TCO:</span>
|
||||
<span className="font-medium text-emerald-400">{formatCurrency(item.economicImpact)}/año</span>
|
||||
<span className="text-gray-400">{t('roadmap.tooltipSavingsTco')}</span>
|
||||
<span className="font-medium text-emerald-400">{formatCurrency(item.economicImpact)}{t('roadmap.perYear')}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 pt-1 border-t border-gray-600">
|
||||
<span className="text-gray-400">Tier:</span>
|
||||
<span className="text-gray-400">{t('roadmap.tooltipTier')}</span>
|
||||
<span
|
||||
className="px-1.5 py-0.5 rounded text-[10px] font-medium"
|
||||
style={{ backgroundColor: tierColor.fill }}
|
||||
@@ -705,12 +708,11 @@ function OpportunityBubbleChart({
|
||||
{/* Leyenda por Tier */}
|
||||
<div className="mt-4 p-3 bg-gray-50 rounded-lg border border-gray-200">
|
||||
<p className="text-xs text-gray-700 mb-2">
|
||||
<span className="font-semibold" style={{ color: '#6d84e3' }}>Interpretación:</span> Las burbujas en el cuadrante superior derecho (Score alto + Ahorro alto)
|
||||
son Quick Wins para automatización. El tamaño indica volumen de interacciones.
|
||||
<span className="font-semibold" style={{ color: '#6d84e3' }}>{t('roadmap.interpretation')}</span> {t('roadmap.opportunityMapInterpretation')}
|
||||
</p>
|
||||
<div className="flex flex-wrap items-center gap-4 text-[10px] text-gray-600 pt-2 border-t border-gray-200">
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="font-medium">Tamaño:</span> Volumen
|
||||
<span className="font-medium">{t('roadmap.bubbleSize')}</span> {t('roadmap.volume')}
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="w-3 h-3 rounded-full" style={{ backgroundColor: TIER_COLORS.AUTOMATE.fill }} />
|
||||
@@ -735,29 +737,29 @@ function OpportunityBubbleChart({
|
||||
<div className="mt-4 p-4 bg-white rounded-lg border border-gray-300 shadow-sm">
|
||||
<h4 className="text-sm font-semibold text-gray-800 mb-3 flex items-center gap-2">
|
||||
<Info className="w-4 h-4 text-[#6D84E3]" />
|
||||
Metodología de Cálculo
|
||||
{t('roadmap.methodologyTitle')}
|
||||
</h4>
|
||||
|
||||
{/* Ejes */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
||||
<div className="p-3 bg-gray-50 rounded border border-gray-200">
|
||||
<h5 className="text-xs font-semibold text-gray-700 mb-2">📊 Eje X: FACTIBILIDAD (Score 0-10)</h5>
|
||||
<h5 className="text-xs font-semibold text-gray-700 mb-2">📊 {t('roadmap.axisXFactibility')}</h5>
|
||||
<p className="text-[11px] text-gray-600 mb-2">
|
||||
Score Agentic Readiness calculado con 5 factores ponderados:
|
||||
{t('roadmap.axisXFactibilityDesc')}
|
||||
</p>
|
||||
<ul className="text-[10px] text-gray-500 space-y-1 ml-2">
|
||||
<li>• <strong>Predictibilidad (30%)</strong>: basado en CV AHT</li>
|
||||
<li>• <strong>Resolutividad (25%)</strong>: FCR (60%) + Transfer (40%)</li>
|
||||
<li>• <strong>Volumen (25%)</strong>: escala logarítmica del volumen</li>
|
||||
<li>• <strong>Calidad Datos (10%)</strong>: % registros válidos</li>
|
||||
<li>• <strong>Simplicidad (10%)</strong>: basado en AHT</li>
|
||||
<li>• <strong>{t('roadmap.factorPredictability')}</strong>: {t('roadmap.factorPredictabilityDesc')}</li>
|
||||
<li>• <strong>{t('roadmap.factorResolution')}</strong>: {t('roadmap.factorResolutionDesc')}</li>
|
||||
<li>• <strong>{t('roadmap.factorVolumeWeight')}</strong>: {t('roadmap.factorVolumeDesc')}</li>
|
||||
<li>• <strong>{t('roadmap.factorDataQuality')}</strong>: {t('roadmap.factorDataQualityDesc')}</li>
|
||||
<li>• <strong>{t('roadmap.factorSimplicity')}</strong>: {t('roadmap.factorSimplicityDesc')}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="p-3 bg-gray-50 rounded border border-gray-200">
|
||||
<h5 className="text-xs font-semibold text-gray-700 mb-2">💰 Eje Y: IMPACTO ECONÓMICO (€/año)</h5>
|
||||
<h5 className="text-xs font-semibold text-gray-700 mb-2">💰 {t('roadmap.axisYEconomicImpact')}</h5>
|
||||
<p className="text-[11px] text-gray-600 mb-2">
|
||||
Ahorro TCO calculado según tier con CPI diferencial:
|
||||
{t('roadmap.axisYEconomicImpactDesc')}
|
||||
</p>
|
||||
<div className="text-[10px] text-gray-500 space-y-1 ml-2">
|
||||
<p className="font-mono bg-gray-100 px-1 py-0.5 rounded text-[9px]">
|
||||
@@ -778,49 +780,49 @@ function OpportunityBubbleChart({
|
||||
|
||||
{/* Fórmulas por Tier */}
|
||||
<div className="p-3 bg-gradient-to-r from-slate-50 to-white rounded border border-gray-200">
|
||||
<h5 className="text-xs font-semibold text-gray-700 mb-3">🧮 Fórmulas de Ahorro por Tier</h5>
|
||||
<h5 className="text-xs font-semibold text-gray-700 mb-3">🧮 {t('roadmap.savingsFormulas')}</h5>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 text-[10px]">
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-3 h-3 rounded-full flex-shrink-0 mt-0.5" style={{ backgroundColor: TIER_COLORS.AUTOMATE.fill }} />
|
||||
<div>
|
||||
<p className="font-semibold text-emerald-700">AUTOMATE (Score ≥ 7.5)</p>
|
||||
<p className="font-semibold text-emerald-700">{t('roadmap.formulaAutomate')}</p>
|
||||
<p className="font-mono text-gray-600 mt-0.5">
|
||||
Ahorro = Vol × 12 × <strong>70%</strong> × (€2.33 - €0.15)
|
||||
{t('roadmap.formulaAutomateCalc')}
|
||||
</p>
|
||||
<p className="text-gray-500">= Vol × 12 × 0.70 × €2.18</p>
|
||||
<p className="text-gray-500">{t('roadmap.formulaAutomateResult')}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-3 h-3 rounded-full flex-shrink-0 mt-0.5" style={{ backgroundColor: TIER_COLORS.ASSIST.fill }} />
|
||||
<div>
|
||||
<p className="font-semibold text-blue-700">ASSIST (Score ≥ 5.5)</p>
|
||||
<p className="font-semibold text-blue-700">{t('roadmap.formulaAssist')}</p>
|
||||
<p className="font-mono text-gray-600 mt-0.5">
|
||||
Ahorro = Vol × 12 × <strong>30%</strong> × (€2.33 - €1.50)
|
||||
{t('roadmap.formulaAssistCalc')}
|
||||
</p>
|
||||
<p className="text-gray-500">= Vol × 12 × 0.30 × €0.83</p>
|
||||
<p className="text-gray-500">{t('roadmap.formulaAssistResult')}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-3 h-3 rounded-full flex-shrink-0 mt-0.5" style={{ backgroundColor: TIER_COLORS.AUGMENT.fill }} />
|
||||
<div>
|
||||
<p className="font-semibold text-amber-700">AUGMENT (Score ≥ 3.5)</p>
|
||||
<p className="font-semibold text-amber-700">{t('roadmap.formulaAugment')}</p>
|
||||
<p className="font-mono text-gray-600 mt-0.5">
|
||||
Ahorro = Vol × 12 × <strong>15%</strong> × (€2.33 - €2.00)
|
||||
{t('roadmap.formulaAugmentCalc')}
|
||||
</p>
|
||||
<p className="text-gray-500">= Vol × 12 × 0.15 × €0.33</p>
|
||||
<p className="text-gray-500">{t('roadmap.formulaAugmentResult')}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-2">
|
||||
<div className="w-3 h-3 rounded-full flex-shrink-0 mt-0.5" style={{ backgroundColor: TIER_COLORS['HUMAN-ONLY'].fill }} />
|
||||
<div>
|
||||
<p className="font-semibold text-red-700">HUMAN-ONLY (Score < 3.5 o Red Flags)</p>
|
||||
<p className="font-semibold text-red-700">{t('roadmap.formulaHumanOnly')}</p>
|
||||
<p className="font-mono text-gray-600 mt-0.5">
|
||||
Ahorro = <strong>€0</strong>
|
||||
{t('roadmap.formulaHumanOnlyCalc')}
|
||||
</p>
|
||||
<p className="text-gray-500">Requiere estandarización previa</p>
|
||||
<p className="text-gray-500">{t('roadmap.formulaHumanOnlyRequires')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -828,7 +830,7 @@ function OpportunityBubbleChart({
|
||||
|
||||
{/* Clasificación de Tier */}
|
||||
<div className="mt-3 p-3 bg-gray-50 rounded border border-gray-200">
|
||||
<h5 className="text-xs font-semibold text-gray-700 mb-2">🏷️ Criterios de Clasificación de Tier</h5>
|
||||
<h5 className="text-xs font-semibold text-gray-700 mb-2">🏷️ {t('roadmap.tierClassificationCriteria')}</h5>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-2 text-[10px]">
|
||||
<div className="p-2 bg-emerald-50 rounded border border-emerald-200">
|
||||
<p className="font-semibold text-emerald-700">AUTOMATE</p>
|
||||
@@ -871,9 +873,7 @@ function OpportunityBubbleChart({
|
||||
|
||||
{/* Nota metodológica */}
|
||||
<p className="text-[10px] text-gray-500 mt-3 italic">
|
||||
<strong>Nota:</strong> El tamaño de las burbujas representa el volumen de interacciones.
|
||||
Las colas clasificadas como HUMAN-ONLY no aparecen en el gráfico (ahorro = €0).
|
||||
Los ahorros son proyecciones basadas en benchmarks de industria y deben validarse con pilotos.
|
||||
<strong>{t('roadmap.methodologicalNote')}</strong> {t('roadmap.methodologicalNoteText')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -954,6 +954,7 @@ function WaveCard({
|
||||
exitCriteria?: WaveExitCriteria;
|
||||
priorityQueues?: PriorityQueue[];
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [expanded, setExpanded] = React.useState(false);
|
||||
|
||||
const margenAnual = wave.ahorroAnual - wave.costoRecurrenteAnual;
|
||||
@@ -990,7 +991,7 @@ function WaveCard({
|
||||
<h3 className="font-bold text-gray-800">{wave.titulo}</h3>
|
||||
{wave.esCondicional && (
|
||||
<span className="text-[10px] bg-amber-200 text-amber-800 px-2 py-0.5 rounded-full font-medium">
|
||||
Condicional
|
||||
{t('roadmap.conditional')}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -998,7 +999,7 @@ function WaveCard({
|
||||
</div>
|
||||
</div>
|
||||
<span className={`text-xs px-2 py-1 rounded-full font-medium ${riesgoColors[wave.riesgo]}`}>
|
||||
{riesgoIcons[wave.riesgo]} Riesgo {wave.riesgo}
|
||||
{riesgoIcons[wave.riesgo]} {t('roadmap.risk')} {t(`roadmap.risk${wave.riesgo.charAt(0).toUpperCase() + wave.riesgo.slice(1)}`)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1056,7 +1057,7 @@ function WaveCard({
|
||||
|
||||
{/* Por qué es necesario */}
|
||||
<div className="p-3 bg-gray-50 rounded-lg border border-gray-100">
|
||||
<p className="text-xs text-gray-500 font-medium mb-1">🎯 Por qué es necesario:</p>
|
||||
<p className="text-xs text-gray-500 font-medium mb-1">🎯 {t('roadmap.whyNecessary')}</p>
|
||||
<p className="text-sm text-gray-700">{wave.porQueNecesario}</p>
|
||||
</div>
|
||||
|
||||
@@ -1169,7 +1170,7 @@ function WaveCard({
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
className="w-full text-sm text-gray-500 hover:text-gray-700 flex items-center justify-center gap-1 py-2 border-t border-gray-100"
|
||||
>
|
||||
{expanded ? 'Ocultar detalles' : 'Ver iniciativas y criterios'}
|
||||
{expanded ? t('roadmap.hideDetails') : t('roadmap.viewInitiatives')}
|
||||
{expanded ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
|
||||
</button>
|
||||
|
||||
@@ -1678,6 +1679,8 @@ function RoadmapTimeline({ waves }: { waves: WaveData[] }) {
|
||||
// ========== COMPONENTE PRINCIPAL: ROADMAP TAB ==========
|
||||
|
||||
export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
// Analizar datos de heatmap para determinar skills listos
|
||||
const heatmapData = data.heatmapData || [];
|
||||
|
||||
@@ -2266,10 +2269,10 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
<div className="px-5 py-4 border-b border-gray-200">
|
||||
<h3 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<Target className="w-5 h-5 text-blue-600" />
|
||||
Clasificación por Potencial de Automatización
|
||||
{t('roadmap.classificationByAutomationTier')}
|
||||
</h3>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
{totalQueues} colas clasificadas en 4 Tiers según su preparación para IA • {totalVolume.toLocaleString()} interacciones/mes
|
||||
{t('roadmap.queuesClassifiedDescription', { count: totalQueues, volume: totalVolume.toLocaleString() })}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -2283,20 +2286,20 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
<Rocket className="w-4 h-4 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[10px] text-emerald-600 font-medium">TIER 1</p>
|
||||
<p className="text-[10px] text-emerald-600 font-medium">{t('roadmap.tier1')}</p>
|
||||
<p className="text-xs font-bold text-emerald-800">AUTOMATE</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p className="text-2xl font-bold text-emerald-700">{tierCounts.AUTOMATE.length}</p>
|
||||
<p className="text-[10px] text-emerald-600">
|
||||
{tierVolumes.AUTOMATE.toLocaleString()} int/mes
|
||||
{tierVolumes.AUTOMATE.toLocaleString()} {t('roadmap.intPerMonth')}
|
||||
</p>
|
||||
<p className="text-[10px] text-emerald-500">
|
||||
({Math.round((tierVolumes.AUTOMATE / totalVolume) * 100)}% volumen)
|
||||
{t('roadmap.volumePercentage', { pct: Math.round((tierVolumes.AUTOMATE / totalVolume) * 100) })}
|
||||
</p>
|
||||
<p className="text-xs font-semibold text-emerald-700 pt-1 border-t border-emerald-200">
|
||||
{formatCurrency(potentialSavings.AUTOMATE)}/año
|
||||
{formatCurrency(potentialSavings.AUTOMATE)}{t('roadmap.perYear')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2308,20 +2311,20 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
<Bot className="w-4 h-4 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[10px] text-blue-600 font-medium">TIER 2</p>
|
||||
<p className="text-[10px] text-blue-600 font-medium">{t('roadmap.tier2')}</p>
|
||||
<p className="text-xs font-bold text-blue-800">ASSIST</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p className="text-2xl font-bold text-blue-700">{tierCounts.ASSIST.length}</p>
|
||||
<p className="text-[10px] text-blue-600">
|
||||
{tierVolumes.ASSIST.toLocaleString()} int/mes
|
||||
{tierVolumes.ASSIST.toLocaleString()} {t('roadmap.intPerMonth')}
|
||||
</p>
|
||||
<p className="text-[10px] text-blue-500">
|
||||
({Math.round((tierVolumes.ASSIST / totalVolume) * 100)}% volumen)
|
||||
{t('roadmap.volumePercentage', { pct: Math.round((tierVolumes.ASSIST / totalVolume) * 100) })}
|
||||
</p>
|
||||
<p className="text-xs font-semibold text-blue-700 pt-1 border-t border-blue-200">
|
||||
{formatCurrency(potentialSavings.ASSIST)}/año
|
||||
{formatCurrency(potentialSavings.ASSIST)}{t('roadmap.perYear')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2333,20 +2336,20 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
<TrendingUp className="w-4 h-4 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[10px] text-amber-600 font-medium">TIER 3</p>
|
||||
<p className="text-[10px] text-amber-600 font-medium">{t('roadmap.tier3')}</p>
|
||||
<p className="text-xs font-bold text-amber-800">AUGMENT</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p className="text-2xl font-bold text-amber-700">{tierCounts.AUGMENT.length}</p>
|
||||
<p className="text-[10px] text-amber-600">
|
||||
{tierVolumes.AUGMENT.toLocaleString()} int/mes
|
||||
{tierVolumes.AUGMENT.toLocaleString()} {t('roadmap.intPerMonth')}
|
||||
</p>
|
||||
<p className="text-[10px] text-amber-500">
|
||||
({Math.round((tierVolumes.AUGMENT / totalVolume) * 100)}% volumen)
|
||||
{t('roadmap.volumePercentage', { pct: Math.round((tierVolumes.AUGMENT / totalVolume) * 100) })}
|
||||
</p>
|
||||
<p className="text-xs font-semibold text-amber-700 pt-1 border-t border-amber-200">
|
||||
{formatCurrency(potentialSavings.AUGMENT)}/año
|
||||
{formatCurrency(potentialSavings.AUGMENT)}{t('roadmap.perYear')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2358,20 +2361,20 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
<Users className="w-4 h-4 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-[10px] text-red-600 font-medium">TIER 4</p>
|
||||
<p className="text-[10px] text-red-600 font-medium">{t('roadmap.tier4')}</p>
|
||||
<p className="text-xs font-bold text-red-800">HUMAN-ONLY</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p className="text-2xl font-bold text-red-700">{tierCounts['HUMAN-ONLY'].length}</p>
|
||||
<p className="text-[10px] text-red-600">
|
||||
{tierVolumes['HUMAN-ONLY'].toLocaleString()} int/mes
|
||||
{tierVolumes['HUMAN-ONLY'].toLocaleString()} {t('roadmap.intPerMonth')}
|
||||
</p>
|
||||
<p className="text-[10px] text-red-500">
|
||||
({Math.round((tierVolumes['HUMAN-ONLY'] / totalVolume) * 100)}% volumen)
|
||||
{t('roadmap.volumePercentage', { pct: Math.round((tierVolumes['HUMAN-ONLY'] / totalVolume) * 100) })}
|
||||
</p>
|
||||
<p className="text-xs font-semibold text-red-700 pt-1 border-t border-red-200">
|
||||
€0/año (Red flags)
|
||||
{t('roadmap.noSavingsRedFlags')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2379,7 +2382,7 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
|
||||
{/* Barra de distribución visual */}
|
||||
<div className="bg-white rounded-lg p-3 border border-gray-200">
|
||||
<p className="text-xs text-gray-500 font-medium mb-2">Distribución del volumen por tier:</p>
|
||||
<p className="text-xs text-gray-500 font-medium mb-2">{t('roadmap.volumeDistributionByTier')}</p>
|
||||
<div className="h-6 rounded-full overflow-hidden flex">
|
||||
{tierVolumes.AUTOMATE > 0 && (
|
||||
<div
|
||||
@@ -2501,16 +2504,16 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
// Configuración simplificada por tipo
|
||||
const typeConfig = {
|
||||
DUAL: {
|
||||
label: 'Nuestra Recomendación: Estrategia Dual',
|
||||
sublabel: 'Ejecutar dos líneas de trabajo en paralelo para maximizar el impacto'
|
||||
label: t('roadmap.dualStrategyLabel'),
|
||||
sublabel: t('roadmap.dualStrategySublabel')
|
||||
},
|
||||
FOUNDATION: {
|
||||
label: 'Nuestra Recomendación: Foundation First',
|
||||
sublabel: 'Preparar la operación antes de automatizar'
|
||||
label: t('roadmap.foundationFirstLabel'),
|
||||
sublabel: t('roadmap.foundationFirstSublabel')
|
||||
},
|
||||
STANDARDIZATION: {
|
||||
label: 'Nuestra Recomendación: Estandarización',
|
||||
sublabel: 'Resolver problemas operativos críticos antes de invertir en IA'
|
||||
label: t('roadmap.standardizationLabel'),
|
||||
sublabel: t('roadmap.standardizationSublabel')
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2543,35 +2546,32 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
<>
|
||||
{/* Explicación */}
|
||||
<div className="p-3 bg-gray-50 rounded-lg mb-3">
|
||||
<p className="font-semibold text-gray-800 mb-1">¿Qué significa Foundation?</p>
|
||||
<p className="font-semibold text-gray-800 mb-1">{t('roadmap.whatIsFoundation')}</p>
|
||||
<p className="text-xs text-gray-600">
|
||||
La operación actual no tiene colas listas para automatizar directamente.
|
||||
Foundation es la fase de preparación: estandarizar procesos, reducir variabilidad
|
||||
y mejorar la calidad de datos para que la automatización posterior sea efectiva.
|
||||
{t('roadmap.foundationExplanation')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm text-gray-600 mb-3">
|
||||
{tierCounts.ASSIST.length} colas ASSIST ({Math.round(assistPct)}% del volumen)
|
||||
pueden elevarse a Tier AUTOMATE tras completar Wave 1-2.
|
||||
{t('roadmap.assistQueuesCanElevate', { count: tierCounts.ASSIST.length, pct: Math.round(assistPct) })}
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4 text-sm border-t border-gray-100 pt-3">
|
||||
<div>
|
||||
<p className="text-xs text-gray-500">Inversión</p>
|
||||
<p className="text-xs text-gray-500">{t('roadmap.investment')}</p>
|
||||
<p className="font-semibold text-gray-800">{formatCurrency(wave1Setup + wave2Setup)}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs text-gray-500">Timeline</p>
|
||||
<p className="font-semibold text-gray-800">6-9 meses</p>
|
||||
<p className="text-xs text-gray-500">{t('roadmap.timeline')}</p>
|
||||
<p className="font-semibold text-gray-800">6-9 {t('roadmap.months', { count: 6 }).toLowerCase()}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs text-gray-500">Ahorro habilitado</p>
|
||||
<p className="font-semibold text-gray-800">{formatCurrency(potentialSavings.ASSIST)}/año</p>
|
||||
<p className="text-xs text-gray-500">{t('roadmap.enabledSavings')}</p>
|
||||
<p className="font-semibold text-gray-800">{formatCurrency(potentialSavings.ASSIST)}{t('roadmap.perYear')}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 border-t border-gray-100 pt-3 mt-3">
|
||||
<strong className="text-gray-700">Criterios para pasar a automatización:</strong> CV ≤90% · Transfer ≤30% · AHT -15%
|
||||
<strong className="text-gray-700">{t('roadmap.criteriaForAutomation')}</strong> {t('roadmap.criteriaForAutomationValues')}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
@@ -2581,51 +2581,48 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
<>
|
||||
{/* Explicación */}
|
||||
<div className="p-3 bg-gray-50 rounded-lg mb-3">
|
||||
<p className="font-semibold text-gray-800 mb-1">¿Por qué estandarización primero?</p>
|
||||
<p className="font-semibold text-gray-800 mb-1">{t('roadmap.whyStandardizationFirst')}</p>
|
||||
<p className="text-xs text-gray-600">
|
||||
Se han detectado "red flags" operativos críticos (alta variabilidad, muchas transferencias)
|
||||
que harían fracasar cualquier proyecto de automatización. Invertir en IA ahora sería
|
||||
malgastar recursos. Primero hay que estabilizar la operación.
|
||||
{t('roadmap.standardizationExplanation')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p className="text-sm text-gray-600 mb-3">
|
||||
{Math.round(humanOnlyPct + augmentPct)}% del volumen presenta red flags (CV >75%, Transfer >20%).
|
||||
Wave 1 es una inversión habilitadora sin retorno directo inmediato.
|
||||
{t('roadmap.volumeWithRedFlags', { pct: Math.round(humanOnlyPct + augmentPct) })}
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4 text-sm border-t border-gray-100 pt-3">
|
||||
<div>
|
||||
<p className="text-xs text-gray-500">Inversión Wave 1</p>
|
||||
<p className="text-xs text-gray-500">{t('roadmap.investmentWave1')}</p>
|
||||
<p className="font-semibold text-gray-800">{formatCurrency(wave1Setup)}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs text-gray-500">Timeline</p>
|
||||
<p className="font-semibold text-gray-800">3-4 meses</p>
|
||||
<p className="text-xs text-gray-500">{t('roadmap.timeline')}</p>
|
||||
<p className="font-semibold text-gray-800">3-4 {t('roadmap.months', { count: 3 }).toLowerCase()}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs text-gray-500">Ahorro directo</p>
|
||||
<p className="font-semibold text-gray-500">€0 (habilitador)</p>
|
||||
<p className="text-xs text-gray-500">{t('roadmap.directSavings')}</p>
|
||||
<p className="font-semibold text-gray-500">{t('roadmap.enablingNoDirectSavings')}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 border-t border-gray-100 pt-3 mt-3">
|
||||
<strong className="text-gray-700">Objetivo:</strong> Reducir red flags en las {Math.min(10, tierCounts['HUMAN-ONLY'].length + tierCounts.AUGMENT.length)} colas principales. Reevaluar tras completar.
|
||||
<strong className="text-gray-700">{t('roadmap.objective')}</strong> {t('roadmap.objectiveReduceRedFlags', { count: Math.min(10, tierCounts['HUMAN-ONLY'].length + tierCounts.AUGMENT.length) })}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Siguiente paso */}
|
||||
<div className="border-t border-gray-200 pt-3 mt-3">
|
||||
<p className="text-xs text-gray-500 mb-1">Siguiente paso recomendado:</p>
|
||||
<p className="text-xs text-gray-500 mb-1">{t('roadmap.nextRecommendedStep')}</p>
|
||||
<p className="text-sm text-gray-700">
|
||||
{recType === 'DUAL' && (
|
||||
<>Iniciar piloto de automatización con las {pilotQueues.length} colas AUTOMATE, mientras se ejecuta Wave 1 (Foundation) en paralelo para preparar el resto.</>
|
||||
t('roadmap.nextStepDual', { count: pilotQueues.length })
|
||||
)}
|
||||
{recType === 'FOUNDATION' && (
|
||||
<>Comenzar Wave 1 focalizando en las {Math.min(10, tierCounts['HUMAN-ONLY'].length)} colas de mayor volumen. Medir progreso mensual en CV y Transfer.</>
|
||||
t('roadmap.nextStepFoundation', { count: Math.min(10, tierCounts['HUMAN-ONLY'].length) })
|
||||
)}
|
||||
{recType === 'STANDARDIZATION' && (
|
||||
<>Realizar workshop de diagnóstico operacional para identificar las causas raíz de los red flags antes de planificar inversiones.</>
|
||||
t('roadmap.nextStepStandardization')
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
@@ -2653,13 +2650,13 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
<div className="flex items-center gap-3">
|
||||
<BookOpen className="w-5 h-5 text-blue-500" />
|
||||
<div className="text-left">
|
||||
<h3 className="font-semibold text-gray-800">Detalle por Wave</h3>
|
||||
<p className="text-xs text-gray-500">Iniciativas, criterios de entrada/salida, inversión por fase</p>
|
||||
<h3 className="font-semibold text-gray-800">{t('roadmap.waveDetail')}</h3>
|
||||
<p className="text-xs text-gray-500">{t('roadmap.waveDetailDescription')}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs text-gray-400">
|
||||
{waveDetailExpanded ? 'Ocultar detalle' : 'Ver detalle'}
|
||||
{waveDetailExpanded ? t('roadmap.hideDetail') : t('roadmap.viewDetail')}
|
||||
</span>
|
||||
{waveDetailExpanded ? (
|
||||
<ChevronUp className="w-5 h-5 text-gray-400" />
|
||||
@@ -2678,7 +2675,7 @@ export function RoadmapTab({ data }: RoadmapTabProps) {
|
||||
onClick={() => setShowAllWaves(!showAllWaves)}
|
||||
className="text-xs text-blue-600 hover:text-blue-800 font-medium flex items-center gap-1"
|
||||
>
|
||||
{showAllWaves ? 'Colapsar todas' : 'Expandir todas'}
|
||||
{showAllWaves ? t('roadmap.collapseAll') : t('roadmap.expandAll')}
|
||||
{showAllWaves ? <ChevronUp className="w-3 h-3" /> : <ChevronDown className="w-3 h-3" />}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user