233 lines
9.3 KiB
TypeScript
233 lines
9.3 KiB
TypeScript
import React from 'react';
|
|
import { motion } from 'framer-motion';
|
|
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Cell } from 'recharts';
|
|
import { EconomicModelData } from '../types';
|
|
import { DollarSign, TrendingDown, Calendar, TrendingUp } from 'lucide-react';
|
|
import CountUp from 'react-countup';
|
|
import MethodologyFooter from './MethodologyFooter';
|
|
|
|
interface EconomicModelEnhancedProps {
|
|
data: EconomicModelData;
|
|
}
|
|
|
|
const EconomicModelEnhanced: React.FC<EconomicModelEnhancedProps> = ({ data }) => {
|
|
const {
|
|
currentAnnualCost,
|
|
futureAnnualCost,
|
|
annualSavings,
|
|
initialInvestment,
|
|
paybackMonths,
|
|
roi3yr,
|
|
} = data;
|
|
|
|
// Data for comparison chart
|
|
const comparisonData = [
|
|
{
|
|
name: 'Coste Actual',
|
|
value: currentAnnualCost,
|
|
color: '#ef4444',
|
|
},
|
|
{
|
|
name: 'Coste Futuro',
|
|
value: futureAnnualCost,
|
|
color: '#10b981',
|
|
},
|
|
];
|
|
|
|
// Data for savings breakdown (example)
|
|
const savingsBreakdown = [
|
|
{ category: 'Automatización', amount: annualSavings * 0.45, percentage: 45 },
|
|
{ category: 'Eficiencia', amount: annualSavings * 0.30, percentage: 30 },
|
|
{ category: 'Reducción AHT', amount: annualSavings * 0.15, percentage: 15 },
|
|
{ category: 'Otros', amount: annualSavings * 0.10, percentage: 10 },
|
|
];
|
|
|
|
const CustomTooltip = ({ active, payload }: any) => {
|
|
if (active && payload && payload.length) {
|
|
return (
|
|
<div className="bg-slate-900 text-white px-3 py-2 rounded-lg shadow-lg text-sm">
|
|
<p className="font-semibold">{payload[0].payload.name}</p>
|
|
<p className="text-green-400">€{payload[0].value.toLocaleString('es-ES')}</p>
|
|
</div>
|
|
);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
return (
|
|
<div id="economics" className="bg-white p-6 rounded-xl border border-slate-200 shadow-sm">
|
|
<h3 className="font-bold text-xl text-slate-800 mb-6">Modelo Económico</h3>
|
|
|
|
{/* Key Metrics Grid */}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
|
|
{/* Annual Savings */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ delay: 0.1 }}
|
|
className="bg-gradient-to-br from-green-50 to-emerald-50 p-6 rounded-xl border-2 border-green-200"
|
|
>
|
|
<div className="flex items-center gap-2 mb-2">
|
|
<TrendingDown size={20} className="text-green-600" />
|
|
<span className="text-sm font-medium text-green-900">Ahorro Anual</span>
|
|
</div>
|
|
<div className="text-3xl font-bold text-green-600">
|
|
€<CountUp end={annualSavings} duration={2} separator="," />
|
|
</div>
|
|
<div className="text-xs text-green-700 mt-2">
|
|
{((annualSavings / currentAnnualCost) * 100).toFixed(1)}% reducción de costes
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* ROI 3 Years */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ delay: 0.2 }}
|
|
className="bg-gradient-to-br from-blue-50 to-indigo-50 p-6 rounded-xl border-2 border-blue-200"
|
|
>
|
|
<div className="flex items-center gap-2 mb-2">
|
|
<TrendingUp size={20} className="text-blue-600" />
|
|
<span className="text-sm font-medium text-blue-900">ROI (3 años)</span>
|
|
</div>
|
|
<div className="text-3xl font-bold text-blue-600">
|
|
<CountUp end={roi3yr} duration={2} suffix="x" decimals={1} />
|
|
</div>
|
|
<div className="text-xs text-blue-700 mt-2">
|
|
Retorno sobre inversión
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Payback Period */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ delay: 0.3 }}
|
|
className="bg-gradient-to-br from-amber-50 to-orange-50 p-6 rounded-xl border-2 border-amber-200"
|
|
>
|
|
<div className="flex items-center gap-2 mb-2">
|
|
<Calendar size={20} className="text-amber-600" />
|
|
<span className="text-sm font-medium text-amber-900">Payback</span>
|
|
</div>
|
|
<div className="text-3xl font-bold text-amber-600">
|
|
<CountUp end={paybackMonths} duration={2} /> m
|
|
</div>
|
|
<div className="text-xs text-amber-700 mt-2">
|
|
Recuperación de inversión
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Initial Investment */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ delay: 0.4 }}
|
|
className="bg-gradient-to-br from-slate-50 to-slate-100 p-6 rounded-xl border-2 border-slate-200"
|
|
>
|
|
<div className="flex items-center gap-2 mb-2">
|
|
<DollarSign size={20} className="text-slate-600" />
|
|
<span className="text-sm font-medium text-slate-900">Inversión Inicial</span>
|
|
</div>
|
|
<div className="text-3xl font-bold text-slate-700">
|
|
€<CountUp end={initialInvestment} duration={2} separator="," />
|
|
</div>
|
|
<div className="text-xs text-slate-600 mt-2">
|
|
One-time investment
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
|
|
{/* Comparison Chart */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ delay: 0.5 }}
|
|
className="mb-8"
|
|
>
|
|
<h4 className="font-semibold text-slate-800 mb-4">Comparación AS-IS vs TO-BE</h4>
|
|
<div className="bg-slate-50 p-4 rounded-lg">
|
|
<ResponsiveContainer width="100%" height={250}>
|
|
<BarChart data={comparisonData}>
|
|
<CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" />
|
|
<XAxis dataKey="name" stroke="#64748b" />
|
|
<YAxis stroke="#64748b" />
|
|
<Tooltip content={<CustomTooltip />} />
|
|
<Bar dataKey="value" radius={[8, 8, 0, 0]}>
|
|
{comparisonData.map((entry, index) => (
|
|
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
))}
|
|
</Bar>
|
|
</BarChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Savings Breakdown */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ delay: 0.6 }}
|
|
>
|
|
<h4 className="font-semibold text-slate-800 mb-4">Desglose de Ahorros</h4>
|
|
<div className="space-y-3">
|
|
{savingsBreakdown.map((item, index) => (
|
|
<motion.div
|
|
key={item.category}
|
|
initial={{ opacity: 0, x: -20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ delay: 0.7 + index * 0.1 }}
|
|
className="bg-slate-50 p-4 rounded-lg"
|
|
>
|
|
<div className="flex items-center justify-between mb-2">
|
|
<span className="font-medium text-slate-700">{item.category}</span>
|
|
<span className="font-bold text-slate-900">
|
|
€{item.amount.toLocaleString('es-ES', { maximumFractionDigits: 0 })}
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<div className="flex-1 bg-slate-200 rounded-full h-2">
|
|
<motion.div
|
|
className="bg-green-500 h-2 rounded-full"
|
|
initial={{ width: 0 }}
|
|
animate={{ width: `${item.percentage}%` }}
|
|
transition={{ delay: 0.8 + index * 0.1, duration: 0.8 }}
|
|
/>
|
|
</div>
|
|
<span className="text-sm font-semibold text-slate-600 w-12 text-right">
|
|
{item.percentage}%
|
|
</span>
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Summary Box */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ delay: 1 }}
|
|
className="mt-8 bg-gradient-to-r from-blue-600 to-blue-700 p-6 rounded-xl text-white"
|
|
>
|
|
<h4 className="font-bold text-lg mb-3">Resumen Ejecutivo</h4>
|
|
<p className="text-blue-100 text-sm leading-relaxed">
|
|
Con una inversión inicial de <span className="font-bold text-white">€{initialInvestment.toLocaleString('es-ES')}</span>,
|
|
se proyecta un ahorro anual de <span className="font-bold text-white">€{annualSavings.toLocaleString('es-ES')}</span>,
|
|
recuperando la inversión en <span className="font-bold text-white">{paybackMonths} meses</span> y
|
|
generando un ROI de <span className="font-bold text-white">{roi3yr}x</span> en 3 años.
|
|
</p>
|
|
</motion.div>
|
|
|
|
{/* Methodology Footer */}
|
|
<MethodologyFooter
|
|
sources="Datos operacionales internos (2024) | Benchmarks: Gartner, Forrester Research | Costes de software: RFP vendors (Q4 2024)"
|
|
methodology="DCF (Discounted Cash Flow) con tasa de descuento 10% | Fully-loaded cost incluye salario, beneficios, overhead | Assumptions conservadoras: 80% adoption rate, 30% automatización"
|
|
notes="Desglose de ahorros: Automatización (45%), Eficiencia operativa (30%), Mejora FCR (15%), Reducción attrition (7.5%), Otros (2.5%) | Payback calculado sobre flujo de caja acumulado"
|
|
lastUpdated="Enero 2025"
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default EconomicModelEnhanced;
|