183 lines
6.3 KiB
TypeScript
183 lines
6.3 KiB
TypeScript
'use client'
|
||
|
||
import React, { createContext, useContext, useReducer, useEffect, useCallback, useState } from 'react'
|
||
import axios from 'axios'
|
||
import { ProductType } from '@/type/ProductType'
|
||
|
||
import { BaseURL } from '@/utils/BaseUrl'
|
||
|
||
interface CartItem extends ProductType {
|
||
quantity: number
|
||
selectedSize: string
|
||
selectedColor: string
|
||
_id?: string // Support MongoDB _id format
|
||
}
|
||
|
||
interface CartState {
|
||
cartArray: CartItem[]
|
||
}
|
||
|
||
type CartAction =
|
||
| { type: 'ADD_TO_CART'; payload: CartItem }
|
||
| { type: 'REMOVE_FROM_CART'; payload: string }
|
||
| { type: 'UPDATE_CART'; payload: { itemId: string; quantity: number; selectedSize: string; selectedColor: string } }
|
||
| { type: 'LOAD_CART'; payload: CartItem[] }
|
||
| { type: 'CLEAR_CART' }
|
||
|
||
interface CartContextProps {
|
||
cartState: CartState
|
||
addToCart: (item: CartItem) => void
|
||
removeFromCart: (itemId: string) => void
|
||
updateCart: (itemId: string, quantity: number, selectedSize: string, selectedColor: string) => void
|
||
loadCart: (items: CartItem[]) => void
|
||
clearCart: () => void
|
||
refreshCart: () => Promise<void>
|
||
loading: boolean
|
||
}
|
||
|
||
const CartContext = createContext<CartContextProps | undefined>(undefined)
|
||
|
||
const cartReducer = (state: CartState, action: CartAction): CartState => {
|
||
switch (action.type) {
|
||
case 'ADD_TO_CART':
|
||
return { ...state, cartArray: [...state.cartArray, action.payload] }
|
||
case 'REMOVE_FROM_CART':
|
||
return { ...state, cartArray: state.cartArray.filter((item) => item.id !== action.payload) }
|
||
case 'UPDATE_CART':
|
||
return {
|
||
...state,
|
||
cartArray: state.cartArray.map((item) =>
|
||
item.id === action.payload.itemId
|
||
? { ...item, quantity: action.payload.quantity, selectedSize: action.payload.selectedSize, selectedColor: action.payload.selectedColor }
|
||
: item
|
||
),
|
||
}
|
||
case 'LOAD_CART':
|
||
return { ...state, cartArray: action.payload }
|
||
case 'CLEAR_CART':
|
||
return { ...state, cartArray: [] }
|
||
default:
|
||
return state
|
||
}
|
||
}
|
||
|
||
// Helper functions for localStorage
|
||
const CART_KEY = 'guestCart' // Using same key for all users now
|
||
|
||
const saveCartToLocalStorage = (cart: CartItem[]) => {
|
||
try {
|
||
console.log("💾 saveCartToLocalStorage called with:", cart);
|
||
localStorage.setItem(CART_KEY, JSON.stringify(cart))
|
||
console.log("✅ Cart saved to localStorage successfully");
|
||
} catch (error) {
|
||
console.error('❌ Error saving cart to localStorage:', error)
|
||
}
|
||
}
|
||
|
||
const loadCartFromLocalStorage = (): CartItem[] => {
|
||
try {
|
||
const cartString = localStorage.getItem(CART_KEY)
|
||
console.log("📖 loadCartFromLocalStorage - Raw data:", cartString);
|
||
console.log("📖 loadCartFromLocalStorage - Type:", typeof cartString);
|
||
console.log("📖 loadCartFromLocalStorage - Length:", cartString?.length);
|
||
|
||
// Check if it's the string "[]" vs actual empty
|
||
if (cartString === "[]") {
|
||
console.warn("⚠️ localStorage contains empty array string '[]'");
|
||
}
|
||
|
||
const cart = cartString ? JSON.parse(cartString) : []
|
||
console.log("📖 loadCartFromLocalStorage - Parsed cart:", cart);
|
||
console.log("📖 loadCartFromLocalStorage - Parsed cart length:", cart.length);
|
||
return cart
|
||
} catch (error) {
|
||
console.error('❌ Error loading cart from localStorage:', error)
|
||
return []
|
||
}
|
||
}
|
||
|
||
const clearCartFromLocalStorage = () => {
|
||
try {
|
||
localStorage.removeItem(CART_KEY)
|
||
console.log("✅ localStorage cleared");
|
||
} catch (error) {
|
||
console.error('Error clearing cart from localStorage:', error)
|
||
}
|
||
}
|
||
|
||
export const CartProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||
const [cartState, dispatch] = useReducer(cartReducer, { cartArray: [] })
|
||
const [loading, setLoading] = useState(true)
|
||
const [isInitialLoad, setIsInitialLoad] = useState(true)
|
||
|
||
const refreshCart = useCallback(async () => {
|
||
// Load from localStorage for ALL users (both logged-in and guest)
|
||
console.log("🔄 refreshCart called");
|
||
const cart = loadCartFromLocalStorage()
|
||
console.log("🔄 refreshCart - Dispatching LOAD_CART with:", cart);
|
||
dispatch({ type: 'LOAD_CART', payload: cart })
|
||
setLoading(false)
|
||
setIsInitialLoad(false) // Mark that initial load is complete
|
||
}, [])
|
||
|
||
// Load cart initially
|
||
useEffect(() => {
|
||
refreshCart()
|
||
}, [refreshCart])
|
||
|
||
// Sync cart to localStorage for ALL users whenever cartState changes
|
||
// BUT skip on initial load to prevent overwriting with empty cart
|
||
useEffect(() => {
|
||
console.log("🔔 useEffect triggered - loading:", loading, "isInitialLoad:", isInitialLoad, "cartArray:", cartState.cartArray);
|
||
if (!loading && !isInitialLoad) {
|
||
console.log("💾 Calling saveCartToLocalStorage...");
|
||
saveCartToLocalStorage(cartState.cartArray)
|
||
} else {
|
||
if (loading) {
|
||
console.log("⏳ Skipping save - still loading");
|
||
}
|
||
if (isInitialLoad) {
|
||
console.log("🚀 Skipping save - initial load (preventing empty cart overwrite)");
|
||
}
|
||
}
|
||
}, [cartState.cartArray, loading, isInitialLoad])
|
||
|
||
const addToCart = (item: CartItem) => {
|
||
console.log("➕ addToCart:", item);
|
||
dispatch({ type: 'ADD_TO_CART', payload: item })
|
||
}
|
||
|
||
const removeFromCart = (itemId: string) => {
|
||
console.log("➖ removeFromCart:", itemId);
|
||
dispatch({ type: 'REMOVE_FROM_CART', payload: itemId })
|
||
}
|
||
|
||
const updateCart = (itemId: string, quantity: number, selectedSize: string, selectedColor: string) => {
|
||
console.log("🔄 updateCart:", { itemId, quantity, selectedSize, selectedColor });
|
||
dispatch({ type: 'UPDATE_CART', payload: { itemId, quantity, selectedSize, selectedColor } })
|
||
}
|
||
|
||
const loadCart = (items: CartItem[]) => {
|
||
console.log("📥 loadCart:", items);
|
||
dispatch({ type: 'LOAD_CART', payload: items })
|
||
}
|
||
const clearCart = () => {
|
||
console.log("🗑️ Clearing cart - Redux store and localStorage");
|
||
dispatch({ type: 'CLEAR_CART' })
|
||
clearCartFromLocalStorage()
|
||
console.log("✅ Cart cleared - cartArray should be empty now");
|
||
}
|
||
|
||
return (
|
||
<CartContext.Provider value={{ cartState, addToCart, removeFromCart, updateCart, loadCart, clearCart, refreshCart, loading }}>
|
||
{children}
|
||
</CartContext.Provider>
|
||
)
|
||
}
|
||
|
||
export const useCart = () => {
|
||
const context = useContext(CartContext)
|
||
if (!context) throw new Error('useCart must be used within a CartProvider')
|
||
return context
|
||
}
|