diff --git a/src/components/Header.jsx b/src/components/Header.jsx index d0d5c30d..8338e67c 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -5,6 +5,7 @@ import { LazyLoadImage } from "react-lazy-load-image-component"; import { Link, useLocation } from "react-router-dom"; import logo from "../assets/images/sytLogo.png"; +import CartDrawer from "./shop/CartDrawer"; import CartIcon from "./shop/CartIcon"; const navLinks = [ @@ -52,6 +53,7 @@ const navLinks = [ function Header() { const [showNavlinks, setShowNavlinks] = useState(false); + const [open, setOpen] = useState(false); const { pathname } = useLocation(); @@ -66,7 +68,13 @@ function Header() { {/* mobile menu */}
- +
{showNavlinks ? (
); } diff --git a/src/components/shop/CartDrawer.jsx b/src/components/shop/CartDrawer.jsx index 011383d9..319d04e0 100644 --- a/src/components/shop/CartDrawer.jsx +++ b/src/components/shop/CartDrawer.jsx @@ -6,59 +6,27 @@ import { IoIosCloseCircleOutline } from "react-icons/io"; import { RiDeleteBin6Line } from "react-icons/ri"; import { LazyLoadImage } from "react-lazy-load-image-component"; import { Link, useNavigate } from "react-router-dom"; +import { useDeleteSwag } from "../../hooks/Mutations/shop/useCartSwagg"; import formatPrice from "../../utilities/formatPrice"; function CartDrawer({ open, setOpen }) { const navigate = useNavigate(); // Get the JSON string from localStorage - const [cartProducts, setCartProducts] = useState([]); - - const dummyCartData = [ - { - id: "271fcc1c-0337-44f4-9449-2bc35b6ffd01", - name: "Cityscape Jacket", - description: - "Introducing our Cityscape Jacket: a blend of urban flair and unbeatable comfort. Crafted with premium materials, it offers sleek design and weather resistance for city adventures. Stay stylish and protected with adjustable features and convenient pockets. Upgrade your urban wardrobe today!", - category: "Jackets", - image: - "https://apis.spaceyatech.com/media/product_images/main-sample_copy_Fud5OzF.png", - price: "3000.00", - stock: 10, - color: "brown", - }, - { - id: "232437b9-3e64-4cad-a6c3-08158e118207", - name: "Cityscape Jacket - Mid", - description: - "Introducing our Cityscape Jacket: a blend of urban flair and unbeatable comfort. Crafted with premium materials, it offers sleek design and weather resistance for city adventures. Stay stylish and protected with adjustable features and convenient pockets. Upgrade your urban wardrobe today!", - category: "Jackets", - image: - "https://apis.spaceyatech.com/media/product_images/main-sample_copy_BRv17MK.png", - price: "1800.00", - stock: 11, - color: "brown", - }, - { - id: "9cd9a601-0ed9-4685-8633-4b04e0811fc7", - name: "SYT Hoodie", - description: - "Unleash your tech-savvy style with our Tech-Fit Hoodie. Designed for the modern individual, it seamlessly integrates functionality and fashion. Crafted with cutting-edge materials, it offers unrivaled comfort and durability. Elevate your wardrobe with this essential piece that effortlessly combines innovation and style.", - category: "Hoodies", - image: - "https://apis.spaceyatech.com/media/product_images/sample1_copy_PXgn3MX.png", - price: "2000.00", - stock: 10, - color: "white", - }, - ]; + const [cartProducts, setCartProducts] = useState(() => { + // Initialize state with the value from localStorage if it exists + const storedProducts = localStorage.getItem("swagList"); + return storedProducts ? JSON.parse(storedProducts) : []; + }); useEffect(() => { - const storage = localStorage.getItem("swagList") - ? JSON.parse(localStorage.getItem("swagList")) - : null; - setCartProducts(storage); - }, [cartProducts]); + if (open) { + const storedProducts = localStorage.getItem("swagList"); + if (storedProducts) { + setCartProducts(JSON.parse(storedProducts)); + } + } + }, [open]); // const { data: cartProducts, isSuccess } = useProductsInCart(); useEffect(() => { @@ -78,31 +46,23 @@ function CartDrawer({ open, setOpen }) { }; }, []); - // const { mutate: deleteSwag } = useDeleteSwag(); + const { mutate: removeSwagFromCart } = useDeleteSwag(); const deleteFromLocalStorage = (cartItemId) => { - // Parse it back to an array of objects - const swagList = cartProducts; - - const idxToDelete = swagList.findIndex( - (swag) => swag.swagg_id === cartItemId + // Create a new array by filtering out the item to delete + const updatedSwagList = cartProducts.filter( + (swag) => swag.id !== cartItemId ); - // Check if the object was found - if (idxToDelete !== -1) { - // Remove the object from the swagList - swagList.splice(idxToDelete, 1); - - // Convert the updated list to a JSON string - setCartProducts(JSON.stringify(swagList)); + // Update the state with the new array + setCartProducts(updatedSwagList); - // Store the updated list back to localStorage - localStorage.setItem("swagList", cartProducts); - } + // Convert the updated list to a JSON string and store it in localStorage + localStorage.setItem("swagList", JSON.stringify(updatedSwagList)); }; const handleDeleteSwag = (cartItemId) => { - // deleteSwag(cartItemId); + removeSwagFromCart(cartItemId); deleteFromLocalStorage(cartItemId); }; @@ -167,11 +127,8 @@ function CartDrawer({ open, setOpen }) {
@@ -197,7 +150,7 @@ function CartDrawer({ open, setOpen }) {

- Hoodies + {cartProduct.category}

@@ -205,12 +158,10 @@ function CartDrawer({ open, setOpen }) { {" "} - {cartProduct.name || - cartProduct.product?.name} + {cartProduct.name}

@@ -219,10 +170,7 @@ function CartDrawer({ open, setOpen }) { type="button" className="flex justify-end" onClick={() => { - handleDeleteSwag( - cartProduct.id || - cartProduct.swagg_id - ); + handleDeleteSwag(cartProduct.id); }} > {/* Delete icon */} @@ -230,7 +178,7 @@ function CartDrawer({ open, setOpen }) {
-

Qty: 1

+

Qty: {cartProduct.orderUnits}

KES {formatPrice(cartProduct.price)}

diff --git a/src/components/shop/Counter.jsx b/src/components/shop/Counter.jsx index 21176814..63045311 100644 --- a/src/components/shop/Counter.jsx +++ b/src/components/shop/Counter.jsx @@ -1,13 +1,17 @@ import PropTypes from "prop-types"; -function Counter({ className, setCount, count }) { +function Counter({ className, setCount, count, maxStock }) { + const increment = () => setCount((prevCount) => prevCount + 1); + const decrement = () => + setCount((prevCount) => (prevCount > 1 ? prevCount - 1 : prevCount)); + // console.log(count) return (
@@ -18,10 +22,11 @@ function Counter({ className, setCount, count }) { {count}

@@ -39,4 +44,5 @@ Counter.propTypes = { className: PropTypes.string, setCount: PropTypes.func.isRequired, count: PropTypes.number.isRequired, + maxStock: PropTypes.number.isRequired, }; diff --git a/src/components/shop/ProductCard.jsx b/src/components/shop/ProductCard.jsx index 05b65bc4..61edd15a 100644 --- a/src/components/shop/ProductCard.jsx +++ b/src/components/shop/ProductCard.jsx @@ -21,7 +21,7 @@ function ProductCard({ product }) { return (

@@ -41,7 +41,9 @@ function ProductCard({ product }) { {totalStock > 0 ? (

{totalStock} - items left + + {totalStock === 1 ? "item" : "items"} left +

) : (
diff --git a/src/hooks/Mutations/shop/useCartSwagg.jsx b/src/hooks/Mutations/shop/useCartSwagg.jsx index 8896841a..90be5009 100644 --- a/src/hooks/Mutations/shop/useCartSwagg.jsx +++ b/src/hooks/Mutations/shop/useCartSwagg.jsx @@ -9,7 +9,7 @@ const useAddSwagToCart = () => { return useMutation({ mutationFn: async (cartItems) => { - const response = await publicAxios.post("/cart/swaggs/", cartItems, { + const response = await publicAxios.post("/cart-items/", cartItems, { headers: { "Content-Type": "application/json", // Authorization: `Bearer ${auth?.access}`, @@ -36,7 +36,7 @@ const useDeleteSwag = () => { return useMutation({ mutationFn: async (id) => { - const response = await publicAxios.delete(`/cart/swaggs/${id}/`, { + const response = await publicAxios.delete(`/cart-items/${id}/`, { headers: { "Content-Type": "application/json", // Authorization: `Bearer ${auth?.access}`, @@ -58,4 +58,32 @@ const useDeleteSwag = () => { }); }; -export { useAddSwagToCart, useDeleteSwag }; +const useDeleteAllSwag = () => { + const { logout } = useAuth(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async () => { + const response = await publicAxios.delete("/cart-items/clear_cart/", { + headers: { + "Content-Type": "application/json", + // Authorization: `Bearer ${auth?.access}`, + }, + }); + + return response.data; + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["productsInCart"] }); + }, + onError: (error) => { + // eslint-disable-next-line no-console + console.error("Unable to delete all cart items"); + if (error.response.status === 401) { + logout(); + } + }, + }); +}; + +export { useAddSwagToCart, useDeleteSwag, useDeleteAllSwag }; diff --git a/src/hooks/Mutations/shop/useMakeOrder.jsx b/src/hooks/Mutations/shop/useMakeOrder.jsx index 08d91dfc..df6b2e68 100644 --- a/src/hooks/Mutations/shop/useMakeOrder.jsx +++ b/src/hooks/Mutations/shop/useMakeOrder.jsx @@ -1,18 +1,18 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import privateAxios from "../../../api/privateAxios"; -import useAuth from "../../useAuth"; +// import useAuth from "../../useAuth"; -// POST: https://apis.spaceyatech.com/api/orders/ +// POST: https://apis.spaceyatech.com/api/checkout/ const useMakeOrder = () => { - const { auth, logout } = useAuth(); + // const { auth, logout } = useAuth(); const queryClient = useQueryClient(); return useMutation({ mutationFn: async (customerInfo) => { - const response = await privateAxios.post("/orders/", customerInfo, { + const response = await privateAxios.post("/checkout/", customerInfo, { headers: { "Content-Type": "application/json", - Authorization: `Bearer ${auth?.access}`, + // Authorization: `Bearer ${auth?.access}`, }, }); return response.data; @@ -25,7 +25,7 @@ const useMakeOrder = () => { // eslint-disable-next-line no-console console.error("Unable to add availability"); if (error.response.status === 401) { - logout(); + // logout(); } }, }); diff --git a/src/hooks/Queries/shop/useCartProducts.jsx b/src/hooks/Queries/shop/useCartProducts.jsx index e834e4b1..d3f9ee24 100644 --- a/src/hooks/Queries/shop/useCartProducts.jsx +++ b/src/hooks/Queries/shop/useCartProducts.jsx @@ -8,7 +8,7 @@ const fetchProductsInCart = async () => { // const { access } = authObject; try { - const response = await publicAxios.get("/cart/swaggs/", { + const response = await publicAxios.get("/cart-items/", { headers: { "Content-Type": "application/json", // Authorization: `Bearer ${access}`, diff --git a/src/hooks/Queries/shop/useSwagList.jsx b/src/hooks/Queries/shop/useSwagList.jsx index b14035f1..2201942f 100644 --- a/src/hooks/Queries/shop/useSwagList.jsx +++ b/src/hooks/Queries/shop/useSwagList.jsx @@ -21,7 +21,7 @@ const useSwagList = () => const fetchSingleSwag = async (id) => { try { - const response = await publicAxios.get(`/swaggs/${id}`); + const response = await publicAxios.get(`/swaggsnew/${id}`); return response.data; } catch (error) { toast.error("Error fetching swag list"); diff --git a/src/pages/shop/Homepage.jsx b/src/pages/shop/Homepage.jsx index 3ed1e2b1..adaa2637 100644 --- a/src/pages/shop/Homepage.jsx +++ b/src/pages/shop/Homepage.jsx @@ -1,4 +1,6 @@ +import { useState } from "react"; import SeoMetadata from "../../components/SeoMetadata"; +import CartDrawer from "../../components/shop/CartDrawer"; import CartIcon from "../../components/shop/CartIcon"; import Banner from "./sections/Banner/index"; import BrowseProducts from "./sections/BrowseProducts"; @@ -7,6 +9,8 @@ import FilterSection from "./sections/FilterSection"; import NewProducts from "./sections/NewArrivals"; function Homepage() { + const [open, setOpen] = useState(false); + return ( <>
- +
@@ -28,6 +38,7 @@ function Homepage() {
+ ); } diff --git a/src/pages/shop/OrderSummaryPage.jsx b/src/pages/shop/OrderSummaryPage.jsx index 8ee4cf39..cea35de5 100644 --- a/src/pages/shop/OrderSummaryPage.jsx +++ b/src/pages/shop/OrderSummaryPage.jsx @@ -5,7 +5,10 @@ import { FaTrash } from "react-icons/fa"; import { LazyLoadImage } from "react-lazy-load-image-component"; import { Link } from "react-router-dom"; -import { useDeleteSwag } from "../../hooks/Mutations/shop/useCartSwagg"; +import { + useDeleteSwag, + useDeleteAllSwag, +} from "../../hooks/Mutations/shop/useCartSwagg"; import useMakeOrder from "../../hooks/Mutations/shop/useMakeOrder"; import useProductsInCart from "../../hooks/Queries/shop/useCartProducts"; import PaymentMethd from "./PaymentMethd"; @@ -20,15 +23,30 @@ function Checkout() { } = useMakeOrder(); const { mutate: deleteSwag } = useDeleteSwag(); // Use deleteSwag + const { mutate: clearCart } = useDeleteAllSwag(); + const [isOpen, setIsOpen] = useState(false); + const clearLocalStorageCart = () => { + localStorage.setItem("swagList", []); + }; + const handleSubmit = (data) => { const payload = { - country: data.address.country, + city: `${data.address.city}, ${data.address.country}`, phone: data.phoneNumber, - address: `${data.address.postalAddress}, ${data.address.city}`, + address: data.address.postalAddress, + postal_code: data.address.postalCode, }; makeOrder(payload); + + if (successfulOrder) { + // clear session cart + clearCart(); + + // delete local storage cart + clearLocalStorageCart(); + } }; const closeModal = () => { diff --git a/src/pages/shop/SingleItemPage.jsx b/src/pages/shop/SingleItemPage.jsx index 4e0a8481..ecb54c52 100644 --- a/src/pages/shop/SingleItemPage.jsx +++ b/src/pages/shop/SingleItemPage.jsx @@ -9,13 +9,21 @@ import SmallSample1 from "../../assets/images/shop-page/small-sample-colored.png import SmallSample2 from "../../assets/images/shop-page/small-sample-greyscale.png"; import SeoMetadata from "../../components/SeoMetadata"; import CartDrawer from "../../components/shop/CartDrawer"; -import Counter from "../../components/shop/Counter"; +// import Counter from "../../components/shop/Counter"; import { useAddSwagToCart } from "../../hooks/Mutations/shop/useCartSwagg"; import { useSingleSwag } from "../../hooks/Queries/shop/useSwagList"; import formatPrice from "../../utilities/formatPrice"; import ItemHeader from "./sections/ItemHeader"; -const VariationData = [SmallSample1, SmallSample2, SmallSample1, SmallSample2]; +const VariationData = [ + SmallSample1, + SmallSample2, + SmallSample1, + SmallSample2, + SmallSample2, + SmallSample1, + SmallSample2, +]; export default function SingleItemPage() { const params = useParams(); @@ -23,36 +31,74 @@ export default function SingleItemPage() { const [count, setCount] = useState(1); const [open, setOpen] = useState(false); const [selectedSize, setSelectedSize] = useState(null); - const [selectedColor, setSelectedColor] = useState(null); - const [Payload, setPayload] = useState({}); + const [selectedColor, setSelectedColor] = useState(""); + + const [selectedVariant, setSelectedVariant] = useState(null); + const [variants, setVariants] = useState(null); + const [selectedImage, setSelectedImage] = useState(1); + const [error, setError] = useState(""); // const { data: singleOrder } = useSingleOrder(params.id); - const { data: singleSwag, isSuccess, refetch } = useSingleSwag(params.id); + const { + data: singleSwag, + isSuccess, + isPending, + isError, + refetch, + } = useSingleSwag(params.id); + const { mutate: addItemsToCart } = useAddSwagToCart(); - const sizes = ["XS", "S", "M", "L", "XL", "XXL"]; - const colors = ["BBD278", "BBC1F8", "FFD3F8", "AF674F"]; + const sizes = { + XS: "Extra Small", + S: "Small", + M: "Medium", + L: "Large", + XL: "Extra Large", + }; useEffect(() => { - localStorage.setItem("swagList", []); if (isSuccess) { - setPayload({ - swagg_id: singleSwag.id, - product: { - name: singleSwag.name, - description: singleSwag.description, - price: singleSwag.price, - size: selectedSize, - image: singleSwag.image, - }, - quantity: count, - }); + const initialVariant = singleSwag.attributes[0]; + setSelectedVariant(initialVariant); + setSelectedColor(initialVariant.color); + setVariants(singleSwag.attributes); } + }, [isSuccess, singleSwag]); + + useEffect(() => { refetch(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [params.id]); + }, [params.id, refetch]); + + useEffect(() => { + // Update selected variant when selected color changes + if (selectedColor && variants) { + const variant = variants.find((v) => v.color === selectedColor); + setSelectedVariant(variant); + } + }, [selectedColor, variants]); const addToLocalStorage = () => { + // find an attribute with an image URL + const attributeWithImages = singleSwag.attributes.find( + (attribute) => attribute.images.length > 0 + ); + + const newData = { + id: crypto.randomUUID(), + name: singleSwag.name, + category: singleSwag.category, + size: selectedSize.name, + color: selectedColor, + price: singleSwag.price * count, + orderUnits: count, + slug: singleSwag.slug, + image: + selectedVariant.images.length > 0 + ? selectedVariant.images[0].image + : attributeWithImages.images.map((img) => img.image)[0], + }; + let swagList = []; let swagListJSON; if (localStorage.getItem("swagList")) { @@ -60,11 +106,11 @@ export default function SingleItemPage() { swagList = JSON.parse(localStorage.getItem("swagList")); // Also check for matching swagg_id that already exist in local storage - swagList.push(Payload); + swagList.push(newData); swagListJSON = JSON.stringify(swagList); localStorage.setItem("swagList", swagListJSON); } else { - swagList.push(Payload); + swagList.push(newData); swagListJSON = JSON.stringify(swagList); localStorage.setItem("swagList", swagListJSON); @@ -72,18 +118,25 @@ export default function SingleItemPage() { }; const handleAddToCart = () => { - // Send to backend not giving a usable response - addItemsToCart(Payload); - - // Add to local storage - addToLocalStorage(); + if (!selectedSize) { + setError("Please select a size"); + } else { + // Add a new item to the cart in the backend + addItemsToCart({ + product_attribute: selectedVariant.id, + quantity: count, + }); + // Add to local storage + addToLocalStorage(); - setOpen(true); + // open cart + setOpen(true); + } }; // const handleBuyNow = () => { // // Send to backend not giving a usable response - // addItemsToCart(Payload); + // addItemsToCart(payload); // // Add to local storage // addToLocalStorage(); @@ -91,6 +144,17 @@ export default function SingleItemPage() { // navigate("/shop/checkout"); // }; + const increment = () => { + setCount((prevCount) => prevCount + 1); + }; + + const decrement = () => { + setCount((prevCount) => (prevCount > 1 ? prevCount - 1 : prevCount)); + }; + + const getSizeKeyByValue = (value) => + Object.keys(sizes).find((key) => sizes[key] === value); + return ( <> setOpen((prev) => !prev)} /> - {isSuccess ? ( + {isSuccess && (
- -
- {VariationData.map((pic) => ( -
- -
+
+ {VariationData.map((image, index) => ( + + ))} +
+
+ {VariationData.map((pic, index) => ( + ))}

- {singleSwag.name} + {singleSwag?.name}

- KES {formatPrice(singleSwag.price)} + KES {formatPrice(singleSwag?.price)}

4.5 @@ -139,68 +219,104 @@ export default function SingleItemPage() {

- {colors.map((color) => ( -
- ) : ( -
- )} - - ))} + ) : ( +
+ )} + + ))}

Choose a size

- {sizes.map((size) => ( - - ))} + {selectedVariant && + selectedVariant?.size.map((size) => ( + + ))}

+ {error && ( +

{error}

+ )}
- + maxStock={selectedVariant?.stock} + /> */} +
+ +

+ {count} +

+ +
+
+ )} + {isPending && ( +
+
+

Loading product...

+
+
+
+
+
+ )} + {isError && ( +
+
+

+ Error fetching product. Try again later

- ) : ( -

Error Fetching Item

)} {/* Cart Drawer */} diff --git a/src/pages/shop/sections/Banner/Carousal.jsx b/src/pages/shop/sections/Banner/Carousal.jsx index 275dc828..d010902e 100644 --- a/src/pages/shop/sections/Banner/Carousal.jsx +++ b/src/pages/shop/sections/Banner/Carousal.jsx @@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from "react"; import { LazyLoadImage } from "react-lazy-load-image-component"; import { Link } from "react-router-dom"; import { useSwagList } from "../../../../hooks/Queries/shop/useSwagList"; +import formatPrice from "../../../../utilities/formatPrice"; function Carousel() { const [width, setWidth] = useState(0); @@ -80,9 +81,11 @@ function Carousel() {

Buy out most stylish tech themed items

-

From KES 2,600

+

+ From KES {formatPrice(swagList[selectedIndex]?.price)} +

Shop Now diff --git a/src/pages/shop/sections/BrowseProducts.jsx b/src/pages/shop/sections/BrowseProducts.jsx index d01d5d26..d1f11205 100644 --- a/src/pages/shop/sections/BrowseProducts.jsx +++ b/src/pages/shop/sections/BrowseProducts.jsx @@ -4,7 +4,7 @@ import SectionWrapper from "../../../components/shop/SectionWrapper"; import { useSwagList } from "../../../hooks/Queries/shop/useSwagList"; function BrowseProducts() { - const { data: swagList } = useSwagList(); + const { data: swagList, isSuccess, isError, isPending } = useSwagList(); return ( @@ -15,11 +15,41 @@ function BrowseProducts() {
- {Array.isArray(swagList) && + {isSuccess && + swagList?.length > 0 && swagList.map((product) => ( ))}
+ {isSuccess && swagList?.length === 0 && ( +
+
+

No products available

+
+
+ )} + {isPending && ( +
+
+

Loading products...

+
+
+
+
+
+ )} + {isError && ( +
+
+

+ Error fetching products. Try again later +

+
+
+ )} ); diff --git a/src/pages/shop/sections/ItemHeader.jsx b/src/pages/shop/sections/ItemHeader.jsx index 155ff9a9..23091ebe 100644 --- a/src/pages/shop/sections/ItemHeader.jsx +++ b/src/pages/shop/sections/ItemHeader.jsx @@ -5,7 +5,9 @@ // import { Fragment, useState } from "react"; // import { useSwagList } from "../../../hooks/Queries/shop/useSwagList"; import PropTypes from "prop-types"; +import { useState } from "react"; import { useLocation, useParams } from "react-router-dom"; +import CartDrawer from "../../../components/shop/CartDrawer"; import CartIcon from "../../../components/shop/CartIcon"; import SectionWrapper from "../../../components/shop/SectionWrapper"; @@ -13,6 +15,7 @@ import SectionWrapper from "../../../components/shop/SectionWrapper"; function ItemHeader({ show }) { const { pathname } = useLocation(); const { id } = useParams(); + const [open, setOpen] = useState(false); const pathnames = pathname .split("/") @@ -66,7 +69,14 @@ function ItemHeader({ show }) { - + + {/* Search box */} {/*
diff --git a/src/pages/shop/sections/NewArrivals.jsx b/src/pages/shop/sections/NewArrivals.jsx index 8fb5c56a..b2c1d9f7 100644 --- a/src/pages/shop/sections/NewArrivals.jsx +++ b/src/pages/shop/sections/NewArrivals.jsx @@ -4,7 +4,7 @@ import SectionWrapper from "../../../components/shop/SectionWrapper"; import { useSwagList } from "../../../hooks/Queries/shop/useSwagList"; function NewProducts() { - const { data: swagList } = useSwagList(); + const { data: swagList, isSuccess, isError, isPending } = useSwagList(); return ( @@ -15,7 +15,8 @@ function NewProducts() {
- {Array.isArray(swagList) && + {isSuccess && + swagList?.length > 0 && swagList.slice(0, 10).map((product) => (
))}
+ {isSuccess && swagList?.length === 0 && ( +
+
+

+ No new products available +

+
+
+ )} + {isPending && ( +
+
+

Loading products...

+
+
+
+
+
+ )} + {isError && ( +
+
+

+ Error fetching products. Try again later +

+
+
+ )} ); diff --git a/src/pages/shop/sections/PopularItemsSection.jsx b/src/pages/shop/sections/PopularItemsSection.jsx index 50a6d03b..f750cc7b 100644 --- a/src/pages/shop/sections/PopularItemsSection.jsx +++ b/src/pages/shop/sections/PopularItemsSection.jsx @@ -1,13 +1,8 @@ -import { CiShoppingTag } from "react-icons/ci"; -import { LazyLoadImage } from "react-lazy-load-image-component"; -import { useNavigate } from "react-router-dom"; +import ProductCard from "../../../components/shop/ProductCard"; import { useSwagList } from "../../../hooks/Queries/shop/useSwagList"; -import formatPrice from "../../../utilities/formatPrice"; function PopularItemsSection() { - const navigate = useNavigate(); - - const { data: products } = useSwagList(); + const { data: products, isSuccess, isError, isPending } = useSwagList(); return (
@@ -21,61 +16,47 @@ function PopularItemsSection() {

Products similar to the one above

-
- {products - ?.slice(0, 8) - .map(({ stock, category, id, name, image, price }) => ( + {isSuccess && products?.length > 0 && ( +
+ {products?.slice(0, 8).map((product) => (
navigate(`/shop/item/${id}`)} - role="button" - tabIndex={0} - onKeyPress={(event) => { - if (event.key === "Enter" || event.key === " ") { - navigate(`/shop/item/${id}`); - } - }} + className="min-w-[100%] sm:min-w-[50%] lg:min-w-[33%] h-full" + key={product.id} > -
- -
-
-
-
-

- {name} -

-
- {stock ? ( -

- {stock} {stock === 1 ? "item" : "items"} left -

- ) : ( -

- Out of stock -

- )} -
-
-
-

- - {category} -

-
-

- KES {formatPrice(price)} -

-
-
+
))} -
+
+ )} + {isSuccess && products?.length === 0 && ( +
+
+

No products available

+
+
+ )} + {isPending && ( +
+
+

Loading products...

+
+
+
+
+
+ )} + {isError && ( +
+
+

+ Error fetching products. Try again later +

+
+
+ )}
); }