dressed_for_succes_store/frontend/hooks/useCart.ts

212 lines
6.6 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 { 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';
// Глобальная переменная для отслеживания последней синхронизации
let lastSyncTimestamp = 0;
const SYNC_THROTTLE_MS = 5000; // Минимальное время между синхронизациями (5 секунд)
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) {
// Проверяем, не происходит ли уже синхронизация и не слишком ли рано для новой
const now = Date.now();
if (!syncInProgressRef.current && now - lastSyncTimestamp > SYNC_THROTTLE_MS) {
synchronizeCart();
}
}
}, [apiStatus.isAuthenticated]);
// Синхронизация локальной корзины с сервером с дроттлингом
const synchronizeCart = useCallback(async () => {
try {
// Если синхронизация уже идет, не запускаем новую
if (syncInProgressRef.current) return;
syncInProgressRef.current = true;
setLoading(true);
// Фиксируем время последней синхронизации
lastSyncTimestamp = Date.now();
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
};
}