203 lines
6.1 KiB
TypeScript
203 lines
6.1 KiB
TypeScript
"use client";
|
||
|
||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||
import { useToast } from '@/components/ui/use-toast';
|
||
import type { CartItemCreate } from '@/lib/cart';
|
||
import type { Cart } from '@/lib/cart-store';
|
||
import cartStore from '@/lib/cart-store';
|
||
import { apiStatus } from '@/lib/api';
|
||
|
||
// Синхронизация упрощена, так как кеширование реализовано на бэкенде
|
||
|
||
export function useCart() {
|
||
const [cart, setCart] = useState<Cart>(cartStore.getState());
|
||
const [loading, setLoading] = useState(false);
|
||
const [error, setError] = useState<string | null>(null);
|
||
const { toast } = useToast();
|
||
const syncInProgressRef = useRef(false);
|
||
|
||
// Подписка на изменения корзины
|
||
useEffect(() => {
|
||
const unsubscribe = cartStore.subscribe(() => {
|
||
setCart(cartStore.getState());
|
||
});
|
||
return () => unsubscribe();
|
||
}, []);
|
||
|
||
// Проверка аутентификации и синхронизация корзины
|
||
useEffect(() => {
|
||
if (apiStatus.isAuthenticated && !syncInProgressRef.current) {
|
||
synchronizeCart();
|
||
}
|
||
}, [apiStatus.isAuthenticated]);
|
||
|
||
// Синхронизация локальной корзины с сервером
|
||
const synchronizeCart = useCallback(async () => {
|
||
try {
|
||
// Если синхронизация уже идет, не запускаем новую
|
||
if (syncInProgressRef.current) return;
|
||
|
||
syncInProgressRef.current = true;
|
||
setLoading(true);
|
||
|
||
await cartStore.syncWithServer();
|
||
} catch (err) {
|
||
setError('Не удалось синхронизировать корзину');
|
||
toast({
|
||
variant: 'destructive',
|
||
title: 'Ошибка',
|
||
description: 'Не удалось синхронизировать корзину',
|
||
});
|
||
} finally {
|
||
setLoading(false);
|
||
syncInProgressRef.current = false;
|
||
}
|
||
}, [toast]);
|
||
|
||
// Добавление товара в корзину
|
||
const addToCart = useCallback(async (item: CartItemCreate) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const result = await cartStore.addToCart(item);
|
||
|
||
if (result) {
|
||
toast({
|
||
title: 'Товар добавлен',
|
||
description: 'Товар успешно добавлен в корзину',
|
||
});
|
||
return true;
|
||
} else {
|
||
toast({
|
||
variant: 'destructive',
|
||
title: 'Ошибка',
|
||
description: 'Не удалось добавить товар в корзину',
|
||
});
|
||
return false;
|
||
}
|
||
} catch (err) {
|
||
setError('Не удалось добавить товар в корзину');
|
||
toast({
|
||
variant: 'destructive',
|
||
title: 'Ошибка',
|
||
description: 'Не удалось добавить товар в корзину',
|
||
});
|
||
return false;
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, [toast]);
|
||
|
||
// Обновление количества товара в корзине
|
||
const updateCartItem = useCallback(async (id: number, quantity: number) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const result = await cartStore.updateCartItem(id, quantity);
|
||
|
||
if (!result) {
|
||
toast({
|
||
variant: 'destructive',
|
||
title: 'Ошибка',
|
||
description: 'Не удалось обновить товар в корзине',
|
||
});
|
||
}
|
||
return result;
|
||
} catch (err) {
|
||
setError('Не удалось обновить товар в корзине');
|
||
toast({
|
||
variant: 'destructive',
|
||
title: 'Ошибка',
|
||
description: 'Не удалось обновить товар в корзине',
|
||
});
|
||
return false;
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, [toast]);
|
||
|
||
// Удаление товара из корзины
|
||
const removeFromCart = useCallback(async (id: number) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const result = await cartStore.removeFromCart(id);
|
||
|
||
if (result) {
|
||
toast({
|
||
title: 'Товар удален',
|
||
description: 'Товар успешно удален из корзины',
|
||
});
|
||
return true;
|
||
} else {
|
||
toast({
|
||
variant: 'destructive',
|
||
title: 'Ошибка',
|
||
description: 'Не удалось удалить товар из корзины',
|
||
});
|
||
return false;
|
||
}
|
||
} catch (err) {
|
||
setError('Не удалось удалить товар из корзины');
|
||
toast({
|
||
variant: 'destructive',
|
||
title: 'Ошибка',
|
||
description: 'Не удалось удалить товар из корзины',
|
||
});
|
||
return false;
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, [toast]);
|
||
|
||
// Очистка корзины
|
||
const clearCart = useCallback(async () => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const result = await cartStore.clearCart();
|
||
|
||
if (result) {
|
||
toast({
|
||
title: 'Корзина очищена',
|
||
description: 'Корзина успешно очищена',
|
||
});
|
||
return true;
|
||
} else {
|
||
toast({
|
||
variant: 'destructive',
|
||
title: 'Ошибка',
|
||
description: 'Не удалось очистить корзину',
|
||
});
|
||
return false;
|
||
}
|
||
} catch (err) {
|
||
setError('Не удалось очистить корзину');
|
||
toast({
|
||
variant: 'destructive',
|
||
title: 'Ошибка',
|
||
description: 'Не удалось очистить корзину',
|
||
});
|
||
return false;
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, [toast]);
|
||
|
||
return {
|
||
cart,
|
||
loading,
|
||
error,
|
||
addToCart,
|
||
updateCartItem,
|
||
removeFromCart,
|
||
clearCart,
|
||
synchronizeCart,
|
||
itemsCount: cartStore.getItemsCount(),
|
||
itemCount: cartStore.getItemsCount(),
|
||
isAuthenticated: apiStatus.isAuthenticated,
|
||
items_count: cart.items_count,
|
||
total_amount: cart.total_amount
|
||
};
|
||
}
|