functionality for product quantity in cart, in progress subtotal calculation
This commit is contained in:
@@ -1,22 +1,53 @@
|
|||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import { AppContext } from "../../store/store";
|
import { AppContext } from "../../store/store";
|
||||||
|
import { ActionType } from "../../store/store_types";
|
||||||
import { Product } from '../../types/main';
|
import { Product } from '../../types/main';
|
||||||
|
import { getSubtotal } from "../../util/helpers";
|
||||||
import Page from "../../util/Page";
|
import Page from "../../util/Page";
|
||||||
import CartItem from "./CartItem";
|
import CartItem from "./CartItem";
|
||||||
|
|
||||||
function Cart() {
|
function Cart() {
|
||||||
const [state, dispatch] = useContext(AppContext);
|
const [state, dispatch] = useContext(AppContext);
|
||||||
const [contents, setContents] = useState<JSX.Element>();
|
const [contents, setContents] = useState<JSX.Element>();
|
||||||
|
const [data, setData] = useState<any>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setContents(
|
if (!state.cart.contents) return;
|
||||||
state.cart.contents.map((product: Product) => <CartItem product={product} />)
|
|
||||||
)
|
|
||||||
}, [state, setContents]);
|
|
||||||
|
|
||||||
|
let newProducts: Array<Product> = [];
|
||||||
|
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(() => {
|
useEffect(() => {
|
||||||
console.log(contents);
|
let subtotal = getSubtotal(data);
|
||||||
}, [contents]);
|
subtotal && dispatch({ type: ActionType.UPDATESUBTOTAL, payload: subtotal });
|
||||||
|
}, [data, getSubtotal]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
@@ -29,7 +60,12 @@ function Cart() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
<section id="cart-contents">
|
<section id="cart-contents">
|
||||||
{contents || null}
|
{ data && data.map((product: Product) => <CartItem product={product} />) }
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="subtotal">
|
||||||
|
<p>Subtotal:</p>
|
||||||
|
<p>{state.cart.subtotal || "Not found"}</p>
|
||||||
</section>
|
</section>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
function CartItem({ product }: any) {
|
function CartItem({ product }: any) {
|
||||||
return (
|
return (
|
||||||
<div className="cart-item-panel">
|
<div className="cart-item-panel" key={v4()}>
|
||||||
<strong>{product.name}</strong>
|
<strong>{product.name}</strong>
|
||||||
<p>{product.price}</p>
|
<p>{product.price}</p>
|
||||||
|
<p>Quantity: {product.quantity || "1"}</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ function NavBar() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (state === initialState) return;
|
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!');
|
console.log('authenticated!');
|
||||||
setProfText(state.user.email);
|
setProfText(state.user.email);
|
||||||
setLoggedIn(true);
|
setLoggedIn(true);
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ export const reducer = (state: appState, action: userAction) => {
|
|||||||
contents: updatedContents
|
contents: updatedContents
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case ActionType.UPDATESUBTOTAL:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
cart: {
|
||||||
|
...state.cart,
|
||||||
|
subtotal: action.payload
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ export enum ActionType {
|
|||||||
UPDATEONE,
|
UPDATEONE,
|
||||||
SEARCH,
|
SEARCH,
|
||||||
USERLOGIN,
|
USERLOGIN,
|
||||||
ADDTOCART
|
ADDTOCART,
|
||||||
|
UPDATESUBTOTAL
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface userAction {
|
export interface userAction {
|
||||||
|
|||||||
7
client/src/types/main.d.ts
vendored
7
client/src/types/main.d.ts
vendored
@@ -26,7 +26,9 @@ export type Product = {
|
|||||||
name: string,
|
name: string,
|
||||||
productID?: number,
|
productID?: number,
|
||||||
category?: string
|
category?: string
|
||||||
price?: string | number
|
price?: string | number,
|
||||||
|
// when item is included in cart
|
||||||
|
quantity?: number,
|
||||||
shortDescription?: string,
|
shortDescription?: string,
|
||||||
longDescription?: string,
|
longDescription?: string,
|
||||||
description?: string
|
description?: string
|
||||||
@@ -47,7 +49,8 @@ export type Cart = {
|
|||||||
cartID: number,
|
cartID: number,
|
||||||
userInfo: userInfo,
|
userInfo: userInfo,
|
||||||
checkedOut: boolean,
|
checkedOut: boolean,
|
||||||
contents: Product[]
|
contents: Product[],
|
||||||
|
subTotal?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Order = {
|
export type Order = {
|
||||||
|
|||||||
@@ -4,4 +4,21 @@ import { Product } from "../types/main";
|
|||||||
|
|
||||||
export const addToCart = (productData: Product, dispatch: React.Dispatch<userAction>): any => {
|
export const addToCart = (productData: Product, dispatch: React.Dispatch<userAction>): any => {
|
||||||
dispatch({ type: ActionType.ADDTOCART, payload: productData });
|
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;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user