- Added Express server with SQLite database connection. - Created API endpoints to fetch categories, KPIs, measurements, and statistics. - Implemented error handling for database operations. feat: Create ChartModal component for visualizing KPI data - Developed ChartModal to display line charts for KPI measurements. - Integrated Chart.js for rendering charts with responsive design. - Added styling for modal and chart components. feat: Add ExportModal component for exporting KPI data - Implemented ExportModal to allow users to select data ranges for export. - Included radio buttons for predefined time ranges (last week, month, year, all data). - Styled modal for better user experience. feat: Introduce RangeChartModal for dynamic range selection - Created RangeChartModal to visualize KPI data over user-selected time ranges. - Integrated radio buttons for selecting different time ranges. - Enhanced chart rendering with Chart.js. refactor: Create useSQLiteDatabase hook for data fetching - Developed custom hook to manage fetching categories, KPIs, and measurements. - Improved error handling and loading states for better user feedback. style: Add CSS styles for modals and charts - Created styles for ChartModal, ExportModal, and RangeChartModal. - Ensured responsive design for various screen sizes.
93 lines
2.4 KiB
TypeScript
93 lines
2.4 KiB
TypeScript
import React from 'react';
|
|
import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend } from 'chart.js';
|
|
import { Line } from 'react-chartjs-2';
|
|
import '../styles/ChartModal.css';
|
|
|
|
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend);
|
|
|
|
interface ChartModalProps {
|
|
isOpen: boolean;
|
|
kpi: any;
|
|
measurements: any[];
|
|
onClose: () => void;
|
|
}
|
|
|
|
export const ChartModal: React.FC<ChartModalProps> = ({ isOpen, kpi, measurements, onClose }) => {
|
|
if (!isOpen || !kpi) return null;
|
|
|
|
// Préparer les données pour le graphique
|
|
const labels = measurements
|
|
.map(m => new Date(m.measurement_date).toLocaleDateString('fr-FR'))
|
|
.reverse();
|
|
|
|
const values = measurements
|
|
.map(m => m.value)
|
|
.reverse();
|
|
|
|
const chartData = {
|
|
labels,
|
|
datasets: [
|
|
{
|
|
label: kpi.name,
|
|
data: values,
|
|
borderColor: '#6496ff',
|
|
backgroundColor: 'rgba(100, 150, 255, 0.1)',
|
|
tension: 0.4,
|
|
fill: true,
|
|
pointRadius: 4,
|
|
pointBackgroundColor: '#6496ff',
|
|
pointBorderColor: '#fff',
|
|
pointBorderWidth: 2,
|
|
},
|
|
],
|
|
};
|
|
|
|
const chartOptions = {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
display: true,
|
|
position: 'top' as const,
|
|
},
|
|
title: {
|
|
display: true,
|
|
text: `Graphique Complet: ${kpi.name}`,
|
|
font: { size: 16, weight: 'bold' as const },
|
|
},
|
|
},
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
title: {
|
|
display: true,
|
|
text: kpi.unit,
|
|
},
|
|
},
|
|
x: {
|
|
display: true,
|
|
},
|
|
},
|
|
};
|
|
|
|
return (
|
|
<div className="chart-modal-overlay" onClick={onClose}>
|
|
<div className="chart-modal" onClick={(e) => e.stopPropagation()}>
|
|
<div className="chart-modal-header">
|
|
<h2>📈 {kpi.name}</h2>
|
|
<button className="chart-modal-close" onClick={onClose}>✕</button>
|
|
</div>
|
|
<div className="chart-modal-body">
|
|
<div style={{ height: '500px', width: '100%' }}>
|
|
<Line data={chartData} options={chartOptions} />
|
|
</div>
|
|
</div>
|
|
<div className="chart-modal-footer">
|
|
<p>Nombre de mesures: <strong>{measurements.length}</strong></p>
|
|
<p>Période: <strong>{labels[0]} à {labels[labels.length - 1]}</strong></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|