global state for cart working, need to fix cache

This commit is contained in:
Jacob Delgado 2024-11-28 12:25:00 -08:00
parent 86dd53cb28
commit 0c45e9067d
7 changed files with 67 additions and 29 deletions

Binary file not shown.

View File

@ -28,6 +28,7 @@
"react-icons": "^5.3.0", "react-icons": "^5.3.0",
"react-redux": "^9.1.2", "react-redux": "^9.1.2",
"redux": "^5.0.1", "redux": "^5.0.1",
"redux-persist": "^6.0.0",
"resend": "^3.5.0", "resend": "^3.5.0",
"sass": "^1.80.5", "sass": "^1.80.5",
"sharp": "^0.33.5", "sharp": "^0.33.5",

View File

@ -1,4 +1,4 @@
import { createSlice } from "@reduxjs/toolkit"; import { createSlice, PayloadAction } from "@reduxjs/toolkit";
export interface Product { export interface Product {
id: number; id: number;
@ -18,7 +18,7 @@ export const cartSlice = createSlice({
name: "cart", name: "cart",
initialState, initialState,
reducers: { reducers: {
addToCart: (state: any, action: any) => { addToCart: (state: any, action: PayloadAction<Product>) => {
const item = state.products.find((p:Product) => p.id === action.payload.id); const item = state.products.find((p:Product) => p.id === action.payload.id);
if(item) { if(item) {
item.quantity += action.payload.quantity; item.quantity += action.payload.quantity;
@ -31,10 +31,12 @@ export const cartSlice = createSlice({
}, },
resetCart: (state) => { resetCart: (state) => {
state.products = []; state.products = [];
} },
}, },
}); });
export const { addToCart, removeFromCart, resetCart } = cartSlice.actions; export const { addToCart, removeFromCart, resetCart } = cartSlice.actions;
export default cartSlice.reducer; export default cartSlice.reducer;
export const dynamic = 'force-dynamic'

View File

@ -1,6 +1,5 @@
.cart{ .cart{
z-index: 999; z-index: 999;
background-color: white;
-webkit-box-shadow: 0px 0px 7px -5px rgba(0,0,0,0.5); -webkit-box-shadow: 0px 0px 7px -5px rgba(0,0,0,0.5);
box-shadow: 0px 0px 7px -5px rgba(0,0,0,0.5); box-shadow: 0px 0px 7px -5px rgba(0,0,0,0.5);

View File

@ -4,18 +4,27 @@ import Image from "next/image";
import { MdDeleteOutline } from "react-icons/md"; import { MdDeleteOutline } from "react-icons/md";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import "./CartTab.css"; import "./CartTab.css";
import { useSelector } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
import type { RootState } from "@/lib/Store"; import type { RootState } from "@/lib/Store";
import { removeFromCart } from "@/app/redux/CartReducer";
import type { Product } from "@/app/redux/CartReducer"; import type { Product } from "@/app/redux/CartReducer";
const CartTab = () => { const CartTab = () => {
const cartItems = true; const cartItems = true;
const dispatch = useDispatch();
// get the products from the cart // get the products from the cart
const products = useSelector((state: RootState) => state.cart.products); const products = useSelector((state: RootState) => state.cart.products);
const totalPrice = () => {
let total = 0;
products?.forEach((item: Product) => {
total += item.price * item.quantity;
});
return total.toFixed(2);
};
// const data = [ // const data = [
// { // {
// id: 1, // id: 1,
@ -39,30 +48,32 @@ const CartTab = () => {
// }, // },
// ]; // ];
return ( return (
<div className="cart absolute p-5 text-slate-600 top-28 right-0"> <div className="cart absolute p-5 text-slate-600 top-28 right-0 bg-slate-200">
{products?.map((item: Product) => ( {products?.map((item: Product) => (
<div className="item flex gap-5 items-center mb-[30px] " key={item.id}> <div>
<div className="relative w-[80px] h-[100px]"> <div className="item flex gap-5 items-center mb-[30px] " key={item.id}>
<Image <div className="relative w-[80px] h-[100px]">
src={item.image} <Image
fill src={`${process.env.NEXT_PUBLIC_UPLOAD_URL + item.image}`}
style={{ objectFit: "cover" }} fill
className="" style={{ objectFit: "cover" }}
alt="item picture" className=""
/> alt="item picture"
/>
</div>
<div className="details">
<h1>{item.title}</h1>
{/* <p className="text-sm">{item.desc?.substring(0, 100)}</p> */}
<div className="price">{item.quantity} x ${item.price}</div>
</div>
<MdDeleteOutline className="delete-icon mt-16" onClick={() => dispatch(removeFromCart(item.id))} />
</div> </div>
<div className="details"> <div className="total">
<h1>{item.title}</h1> <span>SUBTOTAL</span>
<p className="text-sm">{item.desc?.substring(0, 100)}</p> <span>${totalPrice()}</span>
<div className="price">{item.quantity} x ${item.price}</div>
</div> </div>
<MdDeleteOutline className="delete-icon mt-16" />
</div> </div>
))} ))}
<div className="total">
<span>SUBTOTAL</span>
<span>$123</span>
</div>
<Button className="bg-[#F45B1E] text-white checkout rounded-none w-full">PROCEED TO CHECKOUT</Button> <Button className="bg-[#F45B1E] text-white checkout rounded-none w-full">PROCEED TO CHECKOUT</Button>
{/* <span className="reset">Reset Cart</span> */} {/* <span className="reset">Reset Cart</span> */}
</div> </div>

View File

@ -5,6 +5,10 @@ import { useMediaQuery } from "@/util/useMediaQuery";
import { FiShoppingCart } from "react-icons/fi"; import { FiShoppingCart } from "react-icons/fi";
import Image from "next/image"; import Image from "next/image";
import CartTab from "@/components/CartTab/CartTab"; import CartTab from "@/components/CartTab/CartTab";
import { useSelector } from "react-redux";
import type { RootState } from "@/lib/Store";
import Products from "@/app/products/page";
import type { Product } from "@/app/redux/CartReducer";
const navMotion = { const navMotion = {
visible: { visible: {
@ -30,8 +34,11 @@ export default function Nav() {
const matches = useMediaQuery("(min-width: 1280px)"); const matches = useMediaQuery("(min-width: 1280px)");
// console.log(matches); // console.log(matches);
// get the products from the cart
const products = useSelector((state: RootState) => state.cart.products);
return ( return (
<nav className="relative mx-8 mb-10 flex justify-between items-center pt-12 font-medium md:mx-16 lg:mx-32 text-white"> <nav className="relative mx-8 mb-10 flex justify-between items-center pt-12 font-medium md:mx-16 lg:mx-32 text-white">
{/* <svg {/* <svg
className="absolute bottom-0 left-1/2 -translate-x-1/2" className="absolute bottom-0 left-1/2 -translate-x-1/2"
width="250" width="250"
@ -78,8 +85,14 @@ export default function Nav() {
<a href="/about">About</a> <a href="/about">About</a>
<div className="flex relative items-center justify-center" onClick={() => setOpen(!open)}> <div className="flex relative items-center justify-center" onClick={() => setOpen(!open)}>
<FiShoppingCart className="text-lg lg:text-xl" /> <FiShoppingCart className="text-lg lg:text-xl" />
<span className="absolute text-white text-xs w-5 h-5 rounded-[50%] bg-orange-600 -top-2.5 -right-2.5 flex items-center justify-center"> <span className="absolute text-white text-xs w-5 h-5 rounded-[50%] bg-orange-600 -top-2.5 -right-2.5 flex items-center justify-center ">
0 {products?.map((item: Product) => {
if (item.quantity > 0 && item.quantity !== undefined) {
return <div key={item.id}>{item.quantity}</div>;
} else {
return <div>0</div>;
}
})}
</span> </span>
</div> </div>
</div> </div>

View File

@ -1,6 +1,16 @@
import { configureStore } from '@reduxjs/toolkit' import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '@/app/redux/slice' import counterReducer from '@/app/redux/slice'
import cartReducer from '@/app/redux/CartReducer' import cartReducer from '@/app/redux/CartReducer'
import { persistReducer, persistStore } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
const persistConfig = {
key: 'cart',
storage,
}
const persistedReducer = persistReducer(persistConfig, cartReducer)
export const makeStore = () => { export const makeStore = () => {
return configureStore({ return configureStore({
reducer: { reducer: {
@ -9,6 +19,8 @@ export const makeStore = () => {
}) })
} }
export const persistor = persistStore(makeStore());
// Infer the type of makeStore // Infer the type of makeStore
export type AppStore = ReturnType<typeof makeStore> export type AppStore = ReturnType<typeof makeStore>
// Infer the `RootState` and `AppDispatch` types from the store itself // Infer the `RootState` and `AppDispatch` types from the store itself