104 lines
3.2 KiB
TypeScript
104 lines
3.2 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { ShoppingCart, Plus, Minus } from 'lucide-react'
|
|
|
|
interface AddToCartButtonProps {
|
|
componentId: string
|
|
disabled?: boolean
|
|
className?: string
|
|
}
|
|
|
|
export function AddToCartButton({ componentId, disabled = false, className = '' }: AddToCartButtonProps) {
|
|
const [quantity, setQuantity] = useState(1)
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
const handleAddToCart = async () => {
|
|
const token = localStorage.getItem('token')
|
|
if (!token) {
|
|
alert('请先登录')
|
|
return
|
|
}
|
|
|
|
setIsLoading(true)
|
|
try {
|
|
const response = await fetch('/api/cart', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${token}`
|
|
},
|
|
body: JSON.stringify({
|
|
componentId,
|
|
quantity
|
|
})
|
|
})
|
|
|
|
if (response.ok) {
|
|
// 触发购物车更新事件
|
|
window.dispatchEvent(new Event('cart-updated'))
|
|
alert('已添加到购物车!')
|
|
} else if (response.status === 401) {
|
|
localStorage.removeItem('token')
|
|
localStorage.removeItem('user')
|
|
alert('登录已过期,请重新登录')
|
|
window.location.href = '/login'
|
|
} else {
|
|
const data = await response.json()
|
|
alert(data.message || '添加失败')
|
|
}
|
|
} catch (error) {
|
|
console.error('添加到购物车失败:', error)
|
|
alert('添加失败,请重试')
|
|
} finally {
|
|
setIsLoading(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className={`space-y-4 ${className}`}>
|
|
{/* Quantity Selector */}
|
|
<div className="flex items-center space-x-4">
|
|
<span className="text-sm text-gray-600">数量:</span>
|
|
<div className="flex items-center border border-gray-300 rounded-lg">
|
|
<button
|
|
type="button"
|
|
onClick={() => setQuantity(Math.max(1, quantity - 1))}
|
|
disabled={quantity <= 1 || disabled}
|
|
className="p-2 hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
>
|
|
<Minus className="h-4 w-4" />
|
|
</button>
|
|
<span className="px-4 py-2 text-center min-w-[50px]">{quantity}</span>
|
|
<button
|
|
type="button"
|
|
onClick={() => setQuantity(quantity + 1)}
|
|
disabled={disabled}
|
|
className="p-2 hover:bg-gray-100 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
>
|
|
<Plus className="h-4 w-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Add to Cart Button */}
|
|
<button
|
|
onClick={handleAddToCart}
|
|
disabled={disabled || isLoading}
|
|
className={`
|
|
flex items-center justify-center space-x-2 w-full py-3 px-6 rounded-lg font-medium transition-colors
|
|
${disabled
|
|
? 'bg-gray-300 text-gray-500 cursor-not-allowed'
|
|
: 'bg-blue-600 text-white hover:bg-blue-700'
|
|
}
|
|
${isLoading ? 'opacity-50 cursor-not-allowed' : ''}
|
|
`}
|
|
>
|
|
<ShoppingCart className="h-5 w-5" />
|
|
<span>
|
|
{isLoading ? '添加中...' : disabled ? '缺货' : '加入购物车'}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|