global state for cart working, need to fix cache
This commit is contained in:
parent
86dd53cb28
commit
0c45e9067d
Binary file not shown.
@ -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",
|
||||||
|
|||||||
@ -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'
|
||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user