ctrlv-ince/gamezone-react-native
0
1const { Product } = require('../models/product');2const { Order } = require('../models/order');3const mongoose = require('mongoose');4 5// Get reviews for a specific product6exports.getReviewsByProduct = async (req, res) => {7 try {8 const product = await Product.findById(req.params.productId)9 .select('reviews')10 .populate('reviews.user', 'name');11 12 if (!product) return res.status(404).json({ success: false, message: 'Product not found' });13 14 res.send(product.reviews);15 } catch (err) {16 res.status(500).json({ success: false, error: err.message });17 }18};19 20// User leaves a review21exports.createReview = async (req, res) => {22 try {23 const { user, product: productId, rating, comment, order: orderId } = req.body;24 25 // Verify purchased product26 const orders = await Order.find({ user: user, status: { $in: ['Shipped', 'Delivered'] } });27 if (!orders || orders.length === 0) {28 return res.status(403).send('You must have a verified purchase to leave a review.');29 }30 31 let hasPurchased = false;32 for (let order of orders) {33 for (let item of order.orderItems) {34 if (item.product.toString() === productId) {35 hasPurchased = true;36 break;37 }38 }39 if (hasPurchased) break;40 }41 42 if (!hasPurchased) {43 return res.status(403).send('You did not purchase this product or it has not been delivered.');44 }45 46 const product = await Product.findById(productId);47 if (!product) return res.status(404).send('Product not found');48 49 // Check if user already reviewed this product50 const existingReview = product.reviews.find(r => r.user.toString() === user);51 if (existingReview) {52 return res.status(400).send('You have already reviewed this product. You can update it instead.');53 }54 55 // Add review as embedded subdocument56 product.reviews.push({57 user,58 name: req.body.name || 'User',59 rating,60 comment,61 order: orderId,62 });63 64 // Update product average rating65 product.numReviews = product.reviews.length;66 product.rating = product.reviews.reduce((acc, r) => acc + r.rating, 0) / product.reviews.length;67 68 await product.save();69 70 // Mark isReviewed on the order item71 if (orderId) {72 await Order.updateOne(73 { _id: orderId, 'orderItems.product': productId },74 { $set: { 'orderItems.$.isReviewed': true } }75 );76 }77 78 res.send(product.reviews[product.reviews.length - 1]);79 } catch (err) {80 res.status(500).json({ success: false, error: err.message });81 }82};83 84// User updates their own review85exports.updateReview = async (req, res) => {86 try {87 const product = await Product.findOne({ 'reviews._id': req.params.id });88 if (!product) return res.status(404).send('Review not found');89 90 const review = product.reviews.id(req.params.id);91 if (!review) return res.status(404).send('Review not found');92 93 // Verify ownership94 if (review.user.toString() !== req.body.user) {95 return res.status(403).send('You can only update your own review');96 }97 98 review.rating = req.body.rating;99 review.comment = req.body.comment;100 101 // Recalculate average rating102 product.rating = product.reviews.reduce((acc, r) => acc + r.rating, 0) / product.reviews.length;103 104 await product.save();105 106 res.send(review);107 } catch (err) {108 res.status(500).json({ success: false, error: err.message });109 }110};111 