E-Commerce-Module/backend/src/routes/products.js
2025-04-25 00:41:30 -05:00

177 lines
No EOL
5.1 KiB
JavaScript

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