177 lines
No EOL
5.1 KiB
JavaScript
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;
|
|
}; |