paul.roost ca05e334a7 feat: Implement server-side API for categories, KPIs, and measurements
- 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.
2025-10-21 13:31:14 +02:00

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);
});