- 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.
153 lines
3.6 KiB
JavaScript
153 lines
3.6 KiB
JavaScript
const express = require('express');
|
|
const sqlite3 = require('sqlite3').verbose();
|
|
const cors = require('cors');
|
|
const path = require('path');
|
|
|
|
const app = express();
|
|
const PORT = 3001;
|
|
|
|
app.use(cors());
|
|
app.use(express.json());
|
|
|
|
let db;
|
|
|
|
// Initialiser la base de données
|
|
function initDatabase() {
|
|
return new Promise((resolve, reject) => {
|
|
db = new sqlite3.Database(
|
|
path.join(__dirname, 'database', 'sqdc.db'),
|
|
(err) => {
|
|
if (err) {
|
|
console.error('❌ Erreur de connexion:', err);
|
|
reject(err);
|
|
} else {
|
|
console.log('✅ Base de données connectée');
|
|
resolve();
|
|
}
|
|
}
|
|
);
|
|
});
|
|
}
|
|
|
|
// Routes API
|
|
|
|
// Obtenir les catégories
|
|
app.get('/api/categories', (req, res) => {
|
|
db.all('SELECT * FROM categories', (err, rows) => {
|
|
if (err) {
|
|
res.status(500).json({ error: err.message });
|
|
return;
|
|
}
|
|
res.json(rows || []);
|
|
});
|
|
});
|
|
|
|
// Obtenir les KPI
|
|
app.get('/api/kpis', (req, res) => {
|
|
db.all('SELECT * FROM kpis', (err, rows) => {
|
|
if (err) {
|
|
res.status(500).json({ error: err.message });
|
|
return;
|
|
}
|
|
res.json(rows || []);
|
|
});
|
|
});
|
|
|
|
// Obtenir les mesures pour un KPI
|
|
app.get('/api/measurements/:kpiId', (req, res) => {
|
|
try {
|
|
const { kpiId } = req.params;
|
|
const days = parseInt(req.query.days || 30);
|
|
|
|
const fromDate = new Date();
|
|
fromDate.setDate(fromDate.getDate() - days);
|
|
|
|
let query = 'SELECT * FROM measurements WHERE kpi_id = ?';
|
|
const params = [kpiId];
|
|
|
|
if (days > 0) {
|
|
query += ' AND measurement_date >= ?';
|
|
params.push(fromDate.toISOString());
|
|
}
|
|
|
|
query += ' ORDER BY measurement_date ASC';
|
|
|
|
db.all(query, params, (err, rows) => {
|
|
if (err) {
|
|
res.status(500).json({ error: err.message });
|
|
return;
|
|
}
|
|
res.json(rows || []);
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
// Obtenir la dernière mesure pour un KPI
|
|
app.get('/api/latest/:kpiId', (req, res) => {
|
|
try {
|
|
const { kpiId } = req.params;
|
|
|
|
db.get(
|
|
'SELECT * FROM measurements WHERE kpi_id = ? ORDER BY measurement_date DESC LIMIT 1',
|
|
[kpiId],
|
|
(err, row) => {
|
|
if (err) {
|
|
res.status(500).json({ error: err.message });
|
|
return;
|
|
}
|
|
res.json(row || {});
|
|
}
|
|
);
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
// Obtenir les statistiques pour un KPI
|
|
app.get('/api/stats/:kpiId', (req, res) => {
|
|
try {
|
|
const { kpiId } = req.params;
|
|
const days = parseInt(req.query.days || 30);
|
|
|
|
const fromDate = new Date();
|
|
fromDate.setDate(fromDate.getDate() - days);
|
|
|
|
let query = `SELECT
|
|
COUNT(*) as count,
|
|
AVG(value) as avg,
|
|
MIN(value) as min,
|
|
MAX(value) as max
|
|
FROM measurements
|
|
WHERE kpi_id = ?`;
|
|
const params = [kpiId];
|
|
|
|
if (days > 0) {
|
|
query += ' AND measurement_date >= ?';
|
|
params.push(fromDate.toISOString());
|
|
}
|
|
|
|
db.get(query, params, (err, row) => {
|
|
if (err) {
|
|
res.status(500).json({ error: err.message });
|
|
return;
|
|
}
|
|
res.json(row || {});
|
|
});
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
// Démarrer le serveur
|
|
initDatabase().then(() => {
|
|
app.listen(PORT, () => {
|
|
console.log(`🚀 Serveur SQDC démarré sur http://localhost:${PORT}`);
|
|
console.log(`📊 API disponible sur http://localhost:${PORT}/api`);
|
|
});
|
|
}).catch(err => {
|
|
console.error('❌ Erreur lors de l\'initialisation:', err);
|
|
process.exit(1);
|
|
});
|