144 lines
3.9 KiB
TypeScript
144 lines
3.9 KiB
TypeScript
"use client"
|
|
|
|
import { createContext, useContext, useState, useEffect, ReactNode } from "react"
|
|
import { useToast } from "@/components/ui/use-toast"
|
|
|
|
// Типы для корзины
|
|
export interface CartItem {
|
|
id: number
|
|
variant_id: number
|
|
product_id: number
|
|
name: string
|
|
price: number
|
|
image: string | object
|
|
quantity: number
|
|
size?: string
|
|
color?: string
|
|
}
|
|
|
|
interface CartContextType {
|
|
items: CartItem[]
|
|
addItem: (item: CartItem) => void
|
|
removeItem: (id: number) => void
|
|
updateQuantity: (id: number, quantity: number) => void
|
|
clearCart: () => void
|
|
itemCount: number
|
|
subtotal: number
|
|
}
|
|
|
|
// Создание контекста
|
|
const CartContext = createContext<CartContextType | undefined>(undefined)
|
|
|
|
// Провайдер контекста
|
|
export function CartProvider({ children }: { children: ReactNode }) {
|
|
const [items, setItems] = useState<CartItem[]>([])
|
|
const { toast } = useToast()
|
|
|
|
// Загрузка корзины из localStorage при инициализации
|
|
useEffect(() => {
|
|
const storedCart = localStorage.getItem("cart")
|
|
if (storedCart) {
|
|
try {
|
|
setItems(JSON.parse(storedCart))
|
|
} catch (e) {
|
|
console.error("Ошибка при загрузке корзины из localStorage:", e)
|
|
localStorage.removeItem("cart")
|
|
}
|
|
}
|
|
}, [])
|
|
|
|
// Сохранение корзины в localStorage при изменении
|
|
useEffect(() => {
|
|
localStorage.setItem("cart", JSON.stringify(items))
|
|
}, [items])
|
|
|
|
// Добавление товара в корзину
|
|
const addItem = (item: CartItem) => {
|
|
setItems(prevItems => {
|
|
// Проверяем, есть ли уже такой товар в корзине
|
|
const existingItemIndex = prevItems.findIndex(
|
|
i => i.variant_id === item.variant_id
|
|
)
|
|
|
|
// Если товар уже есть, увеличиваем количество
|
|
if (existingItemIndex > -1) {
|
|
const newItems = [...prevItems]
|
|
newItems[existingItemIndex].quantity += item.quantity
|
|
|
|
toast({
|
|
title: "Товар добавлен в корзину",
|
|
description: `${item.name} (${item.quantity} шт.)`,
|
|
})
|
|
|
|
return newItems
|
|
}
|
|
|
|
// Если товара нет, добавляем новый
|
|
toast({
|
|
title: "Товар добавлен в корзину",
|
|
description: `${item.name} (${item.quantity} шт.)`,
|
|
})
|
|
|
|
return [...prevItems, item]
|
|
})
|
|
}
|
|
|
|
// Удаление товара из корзины
|
|
const removeItem = (id: number) => {
|
|
setItems(prevItems => prevItems.filter(item => item.id !== id))
|
|
|
|
toast({
|
|
title: "Товар удален из корзины",
|
|
})
|
|
}
|
|
|
|
// Обновление количества товара
|
|
const updateQuantity = (id: number, quantity: number) => {
|
|
setItems(prevItems =>
|
|
prevItems.map(item =>
|
|
item.id === id ? { ...item, quantity } : item
|
|
)
|
|
)
|
|
}
|
|
|
|
// Очистка корзины
|
|
const clearCart = () => {
|
|
setItems([])
|
|
|
|
toast({
|
|
title: "Корзина очищена",
|
|
})
|
|
}
|
|
|
|
// Подсчет общего количества товаров
|
|
const itemCount = items.reduce((total, item) => total + item.quantity, 0)
|
|
|
|
// Подсчет общей стоимости
|
|
const subtotal = items.reduce(
|
|
(total, item) => total + item.price * item.quantity,
|
|
0
|
|
)
|
|
|
|
const value = {
|
|
items,
|
|
addItem,
|
|
removeItem,
|
|
updateQuantity,
|
|
clearCart,
|
|
itemCount,
|
|
subtotal
|
|
}
|
|
|
|
return <CartContext.Provider value={value}>{children}</CartContext.Provider>
|
|
}
|
|
|
|
// Хук для использования корзины
|
|
export function useCart() {
|
|
const context = useContext(CartContext)
|
|
|
|
if (context === undefined) {
|
|
throw new Error("useCart must be used within a CartProvider")
|
|
}
|
|
|
|
return context
|
|
}
|