Spaces:
Running
Running
| const Cart = require('../models/cartModel'); | |
| const Product = require('../models/productModel'); | |
| // add to cart function | |
| exports.addToCart = async (req, res) => { | |
| try { | |
| const userId = req.user.id; | |
| const { productId, quantity } = req.body; | |
| const product = await Product.findById(productId); | |
| if (!product) { | |
| return res.status(404).json({ message: 'Product not found' }); | |
| } | |
| let cart = await Cart.findOne({ user: userId }); | |
| if (!cart) { | |
| cart = await Cart.create({ | |
| user: userId, | |
| items: [{ product: productId, quantity }], | |
| }); | |
| } else { | |
| const existingItem = cart.items.find( | |
| (item) => item.product.toString() === productId, | |
| ); | |
| if (existingItem) { | |
| existingItem.quantity += quantity; | |
| } else { | |
| cart.items.push({ product: productId, quantity }); | |
| } | |
| await cart.save(); | |
| } | |
| // Populate product details before returning | |
| await cart.populate({ | |
| path: 'items.product', | |
| select: 'nameAr nameEn price salePrice imageCover stock', | |
| }); | |
| res.status(200).json({ | |
| status: 'success', | |
| message: 'Product added to cart', | |
| cart, | |
| }); | |
| } catch (err) { | |
| res | |
| .status(500) | |
| .json({ message: 'Failed to add product', error: err.message }); | |
| } | |
| }; | |
| exports.getCart = async (req, res) => { | |
| try { | |
| const userId = req.user.id; | |
| // Find the cart associated with the user | |
| const cart = await Cart.findOne({ user: userId }).populate({ | |
| path: 'items.product', | |
| select: 'nameAr nameEn price salePrice imageCover', | |
| }); | |
| if (!cart || cart.items.length === 0) { | |
| return res.status(200).json({ | |
| status: 'success', | |
| message: 'Cart is empty', | |
| cart: { items: [] }, | |
| }); | |
| } | |
| // Calculate the total price | |
| const totalPrice = cart.items.reduce((acc, item) => { | |
| const price = item.product.salePrice || item.product.price; | |
| return acc + price * item.quantity; | |
| }, 0); | |
| res.status(200).json({ | |
| status: 'success', | |
| cart, | |
| totalPrice, | |
| }); | |
| } catch (err) { | |
| res | |
| .status(500) | |
| .json({ message: 'Failed to fetch cart', error: err.message }); | |
| } | |
| }; | |
| // PATCH /samoulla/v1/cart/update-quantity | |
| exports.updateQuantity = async (req, res) => { | |
| try { | |
| const userId = req.user.id; | |
| const { productId, action } = req.body; | |
| const cart = await Cart.findOne({ user: userId }).populate({ | |
| path: 'items.product', | |
| select: 'nameAr nameEn price salePrice imageCover', | |
| }); | |
| if (!cart) { | |
| return res.status(404).json({ message: 'Cart not found' }); | |
| } | |
| const cartItem = cart.items.find( | |
| (el) => el.product._id.toString() === productId, | |
| ); | |
| if (!cartItem) { | |
| return res.status(404).json({ message: 'Product not found in cart' }); | |
| } | |
| if (action === 'increase') { | |
| cartItem.quantity += 1; | |
| } else if (action === 'decrease') { | |
| cartItem.quantity -= 1; | |
| if (cartItem.quantity <= 0) { | |
| cart.items = cart.items.filter( | |
| (el) => el.product._id.toString() !== productId, | |
| ); | |
| } | |
| } else { | |
| return res.status(400).json({ message: 'Invalid action' }); | |
| } | |
| await cart.save(); | |
| const totalPrice = cart.items.reduce((acc, item) => { | |
| const price = item.product.salePrice || item.product.price; | |
| return acc + price * item.quantity; | |
| }, 0); | |
| res.status(200).json({ | |
| status: 'success', | |
| cart, | |
| totalPrice, | |
| }); | |
| } catch (err) { | |
| res | |
| .status(500) | |
| .json({ message: 'Error updating quantity', error: err.message }); | |
| } | |
| }; | |
| // PATCH /samoulla/v1/cart/update-quantity | |
| // { | |
| // "productId": "ID_OF_PRODUCT", | |
| // "action": "increase" | |
| // } | |
| // { | |
| // "productId": "ID_OF_PRODUCT", | |
| // "action": "decrease" | |
| // } | |
| // DELETE /samoulla/v1/cart/remove-item | |
| exports.removeFromCart = async (req, res) => { | |
| try { | |
| const userId = req.user.id; | |
| const { productId } = req.params; | |
| const cart = await Cart.findOne({ user: userId }).populate({ | |
| path: 'items.product', | |
| select: 'nameAr nameEn price salePrice imageCover', | |
| }); | |
| if (!cart) { | |
| return res.status(404).json({ message: 'Cart not found' }); | |
| } | |
| const itemExists = cart.items.find( | |
| (el) => el.product._id.toString() === productId, | |
| ); | |
| if (!itemExists) { | |
| return res.status(404).json({ message: 'Product not found in cart' }); | |
| } | |
| cart.items = cart.items.filter( | |
| (el) => el.product._id.toString() !== productId, | |
| ); | |
| await cart.save(); | |
| const totalPrice = cart.items.reduce((acc, item) => { | |
| const price = item.product.salePrice || item.product.price; | |
| return acc + price * item.quantity; | |
| }, 0); | |
| res.status(200).json({ | |
| status: 'success', | |
| message: 'Product removed from cart', | |
| cart, | |
| totalPrice, | |
| }); | |
| } catch (err) { | |
| res | |
| .status(500) | |
| .json({ message: 'Error removing product', error: err.message }); | |
| } | |
| }; | |
| exports.clearCart = async (req, res) => { | |
| try { | |
| const cart = await Cart.findOne({ user: req.user._id }); | |
| if (!cart) { | |
| return res.status(404).json({ message: 'Cart not found' }); | |
| } | |
| cart.items = []; | |
| await cart.save(); | |
| res.status(200).json({ | |
| status: 'success', | |
| message: 'Cart cleared successfully', | |
| cart, | |
| }); | |
| } catch (err) { | |
| res | |
| .status(500) | |
| .json({ message: 'Something went wrong', error: err.message }); | |
| } | |
| }; | |
| // GET /samoulla/v1/cart/all (Admin only) | |
| exports.getAllCarts = async (req, res) => { | |
| try { | |
| // Find all carts that are not empty and belong to a user | |
| const carts = await Cart.find({ | |
| user: { $exists: true, $ne: null }, | |
| items: { $exists: true, $not: { $size: 0 } }, | |
| }) | |
| .populate({ | |
| path: 'user', | |
| select: 'name email phone', | |
| }) | |
| .populate({ | |
| path: 'items.product', | |
| select: 'nameAr nameEn price salePrice imageCover', | |
| }) | |
| .sort('-updatedAt'); | |
| res.status(200).json({ | |
| status: 'success', | |
| results: carts.length, | |
| data: { | |
| carts, | |
| }, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to fetch carts', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |
| // DELETE /samoulla/v1/cart/:id (Admin only) | |
| exports.deleteCart = async (req, res) => { | |
| try { | |
| const cart = await Cart.findByIdAndDelete(req.params.id); | |
| if (!cart) { | |
| return res.status(404).json({ | |
| status: 'fail', | |
| message: 'No cart found with that ID', | |
| }); | |
| } | |
| res.status(204).json({ | |
| status: 'success', | |
| data: null, | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| status: 'error', | |
| message: 'Failed to delete cart', | |
| error: err.message, | |
| }); | |
| } | |
| }; | |