const express = require('express'); const router = express.Router(); module.exports = (pool, query, authMiddleware) => { // Apply authentication middleware to all routes router.use(authMiddleware); // Get all pending reviews (admin) router.get('/pending', async (req, res, next) => { try { if (!req.user.is_admin) { return res.status(403).json({ error: true, message: 'Admin access required' }); } // Get all pending reviews with related data const result = await query(` SELECT r.id, r.title, r.content, r.rating, r.created_at, r.parent_id, r.product_id, r.user_id, r.is_verified_purchase, u.first_name, u.last_name, u.email, p.name as product_name FROM product_reviews r JOIN users u ON r.user_id = u.id JOIN products p ON r.product_id = p.id WHERE r.is_approved = false ORDER BY r.created_at DESC `); res.json(result.rows); } catch (error) { next(error); } }); // Get all reviews for a product (admin) router.get('/products/:productId', async (req, res, next) => { try { const { productId } = req.params; if (!req.user.is_admin) { return res.status(403).json({ error: true, message: 'Admin access required' }); } // Check if product exists const productCheck = await query( 'SELECT id, name FROM products WHERE id = $1', [productId] ); if (productCheck.rows.length === 0) { return res.status(404).json({ error: true, message: 'Product not found' }); } const product = productCheck.rows[0]; // Get all reviews for the product const reviewsQuery = ` SELECT r.id, r.title, r.content, r.rating, r.created_at, r.parent_id, r.is_approved, r.is_verified_purchase, u.id as user_id, u.first_name, u.last_name, u.email FROM product_reviews r JOIN users u ON r.user_id = u.id WHERE r.product_id = $1 ORDER BY r.created_at DESC `; const reviewsResult = await query(reviewsQuery, [productId]); // Organize reviews into threads const reviewThreads = []; const reviewMap = {}; // First, create a map of all reviews reviewsResult.rows.forEach(review => { reviewMap[review.id] = { ...review, replies: [] }; }); // Then, organize into threads reviewsResult.rows.forEach(review => { if (review.parent_id) { // This is a reply if (reviewMap[review.parent_id]) { reviewMap[review.parent_id].replies.push(reviewMap[review.id]); } } else { // This is a top-level review reviewThreads.push(reviewMap[review.id]); } }); res.json({ product: { id: product.id, name: product.name }, reviews: reviewThreads }); } catch (error) { next(error); } }); // Approve a review router.post('/:reviewId/approve', async (req, res, next) => { try { const { reviewId } = req.params; if (!req.user.is_admin) { return res.status(403).json({ error: true, message: 'Admin access required' }); } // Check if review exists const reviewCheck = await query( 'SELECT id, is_approved FROM product_reviews WHERE id = $1', [reviewId] ); if (reviewCheck.rows.length === 0) { return res.status(404).json({ error: true, message: 'Review not found' }); } // Check if review is already approved if (reviewCheck.rows[0].is_approved) { return res.status(400).json({ error: true, message: 'Review is already approved' }); } // Approve review const result = await query( 'UPDATE product_reviews SET is_approved = true WHERE id = $1 RETURNING *', [reviewId] ); res.json({ message: 'Review approved successfully', review: result.rows[0] }); } catch (error) { next(error); } }); // Delete a review router.delete('/:reviewId', async (req, res, next) => { try { const { reviewId } = req.params; if (!req.user.is_admin) { return res.status(403).json({ error: true, message: 'Admin access required' }); } // Check if review exists const reviewCheck = await query( 'SELECT id FROM product_reviews WHERE id = $1', [reviewId] ); if (reviewCheck.rows.length === 0) { return res.status(404).json({ error: true, message: 'Review not found' }); } // Delete review and all replies (cascading delete handles this) await query( 'DELETE FROM product_reviews WHERE id = $1', [reviewId] ); res.json({ message: 'Review deleted successfully' }); } catch (error) { next(error); } }); return router; };