Merge pull request #12 from sujucu70/claude/check-agent-readiness-status-Exnpc
Claude/check agent readiness status exnpc
This commit is contained in:
@@ -221,13 +221,31 @@ const getTierExplanations = (t: any): TierExplanation[] => [
|
||||
function AgenticMethodologyIntro({
|
||||
tierData,
|
||||
totalVolume,
|
||||
totalQueues
|
||||
totalQueues,
|
||||
t
|
||||
}: {
|
||||
tierData: TierDataType;
|
||||
totalVolume: number;
|
||||
totalQueues: number;
|
||||
t: any;
|
||||
}) {
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const componentRef = React.useRef<HTMLDivElement>(null);
|
||||
const tierExplanations = getTierExplanations(t);
|
||||
|
||||
// Close when clicking outside
|
||||
React.useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (isExpanded && componentRef.current && !componentRef.current.contains(event.target as Node)) {
|
||||
setIsExpanded(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (isExpanded) {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||
}
|
||||
}, [isExpanded]);
|
||||
|
||||
// Calcular estadísticas para el roadmap
|
||||
const automatizableQueues = tierData.AUTOMATE.count + tierData.ASSIST.count;
|
||||
@@ -239,6 +257,7 @@ function AgenticMethodologyIntro({
|
||||
: 0;
|
||||
|
||||
return (
|
||||
<div ref={componentRef}>
|
||||
<Card padding="none">
|
||||
{/* Header con toggle */}
|
||||
<div
|
||||
@@ -252,10 +271,10 @@ function AgenticMethodologyIntro({
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
¿Qué es el Índice de Agentic Readiness?
|
||||
{t('agenticReadiness.methodology.title')}
|
||||
</h2>
|
||||
<p className="text-sm text-gray-600 mt-0.5">
|
||||
Metodología de evaluación y guía de navegación de este análisis
|
||||
{t('agenticReadiness.methodology.subtitle')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -276,38 +295,36 @@ function AgenticMethodologyIntro({
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2">
|
||||
<Brain className="w-4 h-4 text-blue-600" />
|
||||
Definición del Índice
|
||||
{t('agenticReadiness.methodology.definition')}
|
||||
</h3>
|
||||
<div className="bg-gray-50 rounded-lg p-4">
|
||||
<p className="text-sm text-gray-700 mb-3">
|
||||
El <strong>Índice de Agentic Readiness</strong> evalúa qué porcentaje del volumen de interacciones
|
||||
está preparado para ser gestionado por agentes virtuales o asistido por IA. Se calcula
|
||||
analizando cada cola individualmente según 5 factores clave:
|
||||
{t('agenticReadiness.methodology.definitionDesc')}
|
||||
</p>
|
||||
<div className="grid grid-cols-1 md:grid-cols-5 gap-2 text-xs">
|
||||
<div className="bg-white rounded p-2 border border-gray-200">
|
||||
<div className="font-bold text-blue-600">Predictibilidad</div>
|
||||
<div className="text-gray-500">30% peso</div>
|
||||
<div className="font-bold text-blue-600">{t('agenticReadiness.methodology.factor1')}</div>
|
||||
<div className="text-gray-500">{t('agenticReadiness.methodology.factor1Desc')}</div>
|
||||
<div className="text-gray-600 mt-1">CV AHT <75%</div>
|
||||
</div>
|
||||
<div className="bg-white rounded p-2 border border-gray-200">
|
||||
<div className="font-bold text-blue-600">Resolutividad</div>
|
||||
<div className="text-gray-500">25% peso</div>
|
||||
<div className="font-bold text-blue-600">{t('agenticReadiness.methodology.factor2')}</div>
|
||||
<div className="text-gray-500">{t('agenticReadiness.methodology.factor2Desc')}</div>
|
||||
<div className="text-gray-600 mt-1">FCR alto, Transfer bajo</div>
|
||||
</div>
|
||||
<div className="bg-white rounded p-2 border border-gray-200">
|
||||
<div className="font-bold text-blue-600">Volumen</div>
|
||||
<div className="text-gray-500">25% peso</div>
|
||||
<div className="font-bold text-blue-600">{t('agenticReadiness.methodology.factor3')}</div>
|
||||
<div className="text-gray-500">{t('agenticReadiness.methodology.factor3Desc')}</div>
|
||||
<div className="text-gray-600 mt-1">ROI positivo >500/mes</div>
|
||||
</div>
|
||||
<div className="bg-white rounded p-2 border border-gray-200">
|
||||
<div className="font-bold text-blue-600">Calidad Datos</div>
|
||||
<div className="text-gray-500">10% peso</div>
|
||||
<div className="font-bold text-blue-600">{t('agenticReadiness.methodology.factor4')}</div>
|
||||
<div className="text-gray-500">{t('agenticReadiness.methodology.factor4Desc')}</div>
|
||||
<div className="text-gray-600 mt-1">% registros válidos</div>
|
||||
</div>
|
||||
<div className="bg-white rounded p-2 border border-gray-200">
|
||||
<div className="font-bold text-blue-600">Simplicidad</div>
|
||||
<div className="text-gray-500">10% peso</div>
|
||||
<div className="font-bold text-blue-600">{t('agenticReadiness.methodology.factor5')}</div>
|
||||
<div className="text-gray-500">{t('agenticReadiness.methodology.factor5Desc')}</div>
|
||||
<div className="text-gray-600 mt-1">AHT bajo, proceso simple</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -318,13 +335,13 @@ function AgenticMethodologyIntro({
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2">
|
||||
<BarChart2 className="w-4 h-4 text-blue-600" />
|
||||
Las 4 Categorías de Clasificación
|
||||
{t('agenticReadiness.methodology.categories')}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 mb-3">
|
||||
Cada cola se clasifica en uno de los siguientes tiers según su score compuesto:
|
||||
{t('agenticReadiness.methodology.categoriesDesc')}
|
||||
</p>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
{TIER_EXPLANATIONS.map(tier => (
|
||||
{tierExplanations.map(tier => (
|
||||
<div
|
||||
key={tier.tier}
|
||||
className="rounded-lg border p-3"
|
||||
@@ -351,11 +368,11 @@ function AgenticMethodologyIntro({
|
||||
<div>
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2">
|
||||
<Target className="w-4 h-4 text-blue-600" />
|
||||
Contenido de este Análisis
|
||||
{t('agenticReadiness.methodology.content')}
|
||||
</h3>
|
||||
<div className="bg-blue-50 rounded-lg p-4 border border-blue-100">
|
||||
<p className="text-sm text-gray-700 mb-4">
|
||||
Este tab presenta el análisis de automatización en el siguiente orden:
|
||||
{t('agenticReadiness.methodology.contentDesc')}
|
||||
</p>
|
||||
|
||||
<div className="space-y-3">
|
||||
@@ -365,10 +382,9 @@ function AgenticMethodologyIntro({
|
||||
1
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">Visión Global de Distribución</div>
|
||||
<div className="font-medium text-gray-900">{t('agenticReadiness.methodology.globalVision')}</div>
|
||||
<p className="text-xs text-gray-600">
|
||||
Porcentaje de volumen en cada categoría ({automatizablePct}% automatizable).
|
||||
Las 4 cajas muestran cómo se distribuyen las {totalVolume.toLocaleString()} interacciones.
|
||||
{t('agenticReadiness.methodology.globalVisionDesc', { pct: automatizablePct, total: totalVolume.toLocaleString() })}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -380,14 +396,13 @@ function AgenticMethodologyIntro({
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">
|
||||
Candidatos Prioritarios
|
||||
{t('agenticReadiness.methodology.priorityCandidates')}
|
||||
<span className="ml-2 text-xs px-2 py-0.5 rounded-full bg-emerald-100 text-emerald-700">
|
||||
{automatizableQueues} colas
|
||||
{automatizableQueues} {t('agenticReadiness.table.queues')}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-gray-600">
|
||||
Colas AUTOMATE y ASSIST ordenadas por potencial de ahorro.
|
||||
Quick wins con mayor ROI para priorizar en el roadmap.
|
||||
{t('agenticReadiness.methodology.priorityCandidatesDesc')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -399,14 +414,13 @@ function AgenticMethodologyIntro({
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">
|
||||
Colas a Optimizar
|
||||
{t('agenticReadiness.methodology.queuesToOptimize')}
|
||||
<span className="ml-2 text-xs px-2 py-0.5 rounded-full bg-amber-100 text-amber-700">
|
||||
{optimizableQueues} colas
|
||||
{optimizableQueues} {t('agenticReadiness.table.queues')}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-gray-600">
|
||||
Tier AUGMENT: requieren estandarización previa (reducir variabilidad,
|
||||
mejorar FCR, documentar procesos) antes de automatizar.
|
||||
{t('agenticReadiness.methodology.queuesToOptimizeDesc')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -418,14 +432,13 @@ function AgenticMethodologyIntro({
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">
|
||||
No Automatizables
|
||||
{t('agenticReadiness.methodology.notAutomatable')}
|
||||
<span className="ml-2 text-xs px-2 py-0.5 rounded-full bg-gray-100 text-gray-700">
|
||||
{humanOnlyQueues} colas
|
||||
{humanOnlyQueues} {t('agenticReadiness.table.queues')}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-gray-600">
|
||||
Tier HUMAN-ONLY: volumen insuficiente (ROI negativo), calidad de datos baja,
|
||||
variabilidad extrema, o complejidad que requiere juicio humano.
|
||||
{t('agenticReadiness.methodology.notAutomatableDesc')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -435,9 +448,7 @@ function AgenticMethodologyIntro({
|
||||
|
||||
{/* Nota metodológica */}
|
||||
<div className="text-xs text-gray-500 border-t border-gray-200 pt-4">
|
||||
<strong>Nota metodológica:</strong> El índice se calcula por cola individual, no como promedio global.
|
||||
Esto permite identificar oportunidades específicas incluso cuando la media operativa sea baja.
|
||||
Los umbrales están calibrados según benchmarks de industria (COPC, Gartner).
|
||||
{t('agenticReadiness.methodology.methodNote')}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -445,15 +456,16 @@ function AgenticMethodologyIntro({
|
||||
{/* Mini resumen cuando está colapsado */}
|
||||
{!isExpanded && (
|
||||
<div className="px-5 py-3 bg-gray-50 text-xs text-gray-600 flex items-center gap-4 flex-wrap">
|
||||
<span><strong>5 factores</strong> ponderados</span>
|
||||
<span><strong>{t('agenticReadiness.methodology.factors5')}</strong></span>
|
||||
<span>→</span>
|
||||
<span><strong>4 categorías</strong> de clasificación</span>
|
||||
<span><strong>{t('agenticReadiness.methodology.categories4')}</strong></span>
|
||||
<span>→</span>
|
||||
<span><strong>{totalQueues} colas</strong> analizadas</span>
|
||||
<span className="ml-auto text-blue-600 font-medium">Click para expandir metodología</span>
|
||||
<span><strong>{totalQueues} {t('agenticReadiness.summary.queuesAnalyzed')}</strong></span>
|
||||
<span className="ml-auto text-blue-600 font-medium">{t('agenticReadiness.methodology.clickToExpand')}</span>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -470,83 +482,95 @@ interface FactorConfig {
|
||||
implications: { high: string; low: string };
|
||||
}
|
||||
|
||||
const FACTOR_CONFIGS: FactorConfig[] = [
|
||||
const getFactorConfigs = (t: any): FactorConfig[] => [
|
||||
{
|
||||
id: 'predictibilidad',
|
||||
title: 'Predictibilidad',
|
||||
title: t('agenticReadiness.factorConfigs.predictability.title'),
|
||||
weight: 0.30,
|
||||
icon: Brain,
|
||||
color: '#6D84E3',
|
||||
description: 'Consistencia en tiempos de gestión',
|
||||
methodology: 'Score = 10 - (CV_AHT / 10). CV AHT < 30% → Score > 7',
|
||||
benchmark: 'CV AHT óptimo < 25%',
|
||||
implications: { high: 'Tiempos consistentes, ideal para IA', low: 'Requiere estandarización' }
|
||||
description: t('agenticReadiness.factorConfigs.predictability.description'),
|
||||
methodology: t('agenticReadiness.factorConfigs.predictability.methodology'),
|
||||
benchmark: t('agenticReadiness.factorConfigs.predictability.benchmark'),
|
||||
implications: {
|
||||
high: t('agenticReadiness.factorConfigs.predictability.highImplication'),
|
||||
low: t('agenticReadiness.factorConfigs.predictability.lowImplication')
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'complejidad_inversa',
|
||||
title: 'Simplicidad',
|
||||
title: t('agenticReadiness.factorConfigs.inverseComplexity.title'),
|
||||
weight: 0.20,
|
||||
icon: Zap,
|
||||
color: '#10B981',
|
||||
description: 'Bajo nivel de juicio humano requerido',
|
||||
methodology: 'Score = 10 - (Tasa_Transfer × 0.4). Transfer <10% → Score > 6',
|
||||
benchmark: 'Transferencias óptimas <10%',
|
||||
implications: { high: 'Procesos simples, automatizables', low: 'Alta complejidad, requiere copilot' }
|
||||
description: t('agenticReadiness.factorConfigs.inverseComplexity.description'),
|
||||
methodology: t('agenticReadiness.factorConfigs.inverseComplexity.methodology'),
|
||||
benchmark: t('agenticReadiness.factorConfigs.inverseComplexity.benchmark'),
|
||||
implications: {
|
||||
high: t('agenticReadiness.factorConfigs.inverseComplexity.highImplication'),
|
||||
low: t('agenticReadiness.factorConfigs.inverseComplexity.lowImplication')
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'repetitividad',
|
||||
title: 'Volumen',
|
||||
title: t('agenticReadiness.factorConfigs.repeatability.title'),
|
||||
weight: 0.25,
|
||||
icon: Repeat,
|
||||
color: '#F59E0B',
|
||||
description: 'Escala para justificar inversión',
|
||||
methodology: 'Score = log10(Volumen) normalizado. >5000 → 10, <100 → 2',
|
||||
benchmark: 'ROI positivo requiere >500/mes',
|
||||
implications: { high: 'Alto volumen justifica inversión', low: 'Considerar soluciones compartidas' }
|
||||
description: t('agenticReadiness.factorConfigs.repeatability.description'),
|
||||
methodology: t('agenticReadiness.factorConfigs.repeatability.methodology'),
|
||||
benchmark: t('agenticReadiness.factorConfigs.repeatability.benchmark'),
|
||||
implications: {
|
||||
high: t('agenticReadiness.factorConfigs.repeatability.highImplication'),
|
||||
low: t('agenticReadiness.factorConfigs.repeatability.lowImplication')
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'roi_potencial',
|
||||
title: 'ROI Potencial',
|
||||
title: t('agenticReadiness.factorConfigs.roiPotential.title'),
|
||||
weight: 0.25,
|
||||
icon: TrendingUp,
|
||||
color: '#8B5CF6',
|
||||
description: 'Retorno económico esperado',
|
||||
methodology: 'Score basado en coste anual total. >€500K → 10',
|
||||
benchmark: 'ROI >150% a 12 meses',
|
||||
implications: { high: 'Caso de negocio sólido', low: 'ROI marginal, evaluar otros beneficios' }
|
||||
description: t('agenticReadiness.factorConfigs.roiPotential.description'),
|
||||
methodology: t('agenticReadiness.factorConfigs.roiPotential.methodology'),
|
||||
benchmark: t('agenticReadiness.factorConfigs.roiPotential.benchmark'),
|
||||
implications: {
|
||||
high: t('agenticReadiness.factorConfigs.roiPotential.highImplication'),
|
||||
low: t('agenticReadiness.factorConfigs.roiPotential.lowImplication')
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// v3.4: Helper para obtener estilo de Tier
|
||||
function getTierStyle(tier: AgenticTier): { bg: string; text: string; icon: React.ReactNode; label: string } {
|
||||
function getTierStyle(tier: AgenticTier, t: any): { bg: string; text: string; icon: React.ReactNode; label: string } {
|
||||
switch (tier) {
|
||||
case 'AUTOMATE':
|
||||
return {
|
||||
bg: 'bg-emerald-100',
|
||||
text: 'text-emerald-700',
|
||||
icon: <Sparkles className="w-3 h-3" />,
|
||||
label: 'Automatizar'
|
||||
label: t('agenticReadiness.tiers.automate')
|
||||
};
|
||||
case 'ASSIST':
|
||||
return {
|
||||
bg: 'bg-blue-100',
|
||||
text: 'text-blue-700',
|
||||
icon: <Bot className="w-3 h-3" />,
|
||||
label: 'Asistir'
|
||||
label: t('agenticReadiness.tiers.assist')
|
||||
};
|
||||
case 'AUGMENT':
|
||||
return {
|
||||
bg: 'bg-amber-100',
|
||||
text: 'text-amber-700',
|
||||
icon: <TrendingUp className="w-3 h-3" />,
|
||||
label: 'Optimizar'
|
||||
label: t('agenticReadiness.tiers.optimize')
|
||||
};
|
||||
case 'HUMAN-ONLY':
|
||||
return {
|
||||
bg: 'bg-gray-100',
|
||||
text: 'text-gray-600',
|
||||
icon: <Users className="w-3 h-3" />,
|
||||
label: 'Humano'
|
||||
label: t('agenticReadiness.tiers.human')
|
||||
};
|
||||
default:
|
||||
return {
|
||||
@@ -559,27 +583,27 @@ function getTierStyle(tier: AgenticTier): { bg: string; text: string; icon: Reac
|
||||
}
|
||||
|
||||
// v3.4: Componente de desglose de score
|
||||
function ScoreBreakdownTooltip({ breakdown }: { breakdown: AgenticScoreBreakdown }) {
|
||||
function ScoreBreakdownTooltip({ breakdown, t }: { breakdown: AgenticScoreBreakdown; t: any }) {
|
||||
return (
|
||||
<div className="text-xs space-y-1">
|
||||
<div className="flex justify-between gap-4">
|
||||
<span>Predictibilidad (30%)</span>
|
||||
<span>{t('agenticReadiness.scoreBreakdown.predictability')}</span>
|
||||
<span className="font-medium">{breakdown.predictibilidad.toFixed(1)}</span>
|
||||
</div>
|
||||
<div className="flex justify-between gap-4">
|
||||
<span>Resolutividad (25%)</span>
|
||||
<span>{t('agenticReadiness.scoreBreakdown.resolution')}</span>
|
||||
<span className="font-medium">{breakdown.resolutividad.toFixed(1)}</span>
|
||||
</div>
|
||||
<div className="flex justify-between gap-4">
|
||||
<span>Volumen (25%)</span>
|
||||
<span>{t('agenticReadiness.scoreBreakdown.volume')}</span>
|
||||
<span className="font-medium">{breakdown.volumen.toFixed(1)}</span>
|
||||
</div>
|
||||
<div className="flex justify-between gap-4">
|
||||
<span>Calidad Datos (10%)</span>
|
||||
<span>{t('agenticReadiness.scoreBreakdown.dataQuality')}</span>
|
||||
<span className="font-medium">{breakdown.calidadDatos.toFixed(1)}</span>
|
||||
</div>
|
||||
<div className="flex justify-between gap-4">
|
||||
<span>Simplicidad (10%)</span>
|
||||
<span>{t('agenticReadiness.scoreBreakdown.simplicity')}</span>
|
||||
<span className="font-medium">{breakdown.simplicidad.toFixed(1)}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -651,14 +675,15 @@ function calculateFactorsFromData(heatmapData: HeatmapDataPoint[]): { id: string
|
||||
}
|
||||
|
||||
// Calculate weighted global score from factors
|
||||
function calculateWeightedScore(factors: { id: string; score: number }[]): number {
|
||||
function calculateWeightedScore(factors: { id: string; score: number }[], t: any): number {
|
||||
if (factors.length === 0) return 5;
|
||||
|
||||
const factorConfigs = getFactorConfigs(t);
|
||||
let weightedSum = 0;
|
||||
let totalWeight = 0;
|
||||
|
||||
for (const factor of factors) {
|
||||
const config = FACTOR_CONFIGS.find(c => c.id === factor.id);
|
||||
const config = factorConfigs.find(c => c.id === factor.id);
|
||||
if (config) {
|
||||
weightedSum += factor.score * config.weight;
|
||||
totalWeight += config.weight;
|
||||
@@ -741,7 +766,7 @@ interface BubbleData {
|
||||
}
|
||||
|
||||
// Componente del Bubble Chart de Oportunidades
|
||||
function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDataPoint[] }) {
|
||||
function OpportunityBubbleChart({ drilldownData, t }: { drilldownData: DrilldownDataPoint[]; t: any }) {
|
||||
// Estados para filtros
|
||||
const [tierFilter, setTierFilter] = useState<'Todos' | AgenticTier>('Todos');
|
||||
const [minAhorro, setMinAhorro] = useState<number>(0);
|
||||
@@ -894,35 +919,35 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
<Target className="w-5 h-5 flex-shrink-0" style={{ color: COLORS.primary }} />
|
||||
<h3 className="font-bold text-sm sm:text-base truncate" style={{ color: COLORS.dark }}>
|
||||
Mapa de Oportunidades
|
||||
{t('agenticReadiness.opportunityMap.title')}
|
||||
</h3>
|
||||
</div>
|
||||
<span className="text-xs px-2 py-1 rounded-full font-medium flex-shrink-0" style={{ backgroundColor: COLORS.primary, color: 'white' }}>
|
||||
{bubbleData.length} colas
|
||||
{bubbleData.length} {t('agenticReadiness.volumeLabels.queues')}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-[10px] sm:text-xs mt-1" style={{ color: COLORS.medium }}>
|
||||
Tamaño = Volumen · Color = Tier · Posición = Score vs Ahorro TCO
|
||||
{t('agenticReadiness.opportunityMap.subtitle')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Filtros */}
|
||||
<div className="px-3 sm:px-4 py-2 border-b border-gray-100 flex flex-wrap gap-2 sm:gap-4 items-center bg-gray-50/50">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-medium" style={{ color: COLORS.dark }}>Tier:</span>
|
||||
<span className="text-xs font-medium" style={{ color: COLORS.dark }}>{t('agenticReadiness.filters.tier')}</span>
|
||||
<select
|
||||
value={tierFilter}
|
||||
onChange={(e) => setTierFilter(e.target.value as 'Todos' | AgenticTier)}
|
||||
className="text-xs border border-gray-200 rounded px-2 py-1"
|
||||
>
|
||||
<option value="Todos">Todos</option>
|
||||
<option value="Todos">{t('agenticReadiness.filters.all')}</option>
|
||||
<option value="AUTOMATE">AUTOMATE</option>
|
||||
<option value="ASSIST">ASSIST</option>
|
||||
<option value="AUGMENT">AUGMENT</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-medium" style={{ color: COLORS.dark }}>Ahorro mín:</span>
|
||||
<span className="text-xs font-medium" style={{ color: COLORS.dark }}>{t('agenticReadiness.filters.minSavings')}</span>
|
||||
<select
|
||||
value={minAhorro}
|
||||
onChange={(e) => setMinAhorro(Number(e.target.value))}
|
||||
@@ -935,7 +960,7 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
</select>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-xs font-medium" style={{ color: COLORS.dark }}>Volumen mín:</span>
|
||||
<span className="text-xs font-medium" style={{ color: COLORS.dark }}>{t('agenticReadiness.filters.minVolume')}</span>
|
||||
<select
|
||||
value={minVolumen}
|
||||
onChange={(e) => setMinVolumen(Number(e.target.value))}
|
||||
@@ -951,12 +976,12 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
{/* v3.12: Indicador de filtros activos con resumen de cuadrantes */}
|
||||
{hasActiveFilters && (
|
||||
<div className="ml-auto flex items-center gap-2 text-xs bg-amber-50 text-amber-700 px-2 py-1 rounded border border-amber-200">
|
||||
<span className="font-medium">Filtros activos:</span>
|
||||
{minAhorro > 0 && <span>Ahorro ≥€{minAhorro >= 1000 ? `${minAhorro/1000}K` : minAhorro}</span>}
|
||||
<span className="font-medium">{t('agenticReadiness.bubbleChart.activeFiltersLabel')}</span>
|
||||
{minAhorro > 0 && <span>{t('agenticReadiness.filters.minSavings')} ≥€{minAhorro >= 1000 ? `${minAhorro/1000}K` : minAhorro}</span>}
|
||||
{minVolumen > 0 && <span>Vol ≥{minVolumen >= 1000 ? `${minVolumen/1000}K` : minVolumen}</span>}
|
||||
{tierFilter !== 'Todos' && <span>Tier: {tierFilter}</span>}
|
||||
<span className="text-amber-500">|</span>
|
||||
<span>{quadrantStats.total} de {allQueues.filter(q => q.tier !== 'HUMAN-ONLY').length} colas</span>
|
||||
<span>{quadrantStats.total} {t('agenticReadiness.bubbleChart.ofQueues', { total: allQueues.filter(q => q.tier !== 'HUMAN-ONLY').length })}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -1026,33 +1051,33 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
{/* v3.12: Etiquetas de cuadrante sincronizadas con filtros */}
|
||||
{/* Quick Wins (top-right) */}
|
||||
<text x={automateThresholdX + 10} y={15} fontSize={10} fill="#059669" fontWeight="bold">
|
||||
🎯 QUICK WINS
|
||||
🎯 {t('agenticReadiness.bubbleChart.quickWinsLabel')}
|
||||
</text>
|
||||
<text x={automateThresholdX + 10} y={28} fontSize={9} fill="#059669">
|
||||
{quadrantStats.quickWins.count} colas · {formatCurrency(quadrantStats.quickWins.ahorro)}
|
||||
{quadrantStats.quickWins.count} {t('agenticReadiness.volumeLabels.queues')} · {formatCurrency(quadrantStats.quickWins.ahorro)}
|
||||
</text>
|
||||
|
||||
{/* Alto Potencial (top-center) */}
|
||||
<text x={assistThresholdX + 10} y={15} fontSize={10} fill="#4f63b8" fontWeight="bold">
|
||||
⚡ ALTO POTENCIAL
|
||||
⚡ {t('agenticReadiness.bubbleChart.highPotentialLabel')}
|
||||
</text>
|
||||
<text x={assistThresholdX + 10} y={28} fontSize={9} fill="#4f63b8">
|
||||
{quadrantStats.highPotential.count} colas · {formatCurrency(quadrantStats.highPotential.ahorro)}
|
||||
{quadrantStats.highPotential.count} {t('agenticReadiness.volumeLabels.queues')} · {formatCurrency(quadrantStats.highPotential.ahorro)}
|
||||
</text>
|
||||
|
||||
{/* Desarrollar / Nurture (left column) */}
|
||||
<text x={10} y={15} fontSize={10} fill="#92400e" fontWeight="bold">
|
||||
📈 DESARROLLAR
|
||||
📈 {t('agenticReadiness.bubbleChart.developLabel')}
|
||||
</text>
|
||||
<text x={10} y={28} fontSize={9} fill="#92400e">
|
||||
{quadrantStats.nurture.count} colas · {formatCurrency(quadrantStats.nurture.ahorro)}
|
||||
{quadrantStats.nurture.count} {t('agenticReadiness.volumeLabels.queues')} · {formatCurrency(quadrantStats.nurture.ahorro)}
|
||||
</text>
|
||||
|
||||
{/* Low Hanging Fruit (bottom-right) - Fácil pero bajo ahorro */}
|
||||
{quadrantStats.lowHanging.count > 0 && (
|
||||
<>
|
||||
<text x={automateThresholdX + 10} y={innerHeight * 0.75 + 15} fontSize={9} fill="#6b7280" fontWeight="medium">
|
||||
✅ FÁCIL IMPL.
|
||||
✅ {t('agenticReadiness.bubbleChart.easyImplLabel')}
|
||||
</text>
|
||||
<text x={automateThresholdX + 10} y={innerHeight * 0.75 + 27} fontSize={8} fill="#9ca3af">
|
||||
{quadrantStats.lowHanging.count} · {formatCurrency(quadrantStats.lowHanging.ahorro)}
|
||||
@@ -1064,7 +1089,7 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
{quadrantStats.backlog.count > 0 && (
|
||||
<>
|
||||
<text x={assistThresholdX + 10} y={innerHeight * 0.75 + 15} fontSize={9} fill="#6b7280" fontWeight="medium">
|
||||
📋 BACKLOG
|
||||
📋 {t('agenticReadiness.bubbleChart.backlogLabel')}
|
||||
</text>
|
||||
<text x={assistThresholdX + 10} y={innerHeight * 0.75 + 27} fontSize={8} fill="#9ca3af">
|
||||
{quadrantStats.backlog.count} · {formatCurrency(quadrantStats.backlog.ahorro)}
|
||||
@@ -1095,7 +1120,7 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
);
|
||||
})}
|
||||
<text x={innerWidth / 2} y={innerHeight + 38} textAnchor="middle" fontSize={11} fill={COLORS.dark} fontWeight="medium">
|
||||
Agentic Score
|
||||
{t('agenticReadiness.opportunityMap.agenticScore')}
|
||||
</text>
|
||||
|
||||
{/* Eje Y */}
|
||||
@@ -1122,7 +1147,7 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
fontWeight="medium"
|
||||
transform={`rotate(-90, -45, ${innerHeight / 2})`}
|
||||
>
|
||||
Ahorro TCO Anual
|
||||
{t('agenticReadiness.opportunityMap.annualTcoSavings')}
|
||||
</text>
|
||||
|
||||
{/* Burbujas */}
|
||||
@@ -1165,7 +1190,7 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
{/* Mensaje si no hay datos */}
|
||||
{bubbleData.length === 0 && (
|
||||
<text x={innerWidth / 2} y={innerHeight / 2} textAnchor="middle" fontSize={14} fill={COLORS.medium}>
|
||||
No hay colas que cumplan los filtros seleccionados
|
||||
{t('agenticReadiness.bubbleChart.noQueuesFilters')}
|
||||
</text>
|
||||
)}
|
||||
</g>
|
||||
@@ -1192,19 +1217,19 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
</div>
|
||||
<div className="space-y-1 text-xs">
|
||||
<div className="flex justify-between">
|
||||
<span style={{ color: COLORS.medium }}>Score:</span>
|
||||
<span style={{ color: COLORS.medium }}>{t('agenticReadiness.table.score')}:</span>
|
||||
<span className="font-semibold" style={{ color: COLORS.dark }}>{hoveredBubble.score.toFixed(1)}</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span style={{ color: COLORS.medium }}>Volumen:</span>
|
||||
<span className="font-semibold" style={{ color: COLORS.dark }}>{formatVolume(hoveredBubble.volume)}/mes</span>
|
||||
<span style={{ color: COLORS.medium }}>{t('agenticReadiness.table.volume')}:</span>
|
||||
<span className="font-semibold" style={{ color: COLORS.dark }}>{formatVolume(hoveredBubble.volume)}{t('agenticReadiness.bubbleChart.perMonth')}</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span style={{ color: COLORS.medium }}>Ahorro:</span>
|
||||
<span className="font-semibold text-emerald-600">{formatCurrency(hoveredBubble.ahorro)}/año</span>
|
||||
<span style={{ color: COLORS.medium }}>{t('agenticReadiness.table.savings')}:</span>
|
||||
<span className="font-semibold text-emerald-600">{formatCurrency(hoveredBubble.ahorro)}{t('agenticReadiness.table.perYear')}</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span style={{ color: COLORS.medium }}>CV AHT:</span>
|
||||
<span style={{ color: COLORS.medium }}>{t('agenticReadiness.bubbleChart.cvAht')}</span>
|
||||
<span className={`font-semibold ${hoveredBubble.cv > 120 ? 'text-red-500' : hoveredBubble.cv > 75 ? 'text-amber-500' : 'text-emerald-500'}`}>
|
||||
{hoveredBubble.cv.toFixed(0)}%
|
||||
</span>
|
||||
@@ -1215,7 +1240,7 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-[10px] text-center mt-2 pt-2 border-t border-gray-100" style={{ color: COLORS.medium }}>
|
||||
Click para ver detalle
|
||||
{t('agenticReadiness.bubbleChart.viewDetail')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -1226,7 +1251,7 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
<div className="flex flex-wrap justify-between gap-4">
|
||||
{/* Leyenda de colores */}
|
||||
<div>
|
||||
<p className="text-[10px] font-bold mb-1.5" style={{ color: COLORS.dark }}>COLOR = TIER</p>
|
||||
<p className="text-[10px] font-bold mb-1.5" style={{ color: COLORS.dark }}>{t('agenticReadiness.opportunityMap.colorTier')}</p>
|
||||
<div className="flex gap-3">
|
||||
{(['AUTOMATE', 'ASSIST', 'AUGMENT'] as AgenticTier[]).map(tier => (
|
||||
<div key={tier} className="flex items-center gap-1">
|
||||
@@ -1244,7 +1269,7 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
|
||||
{/* Leyenda de tamaños */}
|
||||
<div>
|
||||
<p className="text-[10px] font-bold mb-1.5" style={{ color: COLORS.dark }}>TAMAÑO = VOLUMEN</p>
|
||||
<p className="text-[10px] font-bold mb-1.5" style={{ color: COLORS.dark }}>{t('agenticReadiness.opportunityMap.sizeVolume')}</p>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="w-2 h-2 rounded-full bg-gray-400" />
|
||||
@@ -1285,7 +1310,7 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
</span>
|
||||
)}
|
||||
<span className="text-gray-400">
|
||||
= {quadrantStats.total} total
|
||||
= {quadrantStats.total} {t('agenticReadiness.bubbleChart.total')}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -1379,11 +1404,13 @@ function OpportunityBubbleChart({ drilldownData }: { drilldownData: DrilldownDat
|
||||
function AgenticReadinessHeader({
|
||||
tierData,
|
||||
totalVolume,
|
||||
totalQueues
|
||||
totalQueues,
|
||||
t
|
||||
}: {
|
||||
tierData: TierDataType;
|
||||
totalVolume: number;
|
||||
totalQueues: number;
|
||||
t: any;
|
||||
}) {
|
||||
// Calcular volumen automatizable (AUTOMATE + ASSIST)
|
||||
const automatizableVolume = tierData.AUTOMATE.volume + tierData.ASSIST.volume;
|
||||
@@ -1406,10 +1433,10 @@ function AgenticReadinessHeader({
|
||||
|
||||
// Tier card config con colores consistentes con la sección introductoria
|
||||
const tierConfigs = [
|
||||
{ key: 'AUTOMATE', label: 'AUTOMATE', emoji: '🤖', sublabel: 'Full IA', color: '#10b981', bgColor: '#d1fae5' },
|
||||
{ key: 'ASSIST', label: 'ASSIST', emoji: '🤝', sublabel: 'Copilot', color: '#3b82f6', bgColor: '#dbeafe' },
|
||||
{ key: 'AUGMENT', label: 'AUGMENT', emoji: '📚', sublabel: 'Tools', color: '#f59e0b', bgColor: '#fef3c7' },
|
||||
{ key: 'HUMAN-ONLY', label: 'HUMAN', emoji: '👤', sublabel: 'Manual', color: '#6b7280', bgColor: '#f3f4f6' }
|
||||
{ key: 'AUTOMATE', label: 'AUTOMATE', emoji: '🤖', sublabel: t('agenticReadiness.tierLabels.automateFull'), color: '#10b981', bgColor: '#d1fae5' },
|
||||
{ key: 'ASSIST', label: 'ASSIST', emoji: '🤝', sublabel: t('agenticReadiness.tierLabels.assistCopilot'), color: '#3b82f6', bgColor: '#dbeafe' },
|
||||
{ key: 'AUGMENT', label: 'AUGMENT', emoji: '📚', sublabel: t('agenticReadiness.tierLabels.augmentTools'), color: '#f59e0b', bgColor: '#fef3c7' },
|
||||
{ key: 'HUMAN-ONLY', label: 'HUMAN', emoji: '👤', sublabel: t('agenticReadiness.tierLabels.humanManual'), color: '#6b7280', bgColor: '#f3f4f6' }
|
||||
];
|
||||
|
||||
// Calcular porcentaje de colas AUTOMATE
|
||||
@@ -1417,12 +1444,13 @@ function AgenticReadinessHeader({
|
||||
|
||||
// Generar interpretación que explica la diferencia volumen vs colas
|
||||
const getInterpretation = () => {
|
||||
// El score principal (88%) se basa en VOLUMEN de interacciones
|
||||
// El % de colas AUTOMATE (26%) es diferente porque hay pocas colas de alto volumen
|
||||
return `El ${Math.round(automatizablePct)}% representa el volumen de interacciones automatizables (AUTOMATE + ASSIST). ` +
|
||||
`Solo el ${Math.round(pctColasAutomate)}% de las colas (${tierData.AUTOMATE.count} de ${totalQueues}) son AUTOMATE, ` +
|
||||
`pero concentran ${Math.round(tierPcts.AUTOMATE)}% del volumen total. ` +
|
||||
`Esto indica pocas colas de alto volumen automatizables - oportunidad concentrada en Quick Wins de alto impacto.`;
|
||||
return t('agenticReadiness.summary.interpretationText', {
|
||||
pct: Math.round(automatizablePct),
|
||||
queuePct: Math.round(pctColasAutomate),
|
||||
count: tierData.AUTOMATE.count,
|
||||
total: totalQueues,
|
||||
volumePct: Math.round(tierPcts.AUTOMATE)
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -1431,7 +1459,7 @@ function AgenticReadinessHeader({
|
||||
<div className="px-5 py-3 bg-gray-50 border-b border-gray-200">
|
||||
<h2 className="font-semibold text-gray-900 flex items-center gap-2">
|
||||
<Bot className="w-4 h-4 text-blue-600" />
|
||||
Agentic Readiness Score
|
||||
{t('agenticReadiness.score')}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
@@ -1443,10 +1471,10 @@ function AgenticReadinessHeader({
|
||||
{Math.round(automatizablePct)}%
|
||||
</div>
|
||||
<div className="text-sm font-semibold mt-1" style={{ color: COLORS.dark }}>
|
||||
Volumen Automatizable
|
||||
{t('agenticReadiness.summary.volumeAutomatable')}
|
||||
</div>
|
||||
<div className="text-xs" style={{ color: COLORS.medium }}>
|
||||
(Tier AUTOMATE + ASSIST)
|
||||
{t('agenticReadiness.summary.tierAutoAssist')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1471,13 +1499,13 @@ function AgenticReadinessHeader({
|
||||
{Math.round(pct)}%
|
||||
</div>
|
||||
<div className="text-xs mt-1 text-gray-600">
|
||||
{formatVolume(data.volume)} int
|
||||
{formatVolume(data.volume)} {t('agenticReadiness.volumeLabels.int')}
|
||||
</div>
|
||||
<div className="text-sm mt-1 text-gray-700">
|
||||
{config.emoji} {config.sublabel}
|
||||
</div>
|
||||
<div className="text-xs mt-0.5 text-gray-500">
|
||||
{data.count} colas
|
||||
{data.count} {t('agenticReadiness.volumeLabels.queues')}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -1522,7 +1550,7 @@ function AgenticReadinessHeader({
|
||||
{/* Interpretación condensada en una línea */}
|
||||
<div className="pt-3" style={{ borderTop: `2px solid ${COLORS.light}` }}>
|
||||
<p className="text-xs" style={{ color: COLORS.dark }}>
|
||||
<span className="font-semibold" style={{ color: COLORS.primary }}>📊 Interpretación: </span>
|
||||
<span className="font-semibold" style={{ color: COLORS.primary }}>📊 {t('agenticReadiness.summary.interpretation')} </span>
|
||||
{getInterpretation()}
|
||||
</p>
|
||||
</div>
|
||||
@@ -2008,13 +2036,15 @@ function ExpandableSkillRow({
|
||||
idx,
|
||||
isExpanded,
|
||||
onToggle,
|
||||
redFlagConfigs
|
||||
redFlagConfigs,
|
||||
t
|
||||
}: {
|
||||
dataPoint: DrilldownDataPoint;
|
||||
idx: number;
|
||||
isExpanded: boolean;
|
||||
onToggle: () => void;
|
||||
redFlagConfigs: RedFlagConfig[];
|
||||
t: any;
|
||||
}) {
|
||||
// v3.4: Contar colas por Tier
|
||||
const tierCounts = {
|
||||
@@ -2164,7 +2194,7 @@ function ExpandableSkillRow({
|
||||
<tbody className="divide-y divide-slate-100">
|
||||
{dataPoint.originalQueues.map((queue, queueIdx) => {
|
||||
const queueMonthlySavings = queue.annualCost ? Math.round(queue.annualCost * 0.35 / 12) : 0;
|
||||
const tierStyle = getTierStyle(queue.tier);
|
||||
const tierStyle = getTierStyle(queue.tier, t);
|
||||
const redFlags = detectRedFlags(queue, redFlagConfigs);
|
||||
|
||||
return (
|
||||
@@ -2200,7 +2230,7 @@ function ExpandableSkillRow({
|
||||
<td className="px-3 py-2 text-gray-600 text-right">{(queue.fcr_tecnico ?? (100 - queue.transfer_rate)).toFixed(0)}%</td>
|
||||
<td className="px-3 py-2 text-center">
|
||||
{queue.scoreBreakdown ? (
|
||||
<InfoTooltip content={<ScoreBreakdownTooltip breakdown={queue.scoreBreakdown} />}>
|
||||
<InfoTooltip content={<ScoreBreakdownTooltip breakdown={queue.scoreBreakdown} t={t} />}>
|
||||
<span className={`px-1.5 py-0.5 rounded text-xs font-medium cursor-help ${tierStyle.bg} ${tierStyle.text}`}>
|
||||
{queue.agenticScore.toFixed(1)}
|
||||
</span>
|
||||
@@ -2218,7 +2248,7 @@ function ExpandableSkillRow({
|
||||
{redFlags.length > 0 ? (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{redFlags.map(flag => (
|
||||
<RedFlagBadge key={flag.config.id} flag={flag} size="sm" />
|
||||
<RedFlagBadge key={flag.config.id} flag={flag} size="sm" t={t} />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
@@ -2783,7 +2813,7 @@ function HumanOnlyByReasonSection({ drilldownData, redFlagConfigs }: { drilldown
|
||||
}
|
||||
|
||||
// v3.4: Sección de Candidatos Prioritarios - Por queue_skill con drill-down a original_queue_id
|
||||
function PriorityCandidatesSection({ drilldownData, redFlagConfigs }: { drilldownData: DrilldownDataPoint[]; redFlagConfigs: RedFlagConfig[] }) {
|
||||
function PriorityCandidatesSection({ drilldownData, redFlagConfigs, t }: { drilldownData: DrilldownDataPoint[]; redFlagConfigs: RedFlagConfig[]; t: any }) {
|
||||
const [expandedRows, setExpandedRows] = useState<Set<string>>(new Set());
|
||||
|
||||
// Filtrar skills que tienen al menos una cola AUTOMATE
|
||||
@@ -2908,6 +2938,7 @@ function PriorityCandidatesSection({ drilldownData, redFlagConfigs }: { drilldow
|
||||
isExpanded={expandedRows.has(dataPoint.skill)}
|
||||
onToggle={() => toggleRow(dataPoint.skill)}
|
||||
redFlagConfigs={redFlagConfigs}
|
||||
t={t}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
@@ -3684,6 +3715,7 @@ export function AgenticReadinessTab({ data, onTabChange }: AgenticReadinessTabPr
|
||||
tierData={tierData}
|
||||
totalVolume={totalVolume}
|
||||
totalQueues={totalQueues}
|
||||
t={t}
|
||||
/>
|
||||
|
||||
{/* SECCIÓN 1: Cabecera Agentic Readiness Score - Visión Global */}
|
||||
|
||||
@@ -1139,7 +1139,17 @@
|
||||
"easyImplCount": "{{count}} · {{amount}}",
|
||||
"backlogCount": "{{count}} · {{amount}}",
|
||||
"total": "total",
|
||||
"noQueuesFilters": "No queues match the selected filters"
|
||||
"noQueuesFilters": "No queues match the selected filters",
|
||||
"quickWinsLabel": "QUICK WINS",
|
||||
"highPotentialLabel": "HIGH POTENTIAL",
|
||||
"developLabel": "DEVELOP",
|
||||
"easyImplLabel": "EASY IMPL.",
|
||||
"backlogLabel": "BACKLOG",
|
||||
"activeFiltersLabel": "Active filters:",
|
||||
"ofQueues": "of {{total}} queues",
|
||||
"perMonth": "/month",
|
||||
"cvAht": "CV AHT:",
|
||||
"viewDetail": "Click for details"
|
||||
},
|
||||
"modal": {
|
||||
"skillLabel": "Skill:",
|
||||
|
||||
@@ -1139,7 +1139,17 @@
|
||||
"easyImplCount": "{{count}} · {{amount}}",
|
||||
"backlogCount": "{{count}} · {{amount}}",
|
||||
"total": "total",
|
||||
"noQueuesFilters": "No hay colas que cumplan los filtros seleccionados"
|
||||
"noQueuesFilters": "No hay colas que cumplan los filtros seleccionados",
|
||||
"quickWinsLabel": "QUICK WINS",
|
||||
"highPotentialLabel": "ALTO POTENCIAL",
|
||||
"developLabel": "DESARROLLAR",
|
||||
"easyImplLabel": "FÁCIL IMPL.",
|
||||
"backlogLabel": "BACKLOG",
|
||||
"activeFiltersLabel": "Filtros activos:",
|
||||
"ofQueues": "de {{total}} colas",
|
||||
"perMonth": "/mes",
|
||||
"cvAht": "CV AHT:",
|
||||
"viewDetail": "Click para ver detalle"
|
||||
},
|
||||
"modal": {
|
||||
"skillLabel": "Skill:",
|
||||
|
||||
Reference in New Issue
Block a user