diff --git a/BACKEND/models/returnRequest.model.js b/BACKEND/models/returnRequest.model.js index 4e97c16..b9ff7bd 100644 --- a/BACKEND/models/returnRequest.model.js +++ b/BACKEND/models/returnRequest.model.js @@ -50,7 +50,7 @@ const returnRequestSchema = new mongoose.Schema({ type: [returnItemSchema], required: [true, "At least one return item is required"], validate: { - validator: function (v: any[]) { + validator: function (v) { return v && v.length > 0; }, message: "Items array cannot be empty", diff --git a/FRONTEND/src/components/ui/QuickAddModal.jsx b/FRONTEND/src/components/ui/QuickAddModal.jsx index e551f47..9d69145 100644 --- a/FRONTEND/src/components/ui/QuickAddModal.jsx +++ b/FRONTEND/src/components/ui/QuickAddModal.jsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from "react"; -import { useCart } from "../../store/cart"; +import { useCartStore } from "../../store/cart"; import { showSuccessToast, showWarningToast, @@ -25,7 +25,7 @@ import { const QuickAddModal = ({ product, isOpen, onClose }) => { const [quantity, setQuantity] = useState(1); - const { addToCart } = useCart(); + const { addToCart } = useCartStore(); const toast = useToast(); const isOutOfStock = diff --git a/FRONTEND/src/pages/ProductPage.jsx b/FRONTEND/src/pages/ProductPage.jsx index 36cca65..784cad8 100644 --- a/FRONTEND/src/pages/ProductPage.jsx +++ b/FRONTEND/src/pages/ProductPage.jsx @@ -1,21 +1,53 @@ import React, { useState, useEffect, useMemo } from 'react'; import { useParams, Link as RouterLink } from 'react-router-dom'; import { - Box, Container, Flex, Grid, GridItem, SimpleGrid, Image, Icon, Heading, Text, - Button, Badge, Divider, Checkbox, Select, VStack, HStack, useToast, useColorModeValue, + Box, + Container, + Flex, + Grid, + GridItem, + SimpleGrid, + Image, + Icon, + Heading, + Text, + Button, + IconButton, + Badge, + Divider, + Checkbox, + Select, + Spinner, + Alert, + AlertIcon, + VStack, + HStack, + useToast, + useColorModeValue, } from '@chakra-ui/react'; -import { - FaArrowLeft, FaShoppingCart, FaCheckCircle, FaTruck, FaShieldAlt, FaUndo, - FaInfoCircle, FaGift, FaChevronLeft, FaChevronRight, +import { + FaArrowLeft, + FaShoppingCart, + FaCheckCircle, + FaTruck, + FaShieldAlt, + FaUndo, + FaInfoCircle, + FaGift, + FaChevronLeft, + FaChevronRight, + FaShareAlt, } from 'react-icons/fa'; -import axios from 'axios'; -import { getSocket } from '../socket'; -import RelatedProducts from '../components/ui/RelatedProducts'; -import ProductReviews from '../components/ui/ProductReviews'; +import axios from "axios"; +import { getSocket } from "../socket"; +import Breadcrumbs from "../components/ui/Breadcrumbs"; +import RelatedProducts from "../components/ui/RelatedProducts"; +import ProductReviews from "../components/ui/ProductReviews"; const ProductPage = () => { const { id } = useParams(); const toast = useToast(); + const [product, setProduct] = useState(null); const [selectedSize, setSelectedSize] = useState(''); const [selectedColor, setSelectedColor] = useState(''); const [displayPrice, setDisplayPrice] = useState(0); @@ -39,10 +71,12 @@ const ProductPage = () => { const fetchProduct = async () => { try { const { data } = await axios.get('/api/products/' + id); - setProduct(data); - if (!data.hasVariants) { - setDisplayPrice(data.basePrice); - setDisplayStock(data.baseStock); + + setProduct(data.data); + + if (!data.data.hasVariants) { + setDisplayPrice(data.data.basePrice); + setDisplayStock(data.data.baseStock); } } catch (err) { console.error(err); @@ -118,6 +152,28 @@ const ProductPage = () => { } }; + const handleShare = async () => { + try { + await navigator.clipboard.writeText(window.location.href); + + toast({ + title: "Product link copied!", + description: "Share it with anyone.", + status: "success", + duration: 3000, + isClosable: true, + }); + } catch { + toast({ + title: "Failed to copy link", + description: "Please try again.", + status: "error", + duration: 3000, + isClosable: true, + }); + } +}; + const toggleBundleItem = (productId) => { setSelectedBundleItems((prev) => prev.includes(productId) @@ -255,15 +311,26 @@ const ProductPage = () => { )} - - {product.name} - + + + {product.name} + + + } + aria-label="Share product" + variant="ghost" + size="sm" + mt={1} + onClick={handleShare} + _hover={{ color: "blue.500" }} + /> + {/* Average Rating */} {product.reviewCount > 0 && (