From 7543f1b66a936d1550d36bd1424e147069982235 Mon Sep 17 00:00:00 2001 From: simantstha <simantstha@vt.edu> Date: Tue, 4 Apr 2023 13:56:52 -0400 Subject: [PATCH] Wishlist Implemented. But decoration needs to be done --- .idea/sonarlint/issuestore/index.pb | 24 +- .idea/sonarlint/securityhotspotstore/index.pb | 22 +- client/src/components/header/Header.js | 280 +++++++++--------- client/src/css/ProductPage.css | 3 +- client/src/pages/ProductDetailPage.js | 218 ++++++++------ client/src/pages/ProductPage.js | 238 +++++++++------ 6 files changed, 446 insertions(+), 339 deletions(-) diff --git a/.idea/sonarlint/issuestore/index.pb b/.idea/sonarlint/issuestore/index.pb index 18a0df6c..b69e5f01 100644 --- a/.idea/sonarlint/issuestore/index.pb +++ b/.idea/sonarlint/issuestore/index.pb @@ -10,8 +10,6 @@ B backend/.gitignore,7/e/7e16691a9fc60084a157565ec422c8094d3df67c F backend/routes/user.js,0/4/04c999728cf3fffacfba7b9dc2fceb3a7effba5b -U -%backend/middlewares/userMiddleware.js,d/2/d20cf2d22a8c76eef456a64a9d3e432b8424b54a W 'client/src/pages/SubCategoryViewPage.js,3/e/3e7653d80177e86eed631eb5211416c65a354776 Y @@ -24,7 +22,21 @@ K backend/models/userModel.js,7/d/7d17874bd52d233c70e5e85aab677744c44f4497 J backend/routes/category.js,5/0/5043e25c47f4b194888c8af5ccb44aaf2f9c9297 -S -#client/src/css/ProductPageWomen.css,4/1/41d02ecdd5bab83937ee29ba62a11210c9466dbf -T -$client/src/pages/ProductPageWomen.js,9/6/9607f36b62e8b6c30ee3e1f7470f8ef0c572e2e1 \ No newline at end of file +J +client/src/context/cart.js,5/d/5d907532839561bbdd97fd651a6cba187927f3b3 +K +client/src/css/CartPage.css,4/6/4648ee38f1a98d262e427a4649581d36005377e7 +M +backend/routes/subCategory.js,9/a/9aa48d0a8b915af09aba8e0fa1dcb1ffc3e4cf87 +< +backend/.env,f/3/f30451335edfb80e231f658d0defc83bb7e4c3a7 +I +backend/routes/product.js,9/7/97e5e83bece9eea7190e3474b72f52946f92444e +\ +,backend/controllers/subCategoryController.js,f/a/fa31e6503db662b06c8c3ff36f3eaa688ffa5352 +X +(backend/controllers/productController.js,b/2/b27113bf2b6e2343a805c3df4eda0fe455803ae0 +M +client/src/pages/LoginPage.js,8/b/8bccef5ea8c8a30fa35c68dc460b3d78ce340ac4 +R +"client/src/pages/ProductAddPage.js,9/d/9d22f1978f8da53fbcad47e397503765cbc88315 \ No newline at end of file diff --git a/.idea/sonarlint/securityhotspotstore/index.pb b/.idea/sonarlint/securityhotspotstore/index.pb index 7df54237..c04be89d 100644 --- a/.idea/sonarlint/securityhotspotstore/index.pb +++ b/.idea/sonarlint/securityhotspotstore/index.pb @@ -13,10 +13,26 @@ M ,backend/controllers/subCategoryController.js,f/a/fa31e6503db662b06c8c3ff36f3eaa688ffa5352 I backend/routes/product.js,9/7/97e5e83bece9eea7190e3474b72f52946f92444e -N -backend/models/productModel.js,8/5/85c6087389dbfb69c295e709452db0351ff91ce7 : .gitignore,a/5/a5cc2925ca8258af241be7e5b0381edf30266302 V -&client/src/pages/SubCategoryAddPage.js,e/2/e29041b2db63ae299cd85228d22c41bd03d8c621 \ No newline at end of file +&client/src/pages/SubCategoryAddPage.js,e/2/e29041b2db63ae299cd85228d22c41bd03d8c621 +J +client/src/context/cart.js,5/d/5d907532839561bbdd97fd651a6cba187927f3b3 +K +client/src/css/CartPage.css,4/6/4648ee38f1a98d262e427a4649581d36005377e7 +F +backend/routes/user.js,0/4/04c999728cf3fffacfba7b9dc2fceb3a7effba5b +< +backend/.env,f/3/f30451335edfb80e231f658d0defc83bb7e4c3a7 +X +(backend/controllers/productController.js,b/2/b27113bf2b6e2343a805c3df4eda0fe455803ae0 +J +backend/routes/category.js,5/0/5043e25c47f4b194888c8af5ccb44aaf2f9c9297 +K +backend/models/userModel.js,7/d/7d17874bd52d233c70e5e85aab677744c44f4497 +M +client/src/pages/LoginPage.js,8/b/8bccef5ea8c8a30fa35c68dc460b3d78ce340ac4 +R +"client/src/pages/ProductAddPage.js,9/d/9d22f1978f8da53fbcad47e397503765cbc88315 \ No newline at end of file diff --git a/client/src/components/header/Header.js b/client/src/components/header/Header.js index 4a6518a9..69e6e14b 100644 --- a/client/src/components/header/Header.js +++ b/client/src/components/header/Header.js @@ -1,10 +1,9 @@ import React, { useEffect, useState } from "react"; import logo from "../images/logo.png"; import "./Header.css"; -import { Link, useLocation } from "react-router-dom"; +import { Link, useLocation, useNavigate } from "react-router-dom"; import axios from "axios"; import { useAuth } from "../../context/auth"; -import { useNavigate } from "react-router-dom"; import { useCart } from "../../context/cart"; import { Badge } from "antd"; import { @@ -16,7 +15,7 @@ import { const Header = () => { const [categories, setCategories] = useState([]); const [isDropdownOpen, setIsDropdownOpen] = useState(false); - const { cart, getTotalQuantity } = useCart(); + const { getTotalQuantity } = useCart(); const [auth, setAuth] = useAuth(); const navigate = useNavigate(); const location = useLocation(); @@ -29,9 +28,9 @@ const Header = () => { useEffect(() => { axios - .get("http://localhost:4000/api/categories") - .then((response) => setCategories(response.data)) - .catch((error) => console.log(error)); + .get("http://localhost:4000/api/categories") + .then((response) => setCategories(response.data)) + .catch((error) => console.log(error)); }, []); const handleDropdownOpen = () => { @@ -43,155 +42,154 @@ const Header = () => { }; return ( - <nav className="navbar navbar-expand-xl bg-white border-bottom navbar-toggler"> - <div className="container-fluid"> - <div className="navbar-brand"> - <Link to={"/"}> - <img src={logo} alt="Logo" width="150" height="60" /> - </Link> + <nav className="navbar navbar-expand-xl bg-white border-bottom navbar-toggler"> + <div className="container-fluid"> + <div className="navbar-brand"> + <Link to={"/"}> + <img src={logo} alt="Logo" width="150" height="60" /> + </Link> + </div> + <button + className="navbar-toggler" + type="button" + data-bs-toggle="collapse" + data-bs-target="#navbarTogglerDemo03" + aria-controls="navbarTogglerDemo03" + aria-expanded="false" + aria-label="Toggle navigation" + > + <span className="navbar-toggler-icon"></span> + </button> + <div + className="d-flex collapse navbar-collapse" + id="navbarTogglerDemo03" + > + <ul className="navbar-nav me-auto mb-2 mb-lg-0"> + {categories.map((category) => ( + <li + className={`nav-item ${ + location.pathname.includes(`/category/${category.name}`) || + location.pathname.includes(`/${category.name}/products`) + ? "active" + : "" + }`} + key={category.id} + > + <Link + to={`/category/${category.name}`} + className="text-decoration-none text-reset" + > + <a className="nav-link">{category.name}</a> + </Link> + </li> + ))} + </ul> + <div className="navbar-collapse justify-content-center"> + <form + className="d-flex justify-content-center col-sm-6 col-md-7 col-lg-8 col-xl-10 " + role="search" + > + <div className="input-group"> + <input + className="form-control border-end-0 border" + type="search" + placeholder="Search" + aria-label="Search" + /> + <button + className="btn btn-outline-secondary button" + type="submit" + > + <i className="fa-solid fa-magnifying-glass"></i> + </button> + </div> + </form> </div> - <button - className="navbar-toggler" - type="button" - data-bs-toggle="collapse" - data-bs-target="#navbarTogglerDemo03" - aria-controls="navbarTogglerDemo03" - aria-expanded="false" - aria-label="Toggle navigation" - > - <span className="navbar-toggler-icon"></span> - </button> - <div - className="d-flex collapse navbar-collapse" - id="navbarTogglerDemo03" - > - <ul className="navbar-nav me-auto mb-2 mb-lg-0"> - {categories.map((category) => ( - <li - className={`nav-item ${ - location.pathname.includes(`/category/${category.name}`) || - location.pathname.includes(`/${category.name}/products`) - ? "active" - : "" - }`} - key={category.id} - > - <Link - to={`/category/${category.name}`} - className="text-decoration-none text-reset" - > - <a className="nav-link">{category.name}</a> - </Link> - </li> - ))} - </ul> - <div className="navbar-collapse justify-content-center"> - <form - className="d-flex justify-content-center col-sm-6 col-md-7 col-lg-8 col-xl-10 " - role="search" + <div className="navbar-collapse"> + <div className="d-flex ms-auto"> + <div + className="dropdown" + onMouseEnter={handleDropdownOpen} + onMouseLeave={handleDropdownClose} > - <div className="input-group"> - <input - className="form-control border-end-0 border" - type="search" - placeholder="Search" - aria-label="Search" - /> - <button - className="btn btn-outline-secondary button" - type="submit" - > - <i className="fa-solid fa-magnifying-glass"></i> - </button> - </div> - </form> - </div> - <div className="navbar-collapse"> - <div className="d-flex ms-auto"> - <div - className="dropdown" - onMouseEnter={handleDropdownOpen} - onMouseLeave={handleDropdownClose} + <button + type="button" + className="btn dropdown-toggle" + data-bs-toggle="dropdown" + aria-expanded="false" > - <button - type="button" - className="btn dropdown-toggle" - data-bs-toggle="dropdown" - aria-expanded="false" - > - <UserOutlined style={{ fontSize: "130%" }} /> - <br /> - {auth.token ? ( - <label className="fw-bolder">{auth.first.first}</label> - ) : ( - <label className="fw-bolder">Profile</label> - )} - </button> - <ul - className={`dropdown-menu ${isDropdownOpen ? "show" : ""}`} - aria-labelledby="dropdownMenuButton2" - > - {!auth.token ? ( - <li> - <Link to="/login" className="dropdown-item"> - Login/SignUp - </Link> - </li> - ) : ( - <li> - <Link to="/" className="dropdown-item" onClick={logout}> - Logout - </Link> - </li> - )} - <li> - <hr className="dropdown-divider" /> - </li> + <UserOutlined style={{ fontSize: "130%" }} /> + <br /> + {auth.token ? ( + <label className="fw-bolder">{auth.first.first}</label> + ) : ( + <label className="fw-bolder">Profile</label> + )} + </button> + <ul + className={`dropdown-menu ${isDropdownOpen ? "show" : ""}`} + aria-labelledby="dropdownMenuButton2" + > + {!auth.token ? ( <li> - <Link to="/dashboard" className="dropdown-item"> - Dashboard + <Link to="/login" className="dropdown-item"> + Login/SignUp </Link> </li> + ) : ( <li> - <hr className="dropdown-divider" /> - </li> - <li> - <Link to="/orders" className="dropdown-item"> - Orders + <Link to="/" className="dropdown-item" onClick={logout}> + Logout </Link> </li> - </ul> - </div> - <button type="button" className="btn"> - <Link - to="/wishlist" - className="text-decoration-none text-reset" - > - <div> - <HeartOutlined style={{ fontSize: "130%" }} /> - <br /> - <label className="fw-bolder">Wishlist</label> - </div> - </Link> - </button> - <button type="button" className="btn"> - <Link to="/cart" className="text-decoration-none text-reset"> - <div> - <Badge count={getTotalQuantity()}> - <ShoppingCartOutlined style={{ fontSize: "140%" }} /> - </Badge> - <br /> - <label className="fw-bolder">Cart</label> - </div> - </Link> - </button> + )} + <li> + <hr className="dropdown-divider" /> + </li> + <li> + <Link to="/dashboard" className="dropdown-item"> + Dashboard + </Link> + </li> + <li> + <hr className="dropdown-divider" /> + </li> + <li> + <Link to="/orders" className="dropdown-item"> + Orders + </Link> + </li> + </ul> </div> + <button type="button" className="btn"> + <Link + to="/wishlist" + className="text-decoration-none text-reset" + > + <div> + <HeartOutlined style={{ fontSize: "130%" }} /> + <br /> + <label className="fw-bolder">Wishlist</label> + </div> + </Link> + </button> + <button type="button" className="btn"> + <Link to="/cart" className="text-decoration-none text-reset"> + <div> + <Badge count={getTotalQuantity()}> + <ShoppingCartOutlined style={{ fontSize: "140%" }} /> + </Badge> + <br /> + <label className="fw-bolder">Cart</label> + </div> + </Link> + </button> </div> </div> </div> - </nav> + </div> + </nav> ); }; export default Header; - diff --git a/client/src/css/ProductPage.css b/client/src/css/ProductPage.css index d22f7e29..d2fd9661 100644 --- a/client/src/css/ProductPage.css +++ b/client/src/css/ProductPage.css @@ -57,9 +57,10 @@ .heart-buttonUnselected { - color:white; + color:#002E6A; } .heart-buttonSelected { color:red; } + diff --git a/client/src/pages/ProductDetailPage.js b/client/src/pages/ProductDetailPage.js index 122eee2b..1380c9a4 100644 --- a/client/src/pages/ProductDetailPage.js +++ b/client/src/pages/ProductDetailPage.js @@ -28,10 +28,27 @@ const ProductDetailPage = () => { useEffect(() => { // Fetch product data using the `id` parameter fetch(`http://localhost:4000/api/product/${id}`) - .then((response) => response.json()) - .then((data) => setProduct(data)) - .catch((error) => console.error(error)); + .then((response) => response.json()) + .then((data) => setProduct(data)) + .catch((error) => console.error(error)); }, [id, selectedSize]); + useEffect(() => { + const fetchWishlist = async () => { + try { + const userId = auth.id.id; + const response = await axios.get( + `http://localhost:4000/api/wishlist/${userId}` + ); + setWishlist(response.data.products); + } catch (error) { + console.error(error); + } + }; + fetchWishlist(); + }, [auth.id.id, wishlist]); + const isInWishlist = (productId) => { + return wishlist.some((item) => item._id === productId); + }; if (!product) { return <div>Loading...</div>; @@ -40,109 +57,128 @@ const ProductDetailPage = () => { try { const userId = auth.id.id; const response = await axios.post( - `http://localhost:4000/api/wishlist/add`, - { - userId, - productId, - } + `http://localhost:4000/api/wishlist/add`, + { + userId, + productId, + } ); setWishlist([...wishlist, response.data.products]); } catch (error) { console.error(error); } }; + const removeFromWishlist = async (productId) => { + try { + const auth = JSON.parse(localStorage.getItem("auth")); + if (!auth) { + return; + } + const userId = auth.id.id; + await axios.delete( + `http://localhost:4000/api/wishlist/delete/${userId}/${productId}` + ); + const updatedWishlist = wishlist.filter( + (products) => products._id !== productId + ); + setWishlist(updatedWishlist); + } catch (err) { + console.error(err.message); + } + }; return ( - <> - <Header></Header> - <div className="container mt-5"> - <div className="row"> - <div className="col-md-6"> - <div className="row"> - <div className="col-md-6"> - <img - src={product.images.front} - alt={product.productName} - className=" img-fluid dis-img " - /> - </div> - <div className="col-md-6"> - <img - src={product.images.left} - alt={product.productName} - className="img-fluid dis-img" - /> - </div> - <div className="col-md-6"> - <img - src={product.images.right} - alt={product.productName} - className="img-fluid dis-img" - /> - </div> - <div className="col-md-6"> - <img - src={product.images.back} - alt={product.productName} - className="img-fluid dis-img" - /> - </div> + <> + <Header></Header> + <div className="container mt-5"> + <div className="row"> + <div className="col-md-6"> + <div className="row"> + <div className="col-md-6"> + <img + src={product.images.front} + alt={product.productName} + className=" img-fluid dis-img " + /> + </div> + <div className="col-md-6"> + <img + src={product.images.left} + alt={product.productName} + className="img-fluid dis-img" + /> + </div> + <div className="col-md-6"> + <img + src={product.images.right} + alt={product.productName} + className="img-fluid dis-img" + /> + </div> + <div className="col-md-6"> + <img + src={product.images.back} + alt={product.productName} + className="img-fluid dis-img" + /> </div> </div> - <div className="col-md-6"> - <h1>{product.productName}</h1> - <p>{product.productDescription}</p> - <hr /> - <p className="productPrice">${product.productPrice}</p> - <p>Price Inclusive of all taxes</p> - {/*<p>Select sizes</p>*/} - {/*{product.productSize.sizes.length == 0 && <h3>Free Size</h3>}*/} - {/*{product.productSize.sizes.length > 0 &&*/} - {/* product.productSize.sizes.map((size, index) => (*/} - {/* <button className="btn size-button">{size.label}</button>*/} - {/* ))}*/} - <p>Select size:</p> - {product.productSize.sizes.length === 0 && <h3>Free Size</h3>} - {product.productSize.sizes.length > 0 && - product.productSize.sizes.map((size) => ( - <button - key={size._id} - className={`btn size-button ${ - selectedSize === size.label ? "size-button-active" : "" - }`} - onClick={() => handleSizeSelection(size.label)} - > - {size.label} - </button> - ))} - <div className="row mt-4"> - <div className="col-12"> - <div className="d-flex justify-content-start"> - <button - className="btn button m-2 add-to-cart" - onClick={() => { - handleAddToCart(product, selectedSize); - }} - > - <i className="fa-solid fa-cart-shopping"></i> Add to Cart - </button> - <button - className="btn button m-2" - onClick={() => { - addToWishlist(product._id); - }} - > - <i className="fa-regular fa-heart"></i> Wishlist - </button> - </div> + </div> + <div className="col-md-6"> + <h1>{product.productName}</h1> + <p>{product.productDescription}</p> + <hr /> + <p className="productPrice">${product.productPrice}</p> + <p>Price Inclusive of all taxes</p> + <p>Select size:</p> + {product.productSize.sizes.length === 0 && <h3>Free Size</h3>} + {product.productSize.sizes.length > 0 && + product.productSize.sizes.map((size) => ( + <button + key={size._id} + className={`btn size-button ${ + selectedSize === size.label ? "size-button-active" : "" + }`} + onClick={() => handleSizeSelection(size.label)} + > + {size.label} + </button> + ))} + <div className="row mt-4"> + <div className="col-12"> + <div className="d-flex justify-content-start"> + <button + className="btn button m-2 add-to-cart" + onClick={() => { + handleAddToCart(product, selectedSize); + }} + > + <i className="fa-solid fa-cart-shopping"></i> Add to Cart + </button> + <button + className={`btn ${ + isInWishlist(product._id) + ? "heart-buttonSelected" + : "heart-buttonUnselected" + }`} + onClick={() => { + if (isInWishlist(product._id)) { + removeFromWishlist(product._id); + } else { + addToWishlist(product._id); + } + }} + > + <i className="fas fa-heart fa-2x"></i> + </button> </div> </div> </div> </div> </div> - <Footer></Footer> - </> + </div> + <Footer></Footer> + </> ); }; export default ProductDetailPage; - diff --git a/client/src/pages/ProductPage.js b/client/src/pages/ProductPage.js index fa3e6a93..f5b42e71 100644 --- a/client/src/pages/ProductPage.js +++ b/client/src/pages/ProductPage.js @@ -12,7 +12,7 @@ const ProductPage = () => { const [selectedSubCategory, setSelectedSubCategory] = useState(""); const [products, setProducts] = useState([]); const { category, subcategory } = useParams(); - const { cart, addToCart } = useCart(); + const { addToCart } = useCart(); const [wishlist, setWishlist] = useState([]); const [auth] = useAuth(); const handleAddToCart = (product, size) => { @@ -21,126 +21,170 @@ const ProductPage = () => { useEffect(() => { axios - .get(`http://localhost:4000/api/categories/${category}/subcategories`) - .then((response) => { - setSubCategory(response.data.subCategories); - }) - .catch((error) => { - console.error(error); - }); + .get(`http://localhost:4000/api/categories/${category}/subcategories`) + .then((response) => { + setSubCategory(response.data.subCategories); + }) + .catch((error) => { + console.error(error); + }); setSelectedSubCategory(subcategory); }, [subcategory]); useEffect(() => { axios - .get( - `http://localhost:4000/api/categories/${category}/subcategory/${selectedSubCategory}/products` - ) - .then((response) => { - setProducts(response.data); - }) - .catch((error) => { - console.error(error); - }); + .get( + `http://localhost:4000/api/categories/${category}/subcategory/${selectedSubCategory}/products` + ) + .then((response) => { + setProducts(response.data); + }) + .catch((error) => { + console.error(error); + }); }, [selectedSubCategory]); + useEffect(() => { + const fetchWishlist = async () => { + try { + const userId = auth.id.id; + const response = await axios.get( + `http://localhost:4000/api/wishlist/${userId}` + ); + setWishlist(response.data.products); + } catch (error) { + console.error(error); + } + }; + fetchWishlist(); + }, [auth.id.id, wishlist]); + const isInWishlist = (productId) => { + return wishlist.some((item) => item._id === productId); + }; + const addToWishlist = async (productId) => { try { const userId = auth.id.id; const response = await axios.post( - `http://localhost:4000/api/wishlist/add`, - { - userId, - productId, - } + `http://localhost:4000/api/wishlist/add`, + { + userId, + productId, + } ); setWishlist([...wishlist, response.data.products]); } catch (error) { console.error(error); } }; + const removeFromWishlist = async (productId) => { + try { + const auth = JSON.parse(localStorage.getItem("auth")); + if (!auth) { + return; + } + const userId = auth.id.id; + await axios.delete( + `http://localhost:4000/api/wishlist/delete/${userId}/${productId}` + ); + const updatedWishlist = wishlist.filter( + (products) => products._id !== productId + ); + setWishlist(updatedWishlist); + } catch (err) { + console.error(err.message); + } + }; return ( - <> - <Header /> - <div className="container mt-5 box"> - <div className="row mb-3"> - <div className="col-sm-1 col-md-2 col-lg-2"> - <select - className="form-select dropdown" - id="productType" - value={selectedSubCategory} - onChange={(event) => setSelectedSubCategory(event.target.value)} - > - {subCategory.map((data) => ( - <option key={data.name} value={data.slug}> - {data.name} - </option> - ))} - </select> - </div> + <> + <Header /> + <div className="container mt-5 box"> + <div className="row mb-3"> + <div className="col-sm-1 col-md-2 col-lg-2"> + <select + className="form-select dropdown" + id="productType" + value={selectedSubCategory} + onChange={(event) => setSelectedSubCategory(event.target.value)} + > + {subCategory.map((data) => ( + <option key={data.name} value={data.slug}> + {data.name} + </option> + ))} + </select> </div> - <div className="product-list row row-cols-1 row-cols-md-4 g-4"> - {products.length > 0 && - products.map((product) => ( - <div className="product col mb-5" key={product.id}> - <div className="card h-100"> - <div className="position-relative"> - <Link - to={`/products/${product._id}`} - className="text-decoration-none" - > - <img - src={product.images.front} - alt={product.name} - className="card-img-top img-fluid image-container" - // style={{ objectFit: 'cover', width: '100%', height: '100%' }} - /> - </Link> - <button - className="position-absolute bottom-0 end-0 btn heart-buttonUnselected" - onClick={() => { - addToWishlist(product._id); - }} - > - <i className="fas fa-heart fa-2x"></i> - </button> - </div> + </div> + <div className="product-list row row-cols-1 row-cols-md-4 g-4"> + {products.length > 0 && + products.map((product) => ( + <div className="product col mb-5" key={product.id}> + <div className="card h-100"> + <div className="position-relative"> + <Link + to={`/products/${product._id}`} + className="text-decoration-none" + > + <img + src={product.images.front} + alt={product.name} + className="card-img-top img-fluid image-container" + // style={{ objectFit: 'cover', width: '100%', height: '100%' }} + /> + </Link> + <button + className={`position-absolute bottom-0 end-0 btn ${ + isInWishlist(product._id) + ? "heart-buttonSelected" + : "heart-buttonUnselected" + }`} + onClick={() => { + if (isInWishlist(product._id)) { + removeFromWishlist(product._id); + } else { + addToWishlist(product._id); + } + }} + > + <i className="fas fa-heart fa-2x"></i> + </button> + </div> - <div className="card-body d-flex flex-column justify-content-center align-items-center"> - <h4 className="card-title card-title-design mb-3"> - {product.productName} - </h4> - <div className="d-flex justify-content-between align-items-center w-100"> - <div> - <p className="card-text priceTag flex-grow-0"> - ${product.productPrice} USD - </p> - </div> - <div> - <button - className="btn btn-primary add-to-cart flex-grow-0" - onClick={() => { - handleAddToCart( - product, - product.productSize.sizes[0].label - ); - }} - disabled={product.productSize.sizes.length > 1} - > - Add to cart - </button> - </div> - </div> - </div> + <div className="card-body d-flex flex-column justify-content-center align-items-center"> + <h4 className="card-title card-title-design mb-3"> + {product.productName} + </h4> + <div className="d-flex justify-content-between align-items-center w-100"> + <div> + <p className="card-text priceTag flex-grow-0"> + ${product.productPrice} USD + </p> + </div> + <div> + <button + className="btn btn-primary add-to-cart flex-grow-0" + onClick={() => { + handleAddToCart( + product, + product.productSize.sizes[0].label + ); + }} + disabled={product.productSize.sizes.length > 1} + > + Add to cart + </button> </div> </div> - ))} - {products.length === 0 && <h1>Products will be Added soon.</h1>} - </div> + </div> + </div> + </div> + ))} + {products.length === 0 && <h1>Products will be Added soon.</h1>} </div> - <Footer></Footer> - </> + </div> + <Footer></Footer> + </> ); }; -- GitLab