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-redux": "^9.1.2",
"redux": "^5.0.1",
"redux-persist": "^6.0.0",
"resend": "^3.5.0",
"sass": "^1.80.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 {
id: number;
@ -18,7 +18,7 @@ export const cartSlice = createSlice({
name: "cart",
initialState,
reducers: {
addToCart: (state: any, action: any) => {
addToCart: (state: any, action: PayloadAction<Product>) => {
const item = state.products.find((p:Product) => p.id === action.payload.id);
if(item) {
item.quantity += action.payload.quantity;
@ -31,10 +31,12 @@ export const cartSlice = createSlice({
},
resetCart: (state) => {
state.products = [];
}
},
},
});
export const { addToCart, removeFromCart, resetCart } = cartSlice.actions;
export default cartSlice.reducer;
export const dynamic = 'force-dynamic'

View File

@ -1,6 +1,5 @@
.cart{
z-index: 999;
background-color: white;
-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);

View File

@ -4,18 +4,27 @@ import Image from "next/image";
import { MdDeleteOutline } from "react-icons/md";
import { Button } from "@/components/ui/button";
import "./CartTab.css";
import { useSelector } from "react-redux";
import { useSelector, useDispatch } from "react-redux";
import type { RootState } from "@/lib/Store";
import { removeFromCart } from "@/app/redux/CartReducer";
import type { Product } from "@/app/redux/CartReducer";
const CartTab = () => {
const cartItems = true;
const dispatch = useDispatch();
// get the products from the cart
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 = [
// {
// id: 1,
@ -39,12 +48,13 @@ const CartTab = () => {
// },
// ];
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) => (
<div>
<div className="item flex gap-5 items-center mb-[30px] " key={item.id}>
<div className="relative w-[80px] h-[100px]">
<Image
src={item.image}
src={`${process.env.NEXT_PUBLIC_UPLOAD_URL + item.image}`}
fill
style={{ objectFit: "cover" }}
className=""
@ -53,16 +63,17 @@ const CartTab = () => {
</div>
<div className="details">
<h1>{item.title}</h1>
<p className="text-sm">{item.desc?.substring(0, 100)}</p>
{/* <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" />
<MdDeleteOutline className="delete-icon mt-16" onClick={() => dispatch(removeFromCart(item.id))} />
</div>
))}
<div className="total">
<span>SUBTOTAL</span>
<span>$123</span>
<span>${totalPrice()}</span>
</div>
</div>
))}
<Button className="bg-[#F45B1E] text-white checkout rounded-none w-full">PROCEED TO CHECKOUT</Button>
{/* <span className="reset">Reset Cart</span> */}
</div>

View File

@ -5,6 +5,10 @@ import { useMediaQuery } from "@/util/useMediaQuery";
import { FiShoppingCart } from "react-icons/fi";
import Image from "next/image";
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 = {
visible: {
@ -30,6 +34,9 @@ export default function Nav() {
const matches = useMediaQuery("(min-width: 1280px)");
// console.log(matches);
// get the products from the cart
const products = useSelector((state: RootState) => state.cart.products);
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">
{/* <svg
@ -79,7 +86,13 @@ export default function Nav() {
<div className="flex relative items-center justify-center" onClick={() => setOpen(!open)}>
<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 ">
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>
</div>
</div>

View File

@ -1,6 +1,16 @@
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '@/app/redux/slice'
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 = () => {
return configureStore({
reducer: {
@ -9,6 +19,8 @@ export const makeStore = () => {
})
}
export const persistor = persistStore(makeStore());
// Infer the type of makeStore
export type AppStore = ReturnType<typeof makeStore>
// Infer the `RootState` and `AppDispatch` types from the store itself