fake_shop/app/shop/page.jsx

157 lines
4.6 KiB
JavaScript

"use client";
import React, { useEffect, useState } from "react";
import Link from "next/link";
import Image from "next/image";
import { useRouter } from "next/navigation";
export default function ShopPage() {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [searchTerm, setSearchTerm] = useState("");
const [currentPage, setCurrentPage] = useState(1);
const [productsPerPage] = useState(10); // 每页显示的商品数量
const [activeTab, setActiveTab] = useState("all"); // 新增的状态
const router = useRouter();
useEffect(() => {
const fetchProducts = async () => {
try {
const res = await fetch("/api/products");
if (!res.ok) {
throw new Error("获取商品列表失败");
}
const data = await res.json();
setProducts(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchProducts();
}, []);
const handleSearch = (e) => {
setSearchTerm(e.target.value);
};
const filteredProducts = products.filter((product) =>
product.title.toLowerCase().includes(searchTerm.toLowerCase())
);
const indexOfLastProduct = currentPage * productsPerPage;
const indexOfFirstProduct = indexOfLastProduct - productsPerPage;
const currentProducts = filteredProducts.slice(
indexOfFirstProduct,
indexOfLastProduct
);
const paginate = (pageNumber) => setCurrentPage(pageNumber);
if (loading) return <div className="p-4">加载中...</div>;
if (error) return <div className="p-4 text-red-500">错误: {error}</div>;
return (
<div className="p-4">
<input
type="text"
placeholder="搜索商品"
value={searchTerm}
onChange={handleSearch}
className="mb-4 p-2 border rounded w-full"
/>
{/* 店铺信息 */}
<Link href="/shop/profile" className="flex flex-row items-center">
<Image
src="https://s2.loli.net/2025/02/25/G1yo27THWhNC5uf.jpg" // 替换为实际的店铺头像路径
alt="店铺头像"
width={60}
height={60}
className="rounded-lg border-2 border-yellow-400 mr-4"
/>
<div className="flex flex-col flex-1 justify-around items-start">
<span className="text-lg font-semibold text-gray-800">
宠物用品专卖店
</span>
<p className="text-yellow-700 bg-yellow-400 px-1 rounded">
官方正品旗舰店{" >"}
</p>
</div>
</Link>
{/* Tab 切换栏 */}
<div className="flex border-b mb-4">
<button
className={`flex-1 py-3 text-center ${
activeTab === "all"
? "text-yellow-500 border-b-2 border-yellow-500"
: "text-gray-500"
}`}
onClick={() => setActiveTab("all")}
>
宝贝
</button>
<button
className={`flex-1 py-3 text-center ${
activeTab === "new"
? "text-yellow-500 border-b-2 border-yellow-500"
: "text-gray-500"
}`}
onClick={() => setActiveTab("new")}
>
新品
</button>
</div>
<div
className={`grid gap-4 ${
activeTab === "all" ? "grid-cols-2" : "grid-cols-1"
}`}
>
{currentProducts.map((product) => (
<div
key={product._id}
className="bg-white rounded-lg shadow-md overflow-hidden"
>
<Link href={`/good/${product._id}`}>
<div className="relative aspect-square">
<Image
src={product.imageUrl}
alt={product.title}
fill
className="object-cover rounded-t-lg"
/>
</div>
<div className="p-4">
<h3 className="text-lg truncate font-medium mt-2 line-clamp-2">
{product.title}
</h3>
<p className="text-red-500">¥{product.price}</p>
</div>
</Link>
</div>
))}
</div>
<div className="flex justify-center mt-4">
{[
...Array(Math.ceil(filteredProducts.length / productsPerPage)).keys(),
].map((number) => (
<button
key={number}
onClick={() => paginate(number + 1)}
className={`px-3 py-1 mx-1 ${
currentPage === number + 1 ? "bg-yellow-400" : "bg-gray-200"
}`}
>
{number + 1}
</button>
))}
</div>
</div>
);
}