/** * Modules catalog and hardware routes */ import pool from '../db/index.js'; /** * GET /api/modules * Get all modules from catalog */ export async function getModules(req, res) { try { const { category, active } = req.query; let sql = 'SELECT * FROM modules WHERE 1=1'; const params = []; if (category) { sql += ' AND category = ?'; params.push(category); } if (active !== undefined) { sql += ' AND active = ?'; params.push(active === 'true' || active === '1' ? 1 : 0); } sql += ' ORDER BY category, width_mm, name'; const { rows } = await pool.query(sql, params); res.json(rows); } catch (error) { console.error('Get modules error:', error); res.status(500).json({ error: error.message }); } } /** * GET /api/modules/:id * Get single module by ID */ export async function getModule(req, res) { try { const { id } = req.params; const { rows } = await pool.query('SELECT * FROM modules WHERE id = ?', [id]); if (rows.length === 0) { return res.status(404).json({ error: 'Module non trouvé' }); } res.json(rows[0]); } catch (error) { console.error('Get module error:', error); res.status(500).json({ error: error.message }); } } /** * GET /api/modules/categories * Get distinct module categories */ export async function getModuleCategories(req, res) { try { const { rows } = await pool.query( 'SELECT DISTINCT category FROM modules WHERE active = 1 ORDER BY category' ); res.json(rows.map(r => r.category)); } catch (error) { console.error('Get categories error:', error); res.status(500).json({ error: error.message }); } } /** * GET /api/hardware * Get all Blum hardware */ export async function getHardware(req, res) { try { const { type } = req.query; let sql = 'SELECT * FROM blum_hardware WHERE active = 1'; const params = []; if (type) { sql += ' AND type = ?'; params.push(type); } sql += ' ORDER BY type, name'; const { rows } = await pool.query(sql, params); // Parse specs_json for each item const hardware = rows.map(h => ({ ...h, specs: h.specs_json ? JSON.parse(h.specs_json) : null })); res.json(hardware); } catch (error) { console.error('Get hardware error:', error); res.status(500).json({ error: error.message }); } } /** * GET /api/hardware/types * Get distinct hardware types */ export async function getHardwareTypes(req, res) { try { const { rows } = await pool.query( 'SELECT DISTINCT type FROM blum_hardware WHERE active = 1 ORDER BY type' ); res.json(rows.map(r => r.type)); } catch (error) { console.error('Get hardware types error:', error); res.status(500).json({ error: error.message }); } } /** * GET /api/handles * Get all handle variants */ export async function getHandles(req, res) { try { const { style } = req.query; let sql = 'SELECT * FROM handle_variants WHERE active = 1'; const params = []; if (style) { sql += ' AND style = ?'; params.push(style); } sql += ' ORDER BY style, name'; const { rows } = await pool.query(sql, params); res.json(rows); } catch (error) { console.error('Get handles error:', error); res.status(500).json({ error: error.message }); } } /** * GET /api/hinges * Get all hinge variants */ export async function getHinges(req, res) { try { const { type } = req.query; let sql = 'SELECT * FROM hinge_variants WHERE active = 1'; const params = []; if (type) { sql += ' AND type = ?'; params.push(type); } sql += ' ORDER BY type, name'; const { rows } = await pool.query(sql, params); res.json(rows); } catch (error) { console.error('Get hinges error:', error); res.status(500).json({ error: error.message }); } }