single category page
This commit is contained in:
99
app/category/[categoryName]/page.tsx
Normal file
99
app/category/[categoryName]/page.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import { products } from "@/lib/data";
|
||||
import ProductCard from "@/components/productcard";
|
||||
|
||||
interface PageProps {
|
||||
params: Promise<{ categoryName: string }>;
|
||||
}
|
||||
|
||||
export default async function CategoryPage({ params }: PageProps) {
|
||||
try {
|
||||
// ۱. دریافت پارامترها
|
||||
const resolvedParams = await params;
|
||||
const rawCategoryName = resolvedParams.categoryName;
|
||||
|
||||
// چاپ در ترمینال (VSCode)
|
||||
console.log("--- DEBUG START ---");
|
||||
console.log("1. Raw Params:", resolvedParams);
|
||||
|
||||
// ۲. دیکد کردن آدرس
|
||||
const decodedUrl = decodeURIComponent(rawCategoryName);
|
||||
console.log("2. Decoded URL:", decodedUrl);
|
||||
|
||||
// ۳. آمادهسازی رشته برای مقایسه
|
||||
const categoryNameToMatch = decodedUrl.replace(/-/g, " ").trim();
|
||||
console.log(`3. Final String to Match: "${categoryNameToMatch}"`);
|
||||
|
||||
// استخراج تمام دستهبندیهای موجود در دیتابیس (برای بررسی چشمی)
|
||||
const allCategoriesInDb = Array.from(new Set(products.map(p => p.category)));
|
||||
console.log("4. Available DB Categories:", allCategoriesInDb);
|
||||
|
||||
// ۴. فیلتر کردن (با حذف فاصلههای اضافی از دو طرف برای اطمینان)
|
||||
const filteredProducts = products.filter(
|
||||
(p) => p.category.trim() === categoryNameToMatch
|
||||
);
|
||||
console.log("5. Found Products:", filteredProducts.length);
|
||||
console.log("--- DEBUG END ---");
|
||||
|
||||
// ۵. اگر پیدا نشد، صفحه دیباگ را در مرورگر نمایش بده
|
||||
if (!filteredProducts || filteredProducts.length === 0) {
|
||||
return (
|
||||
<main className="container mx-auto px-4 py-10" dir="rtl">
|
||||
<div className="bg-red-50 border border-red-200 text-red-800 p-6 rounded-lg">
|
||||
<h1 className="text-2xl font-bold mb-4">محصولی پیدا نشد (حالت دیباگ)</h1>
|
||||
|
||||
<div className="mb-6 space-y-2">
|
||||
<p>پارامتر دریافت شده از URL: <strong className="font-mono bg-white px-2 py-1 rounded">{rawCategoryName}</strong></p>
|
||||
<p>رشتهی آماده شده برای جستجو: <strong className="font-mono bg-white px-2 py-1 rounded">{categoryNameToMatch}</strong> (طول: {categoryNameToMatch.length} کاراکتر)</p>
|
||||
</div>
|
||||
|
||||
<h2 className="text-xl font-bold mb-2">لیست دستهبندیهای موجود در دیتابیس شما:</h2>
|
||||
<ul className="list-disc list-inside space-y-1 bg-white p-4 rounded-md">
|
||||
{allCategoriesInDb.map((cat, index) => (
|
||||
<li key={index} className="font-mono">
|
||||
"{cat}" (طول: {cat.length} کاراکتر)
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<p className="mt-4 text-sm text-gray-600">
|
||||
لطفا طول کاراکترها و املای کلمات را در لیست بالا مقایسه کنید. (آیا نیمفاصله یا فاصله اضافه وجود دارد؟)
|
||||
<br />
|
||||
<strong>نکته مهم:</strong> برای دیدن لاگهای بیشتر، ترمینال (کنسول) محیط توسعه (مثلاً VSCode) را چک کنید، نه کنسول مرورگر را.
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
const categoryTitle = filteredProducts[0].category;
|
||||
|
||||
// رندر حالت موفق
|
||||
return (
|
||||
<main className="container mx-auto px-4 py-10" dir="rtl">
|
||||
<div className="mb-8 border-b pb-4">
|
||||
<h1 className="text-2xl font-bold text-gray-800">
|
||||
دستهبندی: {categoryTitle}
|
||||
</h1>
|
||||
<p className="text-gray-500 mt-2">
|
||||
تعداد محصولات یافت شده: {filteredProducts.length} مورد
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
||||
{filteredProducts.map((product) => (
|
||||
<ProductCard key={product.id} product={product} />
|
||||
))}
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
// هندلینگ خطاهای غیرمنتظره
|
||||
console.error("Critical Error in Category Page:", error);
|
||||
return (
|
||||
<div className="p-10 text-center text-red-500 font-bold">
|
||||
خطای پردازشی رخ داد. لطفا ترمینال VSCode را بررسی کنید.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
105
app/page.tsx
105
app/page.tsx
@@ -1,11 +1,12 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
import { Headphones, FileText, Truck, ShieldCheck, Square, MoreVertical, Circle, Target, CookingPot, Plus, Minus, MessageCircleCheckIcon, } from "lucide-react";
|
||||
import { Headphones, FileText, Truck, ShieldCheck, Square, MoreVertical, Circle, Target, CookingPot, Settings, CircleDashed, Disc, Hexagon, Droplets, Wrench, Minus, MessageCircleCheckIcon, } from "lucide-react";
|
||||
import ProductCard from "@/components/productcard";
|
||||
import ArticleCard from "@/components/articlecard";
|
||||
import FAQItem from "@/components/faq";
|
||||
import { products } from "@/lib/data";
|
||||
import { articles } from "@/lib/data";
|
||||
import Link from "next/link";
|
||||
|
||||
|
||||
|
||||
@@ -32,32 +33,32 @@ const features = [
|
||||
},
|
||||
];
|
||||
|
||||
const categories = [
|
||||
{
|
||||
title: "فیلتر و رگلاتور",
|
||||
icon: CookingPot,
|
||||
},
|
||||
{
|
||||
title: "باتن",
|
||||
icon: Square,
|
||||
},
|
||||
{
|
||||
title: "سوئیچ",
|
||||
icon: MoreVertical,
|
||||
},
|
||||
{
|
||||
title: "شبکه ای",
|
||||
icon: Circle,
|
||||
},
|
||||
{
|
||||
title: "مدیرفشار",
|
||||
icon: Target,
|
||||
},
|
||||
{
|
||||
title: "شیر برقی",
|
||||
icon: Minus,
|
||||
},
|
||||
];
|
||||
// const categories = [
|
||||
// {
|
||||
// title: "فیلتر و رگلاتور",
|
||||
// icon: CookingPot,
|
||||
// },
|
||||
// {
|
||||
// title: "باتن",
|
||||
// icon: Square,
|
||||
// },
|
||||
// {
|
||||
// title: "سوئیچ",
|
||||
// icon: MoreVertical,
|
||||
// },
|
||||
// {
|
||||
// title: "شبکه ای",
|
||||
// icon: Circle,
|
||||
// },
|
||||
// {
|
||||
// title: "مدیرفشار",
|
||||
// icon: Target,
|
||||
// },
|
||||
// {
|
||||
// title: "شیر برقی",
|
||||
// icon: Minus,
|
||||
// },
|
||||
// ];
|
||||
|
||||
const tabs = ["پرفروشترینها", "تخفیفدار", "جدیدترینها"];
|
||||
|
||||
@@ -85,20 +86,27 @@ export default function Home() {
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
const brands = ["NTN", "KOYO", "NACHI", "TIMKEN", "FAG", "SKF"];
|
||||
const latestArticles = articles.slice(-4);
|
||||
const featuredProducts = products.slice(0, 10);
|
||||
const [startIndex, setStartIndex] = useState(0);
|
||||
|
||||
const nextSlide = () => {
|
||||
if (startIndex + 4 < featuredProducts.length) {
|
||||
setStartIndex(startIndex + 1);
|
||||
const uniqueCategories = Array.from(new Set(products.map((p) => p.category)));
|
||||
const getCategoryIcon = (categoryName: string) => {
|
||||
switch (categoryName) {
|
||||
case "شیار عمیق":
|
||||
return CircleDashed;
|
||||
case "مخروطی":
|
||||
return Disc;
|
||||
case "شبکه ای":
|
||||
return Hexagon;
|
||||
case "سوزنی":
|
||||
return Settings;
|
||||
case "یاتاقان":
|
||||
return Wrench;
|
||||
case "گریس و روانکار":
|
||||
return Droplets;
|
||||
default:
|
||||
return Settings; // آیکون پیشفرض
|
||||
}
|
||||
};
|
||||
|
||||
const prevSlide = () => {
|
||||
if (startIndex > 0) {
|
||||
setStartIndex(startIndex - 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
@@ -244,26 +252,29 @@ export default function Home() {
|
||||
|
||||
{/* cards */}
|
||||
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-6">
|
||||
{categories.map((cat, index) => {
|
||||
const Icon = cat.icon;
|
||||
{uniqueCategories.map((category, index) => {
|
||||
const Icon = getCategoryIcon(category);
|
||||
|
||||
// فقط فاصلهها را به خط تیره تبدیل میکنیم
|
||||
const categorySlug = category.replace(/\s+/g, "-");
|
||||
|
||||
return (
|
||||
<div
|
||||
<Link
|
||||
href={`/category/${categorySlug}`}
|
||||
key={index}
|
||||
className="bg-white border border-gray-200 rounded-xl shadow-sm hover:shadow-md transition-all duration-300 flex flex-col items-center justify-center py-8 cursor-pointer"
|
||||
className="bg-white border border-gray-200 rounded-xl shadow-sm hover:shadow-md hover:border-blue-400 transition-all duration-300 flex flex-col items-center justify-center py-8 cursor-pointer group"
|
||||
>
|
||||
<Icon size={34} className="text-gray-400 mb-3" />
|
||||
|
||||
<p className="text-sm font-medium text-gray-700">
|
||||
{cat.title}
|
||||
<Icon size={34} className="text-gray-400 mb-3 group-hover:text-blue-500 transition-colors" />
|
||||
<p className="text-sm font-medium text-gray-700 group-hover:text-blue-600">
|
||||
{category}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
{/* products */}
|
||||
<section className="py-12">
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
|
||||
Reference in New Issue
Block a user