fake_shop/app/good/[id]/page.jsx

198 lines
5.3 KiB
JavaScript
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 { useParams } from "next/navigation";
import { useEffect, useState } from "react";
import Image from "next/image";
import { useRouter } from "next/navigation";
import toast from "react-hot-toast";
import AddToCartModal from "@/components/AddToCartModal";
export default function ProductDetail() {
const params = useParams();
const [product, setProduct] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [quantity, setQuantity] = useState(1);
const router = useRouter();
const [showModal, setShowModal] = useState(false);
useEffect(() => {
const fetchProduct = async () => {
try {
const res = await fetch(`/api/products/${params.id}`);
if (!res.ok) {
throw new Error("获取商品详情失败");
}
const data = await res.json();
setProduct(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchProduct();
}, [params.id]);
const handleAddToCart = async () => {
try {
const token = localStorage.getItem("token");
if (!token) {
router.push("/login");
return;
}
const res = await fetch("/api/cart", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
productId: params.id,
quantity: quantity,
}),
});
if (!res.ok) {
throw new Error("添加购物车失败");
}
toast.success("添加成功");
handleModalClose();
} catch (error) {
toast.error(error.message);
}
};
const handleBuyNow = () => {
const token = localStorage.getItem("token");
if (!token) {
router.push("/login");
return;
}
router.push(`/checkout?products=${params.id}&quantity=${quantity}`);
};
const handleAddToCartClick = () => {
const token = localStorage.getItem("token");
if (!token) {
router.push("/login");
return;
}
setShowModal(true);
};
const handleModalClose = () => {
setShowModal(false);
};
if (loading) {
return <div className="p-4">加载中...</div>;
}
if (error) {
return <div className="p-4 text-red-500">错误: {error}</div>;
}
if (!product) {
return <div className="p-4">商品不存在</div>;
}
return (
<div className="flex flex-col min-h-screen pb-20 bg-gray-50">
{/* 商品图片 */}
<div className="relative aspect-square">
<Image
src={product.imageUrl}
alt={product.title}
fill
className="object-cover"
/>
</div>
{/* 商品信息 */}
<div className="flex-1 p-4 bg-white">
<div className="flex items-center">
<span className="text-2xl text-red-500 font-bold">
¥{product.price}
</span>
{product.isVip && (
<span className="ml-2 px-2 py-0.5 text-xs text-yellow-600 border border-yellow-600 rounded">
VIP
</span>
)}
</div>
<h1 className="mt-2 text-lg font-medium">{product.title}</h1>
<div className="mt-2 text-sm text-gray-500">
<span>库存: {product.stock}</span>
<span className="ml-4">销量: {product.sales}</span>
</div>
{/* 配送信息 */}
<div className="mt-4 p-3 bg-gray-50 rounded-lg">
<div className="flex justify-between items-center">
<span className="text-gray-500">配送</span>
<span>{product.delivery}</span>
</div>
<div className="mt-2 flex justify-between items-center">
<span className="text-gray-500">服务</span>
<div className="flex gap-2">
{product.services.map((service, index) => (
<span key={index} className="text-sm text-gray-600">
{service}
</span>
))}
</div>
</div>
</div>
{/* 商品描述 */}
<div className="mt-6">
<h2 className="text-lg font-bold mb-2">商品详情</h2>
<p className="text-gray-600">{product.description}</p>
<h3 className="mt-4 font-bold">产品特点</h3>
<ul className="mt-2 space-y-2">
{product.features.map((feature, index) => (
<li key={index} className="flex items-center text-gray-600">
<span className="mr-2"></span>
{feature}
</li>
))}
</ul>
</div>
</div>
{/* 底部购买栏 */}
<div className="fixed bottom-0 left-0 right-0 flex items-center p-4 bg-white border-t">
<button
className="flex-1 bg-yellow-400 text-white py-2 rounded-full"
onClick={handleAddToCartClick}
>
加入购物车
</button>
<button
className="flex-1 ml-2 bg-red-500 text-white py-2 rounded-full"
onClick={handleBuyNow}
>
立即购买
</button>
</div>
<AddToCartModal
isOpen={showModal}
onClose={handleModalClose}
product={product}
quantity={quantity}
setQuantity={setQuantity}
onAddToCart={handleAddToCart}
/>
</div>
);
}