183 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'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
}