92 lines
3.0 KiB
TypeScript
92 lines
3.0 KiB
TypeScript
import { useState } from 'react';
|
||
import { useRouter } from 'next/router';
|
||
import { ShoppingCart, Check, AlertCircle } from 'lucide-react';
|
||
import cartService from '../services/cart';
|
||
import authService from '../services/auth';
|
||
|
||
interface AddToCartButtonProps {
|
||
variantId: number;
|
||
quantity?: number;
|
||
className?: string;
|
||
onAddToCart?: () => void;
|
||
}
|
||
|
||
export default function AddToCartButton({ variantId, quantity = 1, className = '', onAddToCart }: AddToCartButtonProps) {
|
||
const router = useRouter();
|
||
const [loading, setLoading] = useState(false);
|
||
const [success, setSuccess] = useState(false);
|
||
const [error, setError] = useState<string | null>(null);
|
||
|
||
const handleAddToCart = async () => {
|
||
// Проверяем, авторизован ли пользователь
|
||
if (!authService.isAuthenticated()) {
|
||
// Сохраняем текущий URL для редиректа после авторизации
|
||
const currentPath = router.asPath;
|
||
router.push(`/login?redirect=${encodeURIComponent(currentPath)}`);
|
||
return;
|
||
}
|
||
|
||
setLoading(true);
|
||
setError(null);
|
||
|
||
try {
|
||
await cartService.addToCart({
|
||
variant_id: variantId,
|
||
quantity: quantity
|
||
});
|
||
|
||
setSuccess(true);
|
||
|
||
// Вызываем колбэк, если он передан
|
||
if (onAddToCart) {
|
||
onAddToCart();
|
||
}
|
||
|
||
// Сбрасываем состояние успеха через 2 секунды
|
||
setTimeout(() => {
|
||
setSuccess(false);
|
||
}, 2000);
|
||
} catch (err) {
|
||
console.error('Ошибка при добавлении в корзину:', err);
|
||
setError('Не удалось добавить товар в корзину');
|
||
|
||
// Сбрасываем состояние ошибки через 3 секунды
|
||
setTimeout(() => {
|
||
setError(null);
|
||
}, 3000);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="relative">
|
||
<button
|
||
onClick={handleAddToCart}
|
||
disabled={loading || variantId === 0}
|
||
className={`flex items-center justify-center px-6 py-3 bg-black text-white rounded-md hover:bg-gray-800 transition-colors ${loading ? 'opacity-70 cursor-not-allowed' : ''} ${variantId === 0 ? 'opacity-50 cursor-not-allowed' : ''} ${className}`}
|
||
>
|
||
{loading ? (
|
||
<div className="animate-spin rounded-full h-5 w-5 border-t-2 border-b-2 border-white"></div>
|
||
) : success ? (
|
||
<>
|
||
<Check className="w-5 h-5 mr-2" />
|
||
Добавлено
|
||
</>
|
||
) : (
|
||
<>
|
||
<ShoppingCart className="w-5 h-5 mr-2" />
|
||
{variantId === 0 ? 'Нет в наличии' : 'В корзину'}
|
||
</>
|
||
)}
|
||
</button>
|
||
|
||
{error && (
|
||
<div className="absolute top-full left-0 right-0 mt-2 bg-red-100 text-red-700 p-2 rounded-md text-sm flex items-center">
|
||
<AlertCircle className="w-4 h-4 mr-1 flex-shrink-0" />
|
||
<span>{error}</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|