"use client";
import {
PieChart,
Pie,
Cell,
ResponsiveContainer,
BarChart,
Bar,
XAxis,
YAxis,
Tooltip,
Legend,
RadialBarChart,
RadialBar,
AreaChart,
Area,
CartesianGrid,
LineChart,
Line,
} from "recharts";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
// Colores del tema
const COLORS = {
primary: "#3b82f6", // blue-500
secondary: "#8b5cf6", // purple-500
success: "#22c55e", // green-500
warning: "#f59e0b", // amber-500
danger: "#ef4444", // red-500
info: "#06b6d4", // cyan-500
gray: "#6b7280", // gray-500
orange: "#f97316", // orange-500
pink: "#ec4899", // pink-500
indigo: "#6366f1", // indigo-500
};
const STATUS_COLORS = {
borrador: "#9ca3af", // gray-400
abierto: "#3b82f6", // blue-500
cerrado: "#22c55e", // green-500
};
const PROGRESS_COLORS = ["#ef4444", "#f97316", "#f59e0b", "#22c55e"];
// Tooltip personalizado
interface CustomTooltipProps {
active?: boolean;
payload?: Array<{ name: string; value: number; color?: string }>;
label?: string;
formatter?: (value: number) => string;
}
function CustomTooltip({ active, payload, label, formatter }: CustomTooltipProps) {
if (active && payload && payload.length) {
return (
{label &&
{label}
}
{payload.map((entry, index) => (
{entry.name}: {formatter ? formatter(entry.value) : entry.value}
))}
);
}
return null;
}
// ==================== PIE CHART ====================
interface PieChartData {
name: string;
value: number;
color?: string;
}
interface StatusPieChartProps {
data: PieChartData[];
title: string;
subtitle?: string;
}
export function StatusPieChart({ data, title, subtitle }: StatusPieChartProps) {
const total = data.reduce((acc, item) => acc + item.value, 0);
const colors = [STATUS_COLORS.borrador, STATUS_COLORS.abierto, STATUS_COLORS.cerrado];
return (
{title}
{subtitle && {subtitle}
}
`${name} ${((percent ?? 0) * 100).toFixed(0)}%`}
labelLine={false}
>
{data.map((entry, index) => (
|
))}
} />
{data.map((entry, index) => (
{entry.name}: {entry.value}
))}
);
}
// ==================== DONUT CHART ====================
interface DonutChartProps {
data: PieChartData[];
title: string;
centerLabel?: string;
centerValue?: string | number;
}
export function DonutChart({ data, title, centerLabel, centerValue }: DonutChartProps) {
return (
{title}
{data.map((entry, index) => (
|
))}
} />
{centerLabel && (
{centerValue}
{centerLabel}
)}
{data.map((entry, index) => (
))}
);
}
// ==================== RADIAL BAR CHART ====================
interface RadialBarData {
name: string;
value: number;
fill: string;
}
interface RadialProgressChartProps {
data: RadialBarData[];
title: string;
subtitle?: string;
}
export function RadialProgressChart({ data, title, subtitle }: RadialProgressChartProps) {
return (
{title}
{subtitle && {subtitle}
}
`${v}%`} />} />
);
}
// ==================== SINGLE RADIAL GAUGE ====================
interface RadialGaugeProps {
value: number;
maxValue?: number;
title: string;
subtitle?: string;
color?: string;
}
export function RadialGauge({ value, maxValue = 100, title, subtitle, color = COLORS.primary }: RadialGaugeProps) {
const percentage = Math.min((value / maxValue) * 100, 100);
const data = [
{ name: title, value: percentage, fill: color },
];
return (
{title}
{subtitle && {subtitle}
}
);
}
// ==================== BAR CHART ====================
interface BarChartData {
name: string;
value: number;
value2?: number;
}
interface HorizontalBarChartProps {
data: BarChartData[];
title: string;
subtitle?: string;
dataKey?: string;
color?: string;
formatter?: (value: number) => string;
}
export function HorizontalBarChart({
data,
title,
subtitle,
dataKey = "value",
color = COLORS.primary,
formatter,
}: HorizontalBarChartProps) {
return (
{title}
{subtitle && {subtitle}
}
} />
);
}
// ==================== VERTICAL BAR CHART ====================
interface VerticalBarChartProps {
data: BarChartData[];
title: string;
subtitle?: string;
color?: string;
secondaryColor?: string;
showSecondary?: boolean;
formatter?: (value: number) => string;
}
export function VerticalBarChart({
data,
title,
subtitle,
color = COLORS.primary,
secondaryColor = COLORS.secondary,
showSecondary = false,
formatter,
}: VerticalBarChartProps) {
return (
{title}
{subtitle && {subtitle}
}
} />
{showSecondary && (
)}
{showSecondary && }
);
}
// ==================== AREA CHART ====================
interface AreaChartData {
name: string;
value: number;
value2?: number;
}
interface AreaChartProps {
data: AreaChartData[];
title: string;
subtitle?: string;
color?: string;
gradientId?: string;
}
export function AreaChartComponent({
data,
title,
subtitle,
color = COLORS.primary,
gradientId = "colorValue",
}: AreaChartProps) {
return (
{title}
{subtitle && {subtitle}
}
);
}
// ==================== LINE CHART ====================
interface LineChartData {
name: string;
presupuesto: number;
gastado: number;
}
interface BudgetLineChartProps {
data: LineChartData[];
title: string;
subtitle?: string;
}
export function BudgetLineChart({ data, title, subtitle }: BudgetLineChartProps) {
return (
{title}
{subtitle && {subtitle}
}
`${(v / 1000).toFixed(0)}k`} />
`€${v.toLocaleString("es-ES")}`} />}
/>
);
}
// ==================== STACKED BAR CHART ====================
interface StackedBarData {
name: string;
completado: number;
restante: number;
}
interface StackedProgressChartProps {
data: StackedBarData[];
title: string;
subtitle?: string;
}
export function StackedProgressChart({ data, title, subtitle }: StackedProgressChartProps) {
return (
{title}
{subtitle && {subtitle}
}
`${v}%`} />
`${v}%`} />} />
);
}
// ==================== MULTI RADIAL CHART ====================
interface MultiRadialData {
name: string;
value: number;
fill: string;
}
interface MultiRadialChartProps {
data: MultiRadialData[];
title: string;
subtitle?: string;
}
export function MultiRadialChart({ data, title, subtitle }: MultiRadialChartProps) {
return (
{title}
{subtitle && {subtitle}
}
`${v}%`} />} />
);
}
export { COLORS, STATUS_COLORS, PROGRESS_COLORS };