Merge pull request #18 from sujucu70/claude/check-agent-readiness-status-Exnpc
feat: translate OpportunityPrioritizer component to English
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
|
||||
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,
|
||||
@@ -115,6 +116,7 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
drilldownData,
|
||||
costPerHour = 20
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [expandedId, setExpandedId] = useState<string | null>(null);
|
||||
const [showAllOpportunities, setShowAllOpportunities] = useState(false);
|
||||
|
||||
@@ -260,9 +262,9 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
<div className="p-6 border-b border-slate-200">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-gray-900">Oportunidades Priorizadas</h2>
|
||||
<h2 className="text-xl font-bold text-gray-900">{t('opportunityPrioritizer.title')}</h2>
|
||||
<p className="text-sm text-gray-500 mt-1">
|
||||
{enrichedOpportunities.length} iniciativas ordenadas por potencial de ahorro y factibilidad
|
||||
{t('opportunityPrioritizer.subtitle', { count: enrichedOpportunities.length })}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -273,50 +275,50 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
<div className="bg-white rounded-lg p-4 border border-slate-200 shadow-sm">
|
||||
<div className="flex items-center gap-2 text-slate-500 text-xs mb-1">
|
||||
<DollarSign size={14} />
|
||||
<span>Ahorro Total Identificado</span>
|
||||
<span>{t('opportunityPrioritizer.totalSavingsIdentified')}</span>
|
||||
</div>
|
||||
<div className="text-3xl font-bold text-slate-800">
|
||||
€{(summary.totalSavings / 1000).toFixed(0)}K
|
||||
</div>
|
||||
<div className="text-xs text-slate-500">anuales</div>
|
||||
<div className="text-xs text-slate-500">{t('opportunityPrioritizer.annual')}</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-emerald-50 rounded-lg p-4 border border-emerald-200 shadow-sm">
|
||||
<div className="flex items-center gap-2 text-emerald-600 text-xs mb-1">
|
||||
<Bot size={14} />
|
||||
<span>Quick Wins (AUTOMATE)</span>
|
||||
<span>{t('opportunityPrioritizer.quickWins')}</span>
|
||||
</div>
|
||||
<div className="text-3xl font-bold text-emerald-700">
|
||||
{summary.byTier.AUTOMATE.length}
|
||||
</div>
|
||||
<div className="text-xs text-emerald-600">
|
||||
€{(summary.byTier.AUTOMATE.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K en 3-6 meses
|
||||
€{(summary.byTier.AUTOMATE.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { count: '3-6' })}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-blue-50 rounded-lg p-4 border border-blue-200 shadow-sm">
|
||||
<div className="flex items-center gap-2 text-blue-600 text-xs mb-1">
|
||||
<Headphones size={14} />
|
||||
<span>Asistencia (ASSIST)</span>
|
||||
<span>{t('opportunityPrioritizer.assistance')}</span>
|
||||
</div>
|
||||
<div className="text-3xl font-bold text-blue-700">
|
||||
{summary.byTier.ASSIST.length}
|
||||
</div>
|
||||
<div className="text-xs text-blue-600">
|
||||
€{(summary.byTier.ASSIST.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K en 6-9 meses
|
||||
€{(summary.byTier.ASSIST.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { count: '6-9' })}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-amber-50 rounded-lg p-4 border border-amber-200 shadow-sm">
|
||||
<div className="flex items-center gap-2 text-amber-600 text-xs mb-1">
|
||||
<BookOpen size={14} />
|
||||
<span>Optimización (AUGMENT)</span>
|
||||
<span>{t('opportunityPrioritizer.optimization')}</span>
|
||||
</div>
|
||||
<div className="text-3xl font-bold text-amber-700">
|
||||
{summary.byTier.AUGMENT.length}
|
||||
</div>
|
||||
<div className="text-xs text-amber-600">
|
||||
€{(summary.byTier.AUGMENT.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K en 9-12 meses
|
||||
€{(summary.byTier.AUGMENT.reduce((s, o) => s + o.savings, 0) / 1000).toFixed(0)}K {t('opportunityPrioritizer.inMonths', { count: '9-12' })}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -326,8 +328,8 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
<div className="p-6 bg-gradient-to-r from-emerald-50 to-green-50 border-b-2 border-emerald-200">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<Sparkles className="text-emerald-600" size={20} />
|
||||
<span className="text-emerald-800 font-bold text-lg">EMPIEZA AQUÍ</span>
|
||||
<span className="bg-emerald-600 text-white text-xs px-2 py-0.5 rounded-full">Prioridad #1</span>
|
||||
<span className="text-emerald-800 font-bold text-lg">{t('opportunityPrioritizer.startHere')}</span>
|
||||
<span className="bg-emerald-600 text-white text-xs px-2 py-0.5 rounded-full">{t('opportunityPrioritizer.priority1')}</span>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl border-2 border-emerald-300 p-6 shadow-lg">
|
||||
@@ -343,7 +345,7 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
{topOpportunity.name.replace(/^[^\w\s]+\s*/, '')}
|
||||
</h3>
|
||||
<span className={`text-sm font-medium ${TIER_CONFIG[topOpportunity.tier].color}`}>
|
||||
{TIER_CONFIG[topOpportunity.tier].label} • {TIER_CONFIG[topOpportunity.tier].description}
|
||||
{t(`opportunityPrioritizer.tierLabels.${topOpportunity.tier.toLowerCase()}`)} • {TIER_CONFIG[topOpportunity.tier].description}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -351,21 +353,21 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
{/* Key metrics */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4">
|
||||
<div className="bg-green-50 rounded-lg p-3">
|
||||
<div className="text-xs text-green-600 mb-1">Ahorro Anual</div>
|
||||
<div className="text-xs text-green-600 mb-1">{t('opportunityPrioritizer.annualSavings')}</div>
|
||||
<div className="text-xl font-bold text-green-700">
|
||||
€{(topOpportunity.savings / 1000).toFixed(0)}K
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-slate-50 rounded-lg p-3">
|
||||
<div className="text-xs text-slate-500 mb-1">Volumen</div>
|
||||
<div className="text-xs text-slate-500 mb-1">{t('opportunityPrioritizer.volume')}</div>
|
||||
<div className="text-xl font-bold text-slate-700">
|
||||
{topOpportunity.volume.toLocaleString()}
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-slate-50 rounded-lg p-3">
|
||||
<div className="text-xs text-slate-500 mb-1">Timeline</div>
|
||||
<div className="text-xs text-slate-500 mb-1">{t('opportunityPrioritizer.timeline')}</div>
|
||||
<div className="text-xl font-bold text-slate-700">
|
||||
{topOpportunity.timelineMonths} meses
|
||||
{topOpportunity.timelineMonths} {t('opportunityPrioritizer.months')}
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-slate-50 rounded-lg p-3">
|
||||
@@ -397,7 +399,7 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
<div className="lg:w-80 bg-emerald-50 rounded-lg p-4 border border-emerald-200">
|
||||
<h4 className="text-sm font-semibold text-emerald-800 mb-3 flex items-center gap-2">
|
||||
<ArrowRight size={14} />
|
||||
Próximos Pasos
|
||||
t("opportunityPrioritizer.nextSteps")
|
||||
</h4>
|
||||
<ol className="space-y-2">
|
||||
{topOpportunity.nextSteps.map((step, i) => (
|
||||
@@ -423,7 +425,7 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
<div className="p-6">
|
||||
<h3 className="text-lg font-bold text-slate-800 mb-4 flex items-center gap-2">
|
||||
<BarChart3 size={20} />
|
||||
Todas las Oportunidades Priorizadas
|
||||
{t('opportunityPrioritizer.allOpportunities')}
|
||||
</h3>
|
||||
|
||||
<div className="space-y-3">
|
||||
@@ -460,18 +462,18 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
{opp.name.replace(/^[^\w\s]+\s*/, '')}
|
||||
</h4>
|
||||
<span className={`text-xs ${TIER_CONFIG[opp.tier].color}`}>
|
||||
{TIER_CONFIG[opp.tier].label} • {TIER_CONFIG[opp.tier].timeline}
|
||||
{t(`opportunityPrioritizer.tierLabels.${opp.tier.toLowerCase()}`)} • {t(`opportunityPrioritizer.timelines.${opp.tier.toLowerCase()}`)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Quick stats */}
|
||||
<div className="hidden md:flex items-center gap-6">
|
||||
<div className="text-right">
|
||||
<div className="text-xs text-slate-500">Ahorro</div>
|
||||
<div className="text-xs text-slate-500">{t('opportunityPrioritizer.savings')}</div>
|
||||
<div className="font-bold text-green-600">€{(opp.savings / 1000).toFixed(0)}K</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="text-xs text-slate-500">Volumen</div>
|
||||
<div className="text-xs text-slate-500">{t('opportunityPrioritizer.volume')}</div>
|
||||
<div className="font-semibold text-slate-700">{opp.volume.toLocaleString()}</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
@@ -482,7 +484,7 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
|
||||
{/* Visual bar: Value vs Effort */}
|
||||
<div className="hidden lg:block w-32">
|
||||
<div className="text-xs text-slate-500 mb-1">Valor / Esfuerzo</div>
|
||||
<div className="text-xs text-slate-500 mb-1">{t('opportunityPrioritizer.valueEffort')}</div>
|
||||
<div className="flex h-2 rounded-full overflow-hidden bg-slate-100">
|
||||
<div
|
||||
className="bg-emerald-500 transition-all"
|
||||
@@ -565,7 +567,7 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
|
||||
{/* Next steps */}
|
||||
<div className="mt-4 pt-4 border-t border-slate-200">
|
||||
<h5 className="text-sm font-semibold text-slate-700 mb-2">Próximos Pasos</h5>
|
||||
<h5 className="text-sm font-semibold text-slate-700 mb-2">{t('opportunityPrioritizer.nextSteps')}</h5>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{opp.nextSteps.map((step, i) => (
|
||||
<span key={i} className="bg-white border border-slate-200 rounded-full px-3 py-1 text-xs text-slate-600">
|
||||
@@ -609,7 +611,7 @@ const OpportunityPrioritizer: React.FC<OpportunityPrioritizerProps> = ({
|
||||
<div className="flex items-start gap-2">
|
||||
<Info size={14} className="flex-shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<strong>Metodología de priorización:</strong> Las oportunidades se ordenan por potencial de ahorro TCO (volumen × tasa de contención × diferencial CPI).
|
||||
<strong>{t('opportunityPrioritizer.methodology')}</strong> 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.
|
||||
</div>
|
||||
|
||||
@@ -1820,5 +1820,41 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"opportunityPrioritizer": {
|
||||
"title": "Prioritized Opportunities",
|
||||
"subtitle": "{{count}} initiatives ordered by savings potential and feasibility",
|
||||
"whereAreOpportunities": "Where are opportunities?",
|
||||
"totalSavingsIdentified": "Total Savings Identified",
|
||||
"annual": "annual",
|
||||
"quickWins": "Quick Wins (AUTOMATE)",
|
||||
"assistance": "Assistance (ASSIST)",
|
||||
"optimization": "Optimization (AUGMENT)",
|
||||
"inMonths": "in {{months}} months",
|
||||
"startHere": "START HERE",
|
||||
"priority1": "Priority #1",
|
||||
"annualSavings": "Annual Savings",
|
||||
"volume": "Volume",
|
||||
"timeline": "Timeline",
|
||||
"months": "months",
|
||||
"nextSteps": "Next Steps",
|
||||
"allOpportunities": "All Prioritized Opportunities",
|
||||
"savings": "Savings",
|
||||
"valueEffort": "Value / Effort",
|
||||
"value": "Value",
|
||||
"effort": "Effort",
|
||||
"viewMore": "View {{count}} more opportunities",
|
||||
"methodology": "Prioritization methodology:",
|
||||
"methodologyDescription": "Opportunities are ordered by TCO savings potential (volume × containment rate × CPI differential). AUTOMATE/ASSIST/AUGMENT tier classification is based on Agentic Readiness Score considering predictability (CV AHT), resolvability (FCR + Transfer), volume, data quality and process simplicity.",
|
||||
"tierLabels": {
|
||||
"automate": "Automate",
|
||||
"assist": "Assist",
|
||||
"augment": "Augment"
|
||||
},
|
||||
"timelines": {
|
||||
"automate": "3-6 months",
|
||||
"assist": "6-9 months",
|
||||
"augment": "9-12 months"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1804,5 +1804,41 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"opportunityPrioritizer": {
|
||||
"title": "Oportunidades Priorizadas",
|
||||
"subtitle": "{{count}} iniciativas ordenadas por potencial de ahorro y factibilidad",
|
||||
"whereAreOpportunities": "¿Dónde están las oportunidades?",
|
||||
"totalSavingsIdentified": "Ahorro Total Identificado",
|
||||
"annual": "anuales",
|
||||
"quickWins": "Quick Wins (AUTOMATE)",
|
||||
"assistance": "Asistencia (ASSIST)",
|
||||
"optimization": "Optimización (AUGMENT)",
|
||||
"inMonths": "en {{count}} meses",
|
||||
"startHere": "EMPIEZA AQUÍ",
|
||||
"priority1": "Prioridad #1",
|
||||
"annualSavings": "Ahorro Anual",
|
||||
"volume": "Volumen",
|
||||
"timeline": "Timeline",
|
||||
"months": "meses",
|
||||
"nextSteps": "Próximos Pasos",
|
||||
"allOpportunities": "Todas las Oportunidades Priorizadas",
|
||||
"savings": "Ahorro",
|
||||
"valueEffort": "Valor / Esfuerzo",
|
||||
"value": "Valor",
|
||||
"effort": "Esfuerzo",
|
||||
"viewMore": "Ver {{count}} oportunidades más",
|
||||
"methodology": "Metodología de priorización:",
|
||||
"methodologyDescription": "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), resolvibilidad (FCR + Transfer), volumen, calidad de datos y simplicidad del proceso.",
|
||||
"tierLabels": {
|
||||
"automate": "Automatizar",
|
||||
"assist": "Asistir",
|
||||
"augment": "Aumentar"
|
||||
},
|
||||
"timelines": {
|
||||
"automate": "3-6 meses",
|
||||
"assist": "6-9 meses",
|
||||
"augment": "9-12 meses"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user