Rapport_React/src/components/CustomChartJs.jsx

130 lines
3.0 KiB
JavaScript

import { Suspense, useEffect, useState } from 'react';
import Loader from '@/components/Loader';
import { useLayoutContext } from '@/context/useLayoutContext';
import { CategoryScale, Chart as ChartJS, Decimation, Legend, LinearScale, SubTitle, Title, Tooltip } from 'chart.js';
import { Chart } from 'react-chartjs-2';
import { merge } from 'lodash';
import { getColor } from '@/helpers/color';
function getDefaultChartOptions() {
if (typeof window === 'undefined') {
return {};
}
const bodyFont = getComputedStyle(document.body).fontFamily.trim();
return {
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
top: -10
}
},
scales: {
x: {
ticks: {
font: {
family: bodyFont
},
color: getColor('secondary-color'),
display: true
},
grid: {
display: false
},
border: {
display: false
}
},
y: {
ticks: {
font: {
family: bodyFont
},
color: getColor('secondary-color')
},
grid: {
display: true,
color: getColor('chart-border-color'),
lineWidth: 1
},
border: {
display: false,
dash: [5, 5]
}
}
},
plugins: {
legend: {
display: true,
position: 'top',
labels: {
font: {
family: bodyFont
},
color: getColor('secondary-color'),
usePointStyle: true,
pointStyle: 'circle',
boxWidth: 8,
boxHeight: 8,
padding: 15
}
},
tooltip: {
enabled: true,
titleFont: {
family: bodyFont
},
bodyFont: {
family: bodyFont
}
}
}
};
}
const CustomChartJs = ({
type,
height = '100%',
width = '100%',
getOptions,
plugins,
style
}) => {
ChartJS.register(Tooltip, Legend, Title, SubTitle, Decimation, CategoryScale, LinearScale, plugins ?? []);
const {
skin,
theme
} = useLayoutContext();
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
const [chartState, setChartState] = useState({
data: {
labels: [],
datasets: []
},
options: {}
});
useEffect(() => {
if (!mounted) return;
const delay = theme === 'system' ? 10 : 0;
const timer = setTimeout(() => {
const {
data,
options
} = getOptions();
const mergedOptions = merge({}, getDefaultChartOptions(), options);
setChartState({
data,
options: mergedOptions
});
}, delay);
return () => clearTimeout(timer);
}, [mounted, skin, theme, getOptions]);
return <Suspense fallback={<Loader />}>
<Chart key={`${theme}-${skin}`} type={type} data={chartState.data} options={chartState.options} width={width} height={height} style={{
maxHeight: height,
...style
}} />
</Suspense>;
};
export default CustomChartJs;