From 6e3e23faaad33522ebdbc67d62c579dde69be24d Mon Sep 17 00:00:00 2001 From: Mikayla Dobson <93477693+innocuous-symmetry@users.noreply.github.com> Date: Mon, 4 Jul 2022 14:13:32 -0500 Subject: [PATCH] functionality for product quantity in cart, in progress subtotal calculation --- client/src/components/Cart/Cart.tsx | 50 +++++++++++++++++++++---- client/src/components/Cart/CartItem.tsx | 5 ++- client/src/components/Navbar.tsx | 4 +- client/src/store/store.ts | 8 ++++ client/src/store/store_types.ts | 3 +- client/src/types/main.d.ts | 7 +++- client/src/util/helpers.ts | 17 +++++++++ 7 files changed, 80 insertions(+), 14 deletions(-) diff --git a/client/src/components/Cart/Cart.tsx b/client/src/components/Cart/Cart.tsx index 9c544e3..b0c67bd 100644 --- a/client/src/components/Cart/Cart.tsx +++ b/client/src/components/Cart/Cart.tsx @@ -1,22 +1,53 @@ import { useContext, useEffect, useState } from "react"; import { AppContext } from "../../store/store"; +import { ActionType } from "../../store/store_types"; import { Product } from '../../types/main'; +import { getSubtotal } from "../../util/helpers"; import Page from "../../util/Page"; import CartItem from "./CartItem"; function Cart() { const [state, dispatch] = useContext(AppContext); const [contents, setContents] = useState(); + const [data, setData] = useState(); useEffect(() => { - setContents( - state.cart.contents.map((product: Product) => ) - ) - }, [state, setContents]); + if (!state.cart.contents) return; + let newProducts: Array = []; + for (let item of state.cart.contents) { + const withQuantity = { + ...item, + quantity: 1 + } + const foundItem = newProducts.findIndex((res) => res.name === item.name); + if (foundItem === -1) { + newProducts.push(withQuantity); + } else { + // @ts-ignore + newProducts[foundItem].quantity += 1; + } + } + + for (let item of newProducts) { + if (typeof item.quantity !== 'number') { + throw new Error("Quantity is possibly undefined in Cart.tsx"); + } + item.quantity = item.quantity / 2; + } + + setData(newProducts); + }, [state]); + + /** + * PROBLEMATIC USEEFFECT BELOW + * LOOP BEHAVIOR ON DISPATCH + */ + useEffect(() => { - console.log(contents); - }, [contents]); + let subtotal = getSubtotal(data); + subtotal && dispatch({ type: ActionType.UPDATESUBTOTAL, payload: subtotal }); + }, [data, getSubtotal]); return ( @@ -29,7 +60,12 @@ function Cart() { }
- {contents || null} + { data && data.map((product: Product) => ) } +
+ +
+

Subtotal:

+

{state.cart.subtotal || "Not found"}

) diff --git a/client/src/components/Cart/CartItem.tsx b/client/src/components/Cart/CartItem.tsx index 9074b01..f627398 100644 --- a/client/src/components/Cart/CartItem.tsx +++ b/client/src/components/Cart/CartItem.tsx @@ -1,8 +1,11 @@ +import { v4 } from "uuid"; + function CartItem({ product }: any) { return ( -
+
{product.name}

{product.price}

+

Quantity: {product.quantity || "1"}

) } diff --git a/client/src/components/Navbar.tsx b/client/src/components/Navbar.tsx index 4ef6b33..fcfa77e 100644 --- a/client/src/components/Navbar.tsx +++ b/client/src/components/Navbar.tsx @@ -22,9 +22,7 @@ function NavBar() { useEffect(() => { if (state === initialState) return; - console.log(state.user); - - if (state.user && state.user.headers.authenticated) { + if (state.user && state.user.headers?.authenticated) { console.log('authenticated!'); setProfText(state.user.email); setLoggedIn(true); diff --git a/client/src/store/store.ts b/client/src/store/store.ts index eea3d94..43c4fb9 100644 --- a/client/src/store/store.ts +++ b/client/src/store/store.ts @@ -40,6 +40,14 @@ export const reducer = (state: appState, action: userAction) => { contents: updatedContents } } + case ActionType.UPDATESUBTOTAL: + return { + ...state, + cart: { + ...state.cart, + subtotal: action.payload + } + } default: return state; } diff --git a/client/src/store/store_types.ts b/client/src/store/store_types.ts index c1899dd..b2b1474 100644 --- a/client/src/store/store_types.ts +++ b/client/src/store/store_types.ts @@ -9,7 +9,8 @@ export enum ActionType { UPDATEONE, SEARCH, USERLOGIN, - ADDTOCART + ADDTOCART, + UPDATESUBTOTAL } export interface userAction { diff --git a/client/src/types/main.d.ts b/client/src/types/main.d.ts index 30ce9dc..0655e7d 100644 --- a/client/src/types/main.d.ts +++ b/client/src/types/main.d.ts @@ -26,7 +26,9 @@ export type Product = { name: string, productID?: number, category?: string - price?: string | number + price?: string | number, + // when item is included in cart + quantity?: number, shortDescription?: string, longDescription?: string, description?: string @@ -47,7 +49,8 @@ export type Cart = { cartID: number, userInfo: userInfo, checkedOut: boolean, - contents: Product[] + contents: Product[], + subTotal?: number } export type Order = { diff --git a/client/src/util/helpers.ts b/client/src/util/helpers.ts index 3481f3a..b07e7c6 100644 --- a/client/src/util/helpers.ts +++ b/client/src/util/helpers.ts @@ -4,4 +4,21 @@ import { Product } from "../types/main"; export const addToCart = (productData: Product, dispatch: React.Dispatch): any => { dispatch({ type: ActionType.ADDTOCART, payload: productData }); +} + +export const getSubtotal = (cartData: Product[]) => { + let total = 0; + + if (!cartData) return; + + for (let item of cartData) { + if (typeof item.price === 'number') { + total += (item.price * (item.quantity || 1)); + } else { + const converted = Number(item.price); + total += (converted * (item.quantity || 1)); + } + } + + return total; } \ No newline at end of file