const express = require('express'); const router = express.Router(); module.exports = (pool, qry) => { // Get all products router.get('/', async (req, res, next) => { try { const { category, tag, search, sort, order } = req.query; let query = ` SELECT p.*, pc.name as category_name, ARRAY_AGG(DISTINCT t.name) FILTER (WHERE t.name IS NOT NULL) AS tags, json_agg( json_build_object( 'id', pi.id, 'path', pi.image_path, 'isPrimary', pi.is_primary, 'displayOrder', pi.display_order ) ORDER BY pi.display_order ) FILTER (WHERE pi.id IS NOT NULL) AS images FROM products p JOIN product_categories pc ON p.category_id = pc.id LEFT JOIN product_tags pt ON p.id = pt.product_id LEFT JOIN tags t ON pt.tag_id = t.id LEFT JOIN product_images pi ON p.id = pi.product_id `; const whereConditions = []; const params = []; let paramIndex = 1; // Filter by category if (category) { params.push(category); whereConditions.push(`pc.name = $${params.length}`); paramIndex++; } // Filter by tag if (tag) { params.push(tag); whereConditions.push(`t.name = $${params.length}`); paramIndex++; } // Search functionality if (search) { params.push(`%${search}%`); whereConditions.push(`(p.name ILIKE $${params.length} OR p.description ILIKE $${params.length})`); paramIndex++; } // Add WHERE clause if we have conditions if (whereConditions.length > 0) { query += ` WHERE ${whereConditions.join(' AND ')}`; } // Group by product id query += ` GROUP BY p.id, pc.name`; // Sorting if (sort) { const validSortColumns = ['name', 'price', 'created_at']; const validOrderDirections = ['asc', 'desc']; const sortColumn = validSortColumns.includes(sort) ? sort : 'name'; const orderDirection = validOrderDirections.includes(order) ? order : 'asc'; query += ` ORDER BY p.${sortColumn} ${orderDirection}`; } else { // Default sort query += ` ORDER BY p.name ASC`; } const result = await qry(query, params); res.json(result.rows); } catch (error) { next(error); } }); // Get single product by ID router.get('/:id', async (req, res, next) => { try { const { id } = req.params; const query = ` SELECT p.*, pc.name as category_name, ARRAY_AGG(DISTINCT t.name) FILTER (WHERE t.name IS NOT NULL) AS tags, json_agg( json_build_object( 'id', pi.id, 'path', pi.image_path, 'isPrimary', pi.is_primary, 'displayOrder', pi.display_order ) ORDER BY pi.display_order ) FILTER (WHERE pi.id IS NOT NULL) AS images FROM products p JOIN product_categories pc ON p.category_id = pc.id LEFT JOIN product_tags pt ON p.id = pt.product_id LEFT JOIN tags t ON pt.tag_id = t.id LEFT JOIN product_images pi ON p.id = pi.product_id WHERE p.id = $1 GROUP BY p.id, pc.name `; const result = await qry(query, [id]); if (result.rows.length === 0) { return res.status(404).json({ error: true, message: 'Product not found' }); } res.json(result.rows[0]); } catch (error) { next(error); } }); // Get all product categories router.get('/categories/all', async (req, res, next) => { try { const result = await qry('SELECT * FROM product_categories'); res.json(result.rows); } catch (error) { next(error); } }); // Get all tags router.get('/tags/all', async (req, res, next) => { try { const result = await qry('SELECT * FROM tags'); res.json(result.rows); } catch (error) { next(error); } }); // Get products by category router.get('/category/:categoryName', async (req, res, next) => { try { const { categoryName } = req.params; const query = ` SELECT p.*, ARRAY_AGG(DISTINCT t.name) FILTER (WHERE t.name IS NOT NULL) AS tags, json_agg( json_build_object( 'id', pi.id, 'path', pi.image_path, 'isPrimary', pi.is_primary, 'displayOrder', pi.display_order ) ORDER BY pi.display_order ) FILTER (WHERE pi.id IS NOT NULL) AS images FROM products p JOIN product_categories pc ON p.category_id = pc.id LEFT JOIN product_tags pt ON p.id = pt.product_id LEFT JOIN tags t ON pt.tag_id = t.id LEFT JOIN product_images pi ON p.id = pi.product_id WHERE pc.name = $1 GROUP BY p.id `; const result = await qry(query, [categoryName]); res.json(result.rows); } catch (error) { next(error); } }); return router; };