From 3715bef2a14aaffe01b91bd74abf077e720675ab Mon Sep 17 00:00:00 2001 From: marArcz Date: Mon, 12 Aug 2024 15:21:00 +0800 Subject: [PATCH] fixed all issues --- package-lock.json | 1 + src/Components/Cart.jsx | 26 +++++-- src/Components/NavBar.jsx | 4 +- src/Components/ProductFilters.jsx | 46 ++++++++++-- src/Components/ProductTable.jsx | 119 +++++++++++++++++++++--------- src/Pages/Home.jsx | 18 ++++- todo.md | 8 ++ 7 files changed, 172 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index d01ddfa..bbd664e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "react-ecommerce", "version": "0.0.1", "dependencies": { "@headlessui/react": "^1.6.0", diff --git a/src/Components/Cart.jsx b/src/Components/Cart.jsx index 917b7a1..7d5524b 100644 --- a/src/Components/Cart.jsx +++ b/src/Components/Cart.jsx @@ -1,8 +1,17 @@ import { Dialog, Transition } from "@headlessui/react"; -import { XIcon } from "@heroicons/react/outline"; +import { ShoppingCartIcon, XIcon } from "@heroicons/react/outline"; import React, { Fragment } from "react"; export default function Cart({ open, setOpen, cart, updateCart }) { + + const subtotal = () => { + let total = 0; + for(let cartItem of cart){ + total += cartItem.price * cartItem.quantity + } + return total.toFixed(2); + } + return ( - + setOpen(false)} className="absolute inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
@@ -51,7 +60,6 @@ export default function Cart({ open, setOpen, cart, updateCart }) {
-
    @@ -101,11 +109,19 @@ export default function Cart({ open, setOpen, cart, updateCart }) {
- + {/* show Empty Cart text when no cart is empty */} + {cart.length === 0 && ( +
+
+ +

Your Cart is Empty.

+
+
+ )}

Subtotal

-

$262.00

+

${subtotal()}

Shipping and taxes calculated at checkout.

diff --git a/src/Components/NavBar.jsx b/src/Components/NavBar.jsx index b1d0db9..cccd879 100644 --- a/src/Components/NavBar.jsx +++ b/src/Components/NavBar.jsx @@ -1,7 +1,7 @@ import { ShoppingBagIcon } from "@heroicons/react/outline"; import React from "react"; -export default function NavBar({ setOpen }) { +export default function NavBar({ setOpen, cartSize=0 }) { return (
@@ -41,7 +41,7 @@ export default function NavBar({ setOpen }) { className="flex-shrink-0 h-6 w-6 text-gray-400 group-hover:text-gray-500" aria-hidden="true" /> - 0 + {cartSize} items in cart, view bag
diff --git a/src/Components/ProductFilters.jsx b/src/Components/ProductFilters.jsx index 0f3262a..98ed329 100644 --- a/src/Components/ProductFilters.jsx +++ b/src/Components/ProductFilters.jsx @@ -1,12 +1,44 @@ import { Disclosure, Menu, Transition } from "@headlessui/react"; import { ChevronDownIcon, FilterIcon } from "@heroicons/react/solid"; -import React, { Fragment } from "react"; +import React, { Fragment, useState } from "react"; function classNames(...classes) { return classes.filter(Boolean).join(" "); } export default function ProductFilters({ filterOptions, setFilterOptions, sortOptions, setSortOptions }) { + const [filterCount, setFilterCount] = useState(0) + + const handleUpdateOption = (category, index, checked) => { + let newFilterOptions = { ...filterOptions }; + newFilterOptions[category][index] = { + ...newFilterOptions[category][index], + checked + } + // update filter options + setFilterOptions(newFilterOptions); + updateFilterCount(newFilterOptions) + } + + const updateFilterCount = (newFilterOptions) => { + // count enabled filters + let priceFilterCount = newFilterOptions.price.filter(filter => filter.checked).length; + let colorFilterCount = newFilterOptions.color.filter(filter => filter.checked).length; + + // update filter count + setFilterCount(priceFilterCount + colorFilterCount); + } + + const handleClearFilters = () => { + let newFilterOptions = { + price: filterOptions.price.map(f => ({ ...f, checked: false })), + color: filterOptions.color.map(f => ({ ...f, checked: false })), + } + + setFilterOptions(newFilterOptions); + updateFilterCount(newFilterOptions) + } + return (
-
@@ -47,8 +79,9 @@ export default function ProductFilters({ filterOptions, setFilterOptions, sortOp name="price[]" defaultValue={option.minValue} type="checkbox" + onChange={(e) => handleUpdateOption('price', optionIdx, e.target.checked)} + checked={option.checked} className="flex-shrink-0 h-4 w-4 border-gray-300 rounded text-black focus:ring-black" - defaultChecked={option.checked} />
-

{product.name}

-

${product.price}

-
- ))} + updateCart(newCart); + }} + > + Add To Cart + + +

{product.name}

+

${product.price}

+ + ))} diff --git a/src/Pages/Home.jsx b/src/Pages/Home.jsx index 1a5d5d9..83c332e 100644 --- a/src/Pages/Home.jsx +++ b/src/Pages/Home.jsx @@ -1,15 +1,27 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import Cart from "../Components/Cart"; import NavBar from "../Components/NavBar"; import ProductTable from "../Components/ProductTable"; function Home() { const [open, setOpen] = useState(false); - const [cart, updateCart] = useState([]); + const [cart, updateCart] = useState(JSON.parse(localStorage.getItem('cart') || '[]')); + + useEffect(() => { + localStorage.setItem('cart',JSON.stringify(cart)); + }, [cart]) + + const cartSize = () => { + let size = 0; + for(let cartItem of cart){ + size += cartItem.quantity + } + return size; + } return (
- +
diff --git a/todo.md b/todo.md index e69de29..f7f4058 100644 --- a/todo.md +++ b/todo.md @@ -0,0 +1,8 @@ +- ✔ Sort products by price and release date +- ✔ Cart Persistence on Refresh +- ✔ Add Product Filters Functionality +- ✔ Product Fetch is Causing Infinite Loop +- ✔ Need to display "Empty Cart" when cart is empty on cart page +- ✔ Update Cart in Nav with Cart Size +- ✔ Cart not closing when user clicks gray region +- ✔ Subtotal Is not Implemented on Cart Page \ No newline at end of file