Initial commit from remix

This commit is contained in:
gpt-engineer-app[bot]
2025-09-25 16:01:00 +00:00
commit 5ddc52658d
149 changed files with 32798 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
import React, { useEffect, useState } from 'react';
import type { ApexOptions } from 'apexcharts';
// Chart module is imported dynamically inside the component to avoid SSR/hot-reload issues.
interface ApexChartProps {
type?: 'area' | 'line' | 'bar' | 'pie' | 'donut';
data?: number[];
labels?: string[];
title?: string;
height?: number;
color?: string;
}
const ApexChart: React.FC<ApexChartProps> = ({
type = 'area',
data = [],
labels = [],
title = 'Chart',
height = 350,
color = '#F84525',
}) => {
const isClient = typeof window !== 'undefined';
const [Chart, setChart] = useState<any>(null);
useEffect(() => {
if (isClient) {
import('react-apexcharts')
.then((m) => setChart(m.default))
.catch((e) => console.error('Failed to load react-apexcharts', e));
}
}, [isClient]);
const safeData = Array.isArray(data) ? data.map((n) => (Number.isFinite(Number(n)) ? Number(n) : 0)) : [];
const isDarkMode = typeof document !== 'undefined' && document.documentElement.classList.contains('dark');
// Show loading/no data state if chart not ready or no data
if (!isClient || !Chart || safeData.length === 0) {
return (
<div className="card-enhanced">
<div className="card-body p-4">
<h5 className="card-title mb-3">{title || 'Chart'}</h5>
<div className="text-sm text-muted">
{!Chart ? 'Cargando gráfico...' : 'No hay datos disponibles.'}
</div>
</div>
</div>
);
}
// Ensure options are valid and chart configuration is safe
const options: ApexOptions = {
chart: {
type: type || 'area',
height: height || 350,
zoom: { enabled: false },
toolbar: { show: false },
foreColor: isDarkMode ? '#91989e' : '#433c3a',
animations: { enabled: false } // Disable animations for stability
},
colors: [color || '#F84525'],
dataLabels: { enabled: false },
stroke: {
curve: 'smooth',
width: 3,
},
fill: type === 'area'
? {
type: 'gradient',
gradient: {
shadeIntensity: 1,
type: 'vertical',
opacityFrom: 0.4,
opacityTo: 0,
stops: [0, 70, 97],
gradientToColors: ['#f7b733'],
},
}
: undefined,
markers: {
size: type === 'area' ? 3 : 0,
strokeWidth: 0,
hover: { sizeOffset: 2 },
colors: type === 'area' ? ['#FFFFFF'] : [color || '#F84525'],
},
xaxis: {
categories: labels && labels.length > 0 ? labels : ['Sin datos'],
axisBorder: { show: false },
axisTicks: { show: false },
labels: { style: { colors: isDarkMode ? '#91989e' : '#aaa' } },
},
yaxis: {
labels: { style: { colors: isDarkMode ? '#91989e' : '#aaa' } },
min: 0
},
grid: { borderColor: isDarkMode ? '#26292d' : '#eff2f7' },
legend: {
horizontalAlign: 'left',
labels: { colors: isDarkMode ? '#ffffff' : '#433c3a' },
},
title: {
text: title || 'Chart',
style: { color: isDarkMode ? '#ffffff' : '#433c3a' }
},
theme: { mode: isDarkMode ? 'dark' : 'light' },
noData: {
text: 'No hay datos disponibles',
align: 'center',
verticalAlign: 'middle',
style: {
color: isDarkMode ? '#ffffff' : '#433c3a',
fontSize: '14px'
}
}
};
// Ensure series data is valid
const series = [{
name: title || 'Data',
data: safeData && safeData.length > 0 ? safeData : [0]
}];
return (
<div className="card-enhanced">
<div className="card-body p-4">
<h5 className="card-title mb-3">{title || 'Chart'}</h5>
{Chart && (
<Chart
options={options}
series={series}
type={type || 'area'}
height={height || 350}
key={`chart-${title}-${safeData.length}`}
/>
)}
</div>
</div>
);
};
export default ApexChart;