rework of cart component
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { useCallback, useContext, useEffect, useState } from "react";
|
||||
import { v4 } from "uuid";
|
||||
import { AppContext } from "../../store/store";
|
||||
import { ActionType } from "../../store/store_types";
|
||||
import { Product } from '../../types/main';
|
||||
@@ -8,8 +9,19 @@ import CartItem from "./CartItem";
|
||||
|
||||
function Cart() {
|
||||
const [state, dispatch] = useContext(AppContext);
|
||||
const [contents, setContents] = useState<JSX.Element>();
|
||||
const [data, setData] = useState<any>();
|
||||
const [subtotal, setSubtotal] = useState('loading...');
|
||||
|
||||
// on mount
|
||||
useEffect(() => {
|
||||
if (!state) return;
|
||||
dispatch({ type: ActionType.UPDATESUBTOTAL, payload: getSubtotal(data) });
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(state.cart);
|
||||
setSubtotal(state.cart.subtotal);
|
||||
}, [state.cart.subtotal]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!state.cart.contents) return;
|
||||
@@ -39,15 +51,10 @@ function Cart() {
|
||||
setData(newProducts);
|
||||
}, [state]);
|
||||
|
||||
/**
|
||||
* PROBLEMATIC USEEFFECT BELOW
|
||||
* LOOP BEHAVIOR ON DISPATCH
|
||||
*/
|
||||
|
||||
useEffect(() => {
|
||||
let subtotal = getSubtotal(data);
|
||||
subtotal && dispatch({ type: ActionType.UPDATESUBTOTAL, payload: subtotal });
|
||||
}, [data, getSubtotal]);
|
||||
const updateQuantity = useCallback((product: Product, newQuantity: number) => {
|
||||
const updated = product;
|
||||
updated.quantity = newQuantity;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Page>
|
||||
@@ -60,12 +67,11 @@ function Cart() {
|
||||
}
|
||||
|
||||
<section id="cart-contents">
|
||||
{ data && data.map((product: Product) => <CartItem product={product} />) }
|
||||
{ data && data.map((product: Product) => <CartItem key={v4()} updateQuantity={updateQuantity} product={product} />) }
|
||||
</section>
|
||||
|
||||
<section id="subtotal">
|
||||
<p>Subtotal:</p>
|
||||
<p>{state.cart.subtotal || "Not found"}</p>
|
||||
<p>Subtotal: {subtotal}</p>
|
||||
</section>
|
||||
</Page>
|
||||
)
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
function CartItem({ product }: any) {
|
||||
function CartItem({ product, updateQuantity }: any) {
|
||||
const [quantity, setQuantity] = useState(product.quantity || 0);
|
||||
|
||||
useEffect(() => {
|
||||
updateQuantity(product, quantity);
|
||||
}, [quantity]);
|
||||
|
||||
return (
|
||||
<div className="cart-item-panel" key={v4()}>
|
||||
<div className="cart-item-panel">
|
||||
<strong>{product.name}</strong>
|
||||
<p>{product.price}</p>
|
||||
<p>Quantity: {product.quantity || "1"}</p>
|
||||
<p>Quantity: {quantity}</p>
|
||||
<input type="number" min="0" value={quantity} onChange={(e) => setQuantity(Number(e.target.value))}></input>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -23,13 +23,11 @@ function NavBar() {
|
||||
if (state === initialState) return;
|
||||
|
||||
if (state.user && state.user.headers?.authenticated) {
|
||||
console.log('authenticated!');
|
||||
setProfText(state.user.email);
|
||||
setLoggedIn(true);
|
||||
} else if (!state.user.authenticated) {
|
||||
setLoggedIn(false);
|
||||
}
|
||||
|
||||
}, [state]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useContext } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { addToCart } from "../../util/helpers";
|
||||
import { ActionType } from "../../store/store_types";
|
||||
import { AppContext } from "../../store/store";
|
||||
|
||||
export default function ProductCard({ productData }: any) {
|
||||
@@ -8,6 +8,10 @@ export default function ProductCard({ productData }: any) {
|
||||
const [state, dispatch] = useContext(AppContext);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const addToCart = () => {
|
||||
dispatch({ type: ActionType.ADDTOCART, payload: productData });
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="card product-card" key={`product-id-${id}`}>
|
||||
<div className="product-photo"></div>
|
||||
@@ -20,7 +24,7 @@ export default function ProductCard({ productData }: any) {
|
||||
|
||||
{
|
||||
state.user.headers && state.user.headers.authenticated ?
|
||||
<button onClick={() => addToCart(productData, dispatch)}>Add to Cart</button>
|
||||
<button onClick={addToCart}>Add to Cart</button>
|
||||
:
|
||||
<button onClick={() => navigate('/login')}>Login to add to your cart</button>
|
||||
}
|
||||
|
||||
@@ -24,9 +24,8 @@ function Products() {
|
||||
|
||||
useEffect(() => {
|
||||
if (!productData) return;
|
||||
console.log(productData);
|
||||
|
||||
let results = productData.map((each: ProductResponse) => {
|
||||
const results = productData.map((each: ProductResponse) => {
|
||||
return <ProductCard key={each.id} productData={each} />
|
||||
});
|
||||
|
||||
|
||||
@@ -29,16 +29,31 @@ export const reducer = (state: appState, action: userAction) => {
|
||||
user: payload
|
||||
}
|
||||
case ActionType.ADDTOCART:
|
||||
let updatedContents = state.cart.contents;
|
||||
console.log(action.payload);
|
||||
updatedContents.push(action.payload);
|
||||
|
||||
return {
|
||||
...state,
|
||||
cart: {
|
||||
...state.cart,
|
||||
contents: updatedContents
|
||||
let foundItem = state.cart.contents.find(item => item.id === action.payload.id);
|
||||
if (!foundItem) {
|
||||
let updatedContents = state.cart.contents;
|
||||
updatedContents.push(action.payload);
|
||||
return {
|
||||
...state,
|
||||
cart: {
|
||||
...state.cart,
|
||||
contents: updatedContents
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let updatedState = state;
|
||||
let updatedItem = foundItem;
|
||||
|
||||
if (updatedItem.quantity) {
|
||||
updatedItem.quantity += 1;
|
||||
} else {
|
||||
updatedItem.quantity = 2;
|
||||
}
|
||||
|
||||
updatedState.cart.contents = updatedState.cart.contents.filter(item => item.id !== action.payload.id);
|
||||
updatedState.cart.contents.push(updatedItem);
|
||||
|
||||
return updatedState;
|
||||
}
|
||||
case ActionType.UPDATESUBTOTAL:
|
||||
return {
|
||||
|
||||
1
client/src/types/main.d.ts
vendored
1
client/src/types/main.d.ts
vendored
@@ -28,6 +28,7 @@ export type Product = {
|
||||
category?: string
|
||||
price?: string | number,
|
||||
// when item is included in cart
|
||||
id?: number,
|
||||
quantity?: number,
|
||||
shortDescription?: string,
|
||||
longDescription?: string,
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import React from "react";
|
||||
import { ActionType, userAction } from "../store/store_types";
|
||||
import { Product } from "../types/main";
|
||||
|
||||
export const addToCart = (productData: Product, dispatch: React.Dispatch<userAction>): any => {
|
||||
dispatch({ type: ActionType.ADDTOCART, payload: productData });
|
||||
}
|
||||
|
||||
export const getSubtotal = (cartData: Product[]) => {
|
||||
let total = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user