categories.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. const express = require('express');
  2. const pool = require('../db');
  3. const { authMiddleware } = require('../auth');
  4. const router = express.Router();
  5. router.use(authMiddleware);
  6. const DEFAULT_CATEGORIES = [
  7. { value: 'eau', label: 'Eau', icon: '💧' },
  8. { value: 'gaz', label: 'Gaz', icon: '🔥' },
  9. { value: 'electricite', label: 'Électricité', icon: '⚡' },
  10. { value: 'entretien', label: 'Entretien / Réparations', icon: '🔧' },
  11. { value: 'ascenseur', label: 'Ascenseur', icon: '🛗' },
  12. { value: 'ordures', label: 'Ordures ménagères', icon: '🗑️' },
  13. { value: 'assurance', label: 'Assurance', icon: '🛡️' },
  14. { value: 'autre', label: 'Autre', icon: '📦' },
  15. ];
  16. // Seed default categories for a user if none exist
  17. async function ensureDefaults(userId) {
  18. const count = (await pool.query('SELECT COUNT(*) FROM charge_categories WHERE user_id = $1', [userId])).rows[0].count;
  19. if (parseInt(count) === 0) {
  20. for (let i = 0; i < DEFAULT_CATEGORIES.length; i++) {
  21. const c = DEFAULT_CATEGORIES[i];
  22. await pool.query(
  23. 'INSERT INTO charge_categories (user_id, value, label, icon, sort_order) VALUES ($1, $2, $3, $4, $5)',
  24. [userId, c.value, c.label, c.icon, i]
  25. );
  26. }
  27. }
  28. }
  29. // GET /api/categories - List all categories for user
  30. router.get('/', async (req, res) => {
  31. await ensureDefaults(req.userId);
  32. const rows = (await pool.query(
  33. 'SELECT * FROM charge_categories WHERE user_id = $1 ORDER BY sort_order, id',
  34. [req.userId]
  35. )).rows;
  36. res.json(rows);
  37. });
  38. // POST /api/categories - Create a new category
  39. router.post('/', async (req, res) => {
  40. const { value, label, icon } = req.body;
  41. if (!value || !label) return res.status(400).json({ error: 'Valeur et libellé requis' });
  42. // Check uniqueness
  43. const existing = (await pool.query(
  44. 'SELECT id FROM charge_categories WHERE user_id = $1 AND value = $2',
  45. [req.userId, value]
  46. )).rows[0];
  47. if (existing) return res.status(400).json({ error: 'Cette valeur existe déjà' });
  48. const maxOrder = (await pool.query(
  49. 'SELECT COALESCE(MAX(sort_order), 0) + 1 as next FROM charge_categories WHERE user_id = $1',
  50. [req.userId]
  51. )).rows[0].next;
  52. const result = await pool.query(
  53. 'INSERT INTO charge_categories (user_id, value, label, icon, sort_order) VALUES ($1, $2, $3, $4, $5) RETURNING *',
  54. [req.userId, value, label, icon || '📦', maxOrder]
  55. );
  56. res.status(201).json(result.rows[0]);
  57. });
  58. // PUT /api/categories/reorder - Reorder categories (must be before /:id)
  59. router.put('/reorder', async (req, res) => {
  60. const { order } = req.body;
  61. if (!Array.isArray(order)) return res.status(400).json({ error: 'Tableau d\'ordre requis' });
  62. for (let i = 0; i < order.length; i++) {
  63. await pool.query(
  64. 'UPDATE charge_categories SET sort_order = $1 WHERE id = $2 AND user_id = $3',
  65. [i, order[i], req.userId]
  66. );
  67. }
  68. res.json({ success: true });
  69. });
  70. // PUT /api/categories/:id - Update a category
  71. router.put('/:id', async (req, res) => {
  72. const { label, icon } = req.body;
  73. const cat = (await pool.query(
  74. 'SELECT id FROM charge_categories WHERE id = $1 AND user_id = $2',
  75. [req.params.id, req.userId]
  76. )).rows[0];
  77. if (!cat) return res.status(404).json({ error: 'Catégorie non trouvée' });
  78. await pool.query(
  79. 'UPDATE charge_categories SET label = $1, icon = $2 WHERE id = $3',
  80. [label, icon || '📦', req.params.id]
  81. );
  82. res.json({ success: true });
  83. });
  84. // DELETE /api/categories/:id - Delete a category
  85. router.delete('/:id', async (req, res) => {
  86. const cat = (await pool.query(
  87. 'SELECT * FROM charge_categories WHERE id = $1 AND user_id = $2',
  88. [req.params.id, req.userId]
  89. )).rows[0];
  90. if (!cat) return res.status(404).json({ error: 'Catégorie non trouvée' });
  91. // Check if category is in use
  92. const inUse = (await pool.query(
  93. 'SELECT COUNT(*) FROM charges WHERE user_id = $1 AND category = $2',
  94. [req.userId, cat.value]
  95. )).rows[0].count;
  96. if (parseInt(inUse) > 0) {
  97. return res.status(400).json({ error: `Impossible de supprimer : ${inUse} charge(s) utilisent cette catégorie` });
  98. }
  99. await pool.query('DELETE FROM charge_categories WHERE id = $1', [req.params.id]);
  100. res.json({ success: true });
  101. });
  102. module.exports = router;