Files
parsshop/app/blog/page.tsx
haniyeroozmand db8cbeb153 checkout page ui
2026-03-28 12:28:56 +03:30

145 lines
8.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 { useState, useMemo } from 'react';
import ArticleCard from "@/components/articlecard";
import { articles } from "@/lib/data";
import { Search, BookOpen, FileText } from "lucide-react";
// رابط کاربری مقالات (فیلد category اضافه شد)
interface Article {
title: string;
image: string;
excerpt: string;
date: string;
category?: string; // این فیلد را در صورت امکان به دیتای خود در lib/data.ts اضافه کنید
}
export default function BlogListingPage() {
// ۱. استیت‌های مربوط به فیلتر و جستجو
const [activeCategory, setActiveCategory] = useState<string>('همه');
const [searchQuery, setSearchQuery] = useState<string>('');
// ۲. استخراج خودکار دسته‌بندی‌های یکتا از دیتای مقالات
const categories = useMemo(() => {
// اگر مقاله‌ای دسته‌بندی نداشت، آن را در 'سایر' قرار می‌دهیم
const allCategories = articles.map(article => article.category || 'سایر');
const uniqueCategories = Array.from(new Set(allCategories));
return ['همه', ...uniqueCategories];
}, []);
// ۳. فیلتر کردن مقالات بر اساس دسته‌بندی و متن جستجو
const filteredArticles = useMemo(() => {
return articles.filter((article) => {
const articleCategory = article.category || 'سایر';
const matchesCategory = activeCategory === 'همه' || articleCategory === activeCategory;
const matchesSearch =
article.title.includes(searchQuery) ||
article.excerpt.includes(searchQuery);
return matchesCategory && matchesSearch;
});
}, [activeCategory, searchQuery]);
return (
<main className="min-h-screen bg-gray-50/30 pb-20">
{/*
بخش هدر (Hero Section)
استفاده از گرادیانت ملایم و استایل‌های مدرن
*/}
<div className="bg-gradient-to-b from-gray-50/80 to-transparent pt-12 pb-8 mb-8 border-b border-gray-100">
<div className="container mx-auto px-4 max-w-6xl">
<div className="flex flex-col md:flex-row items-center justify-between gap-6">
<div className="text-center md:text-right">
<h1 className="text-3xl md:text-4xl font-black text-gray-800 mb-4 flex items-center justify-center md:justify-start gap-3">
<BookOpen className="text-[#ffb900]" size={32} />
وبلاگ و مقالات آموزشی
</h1>
<p className="text-gray-500 text-xs max-w-2xl">
جدیدترین اخبار، آموزشها، ترفندها و مقالات تخصصی در حوزه صنعت و قطعات را اینجا بخوانید.
</p>
</div>
{/* باکس آمار مقالات */}
<div className="hidden lg:flex items-center gap-4 bg-white p-4 rounded-2xl shadow-sm border border-gray-100">
<div className="bg-[#ffb900] p-3 rounded-xl ">
<FileText size={24} />
</div>
<div>
<p className="text-xs text-gray-400 font-bold mb-1">تعداد کل مقالات</p>
<p className="text-xl font-black text-gray-800">{articles.length} مقاله</p>
</div>
</div>
</div>
</div>
</div>
<div className="container mx-auto px-4 max-w-6xl">
{/* بخش فیلترها و جستجو */}
<div className="flex flex-col lg:flex-row justify-between items-start lg:items-center gap-6 mb-10 bg-white p-4 rounded-3xl shadow-sm border border-gray-100">
{/* فیلتر دسته‌بندی (قابلیت اسکرول افقی در موبایل با مخفی کردن نوار اسکرول) */}
<div className="flex w-full lg:w-auto overflow-x-auto gap-2 pb-2 lg:pb-0 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]">
{categories.map((category) => (
<button
key={category}
onClick={() => setActiveCategory(category)}
className={`
whitespace-nowrap px-5 py-2.5 rounded-full text-sm font-bold transition-all
${activeCategory === category
? 'bg-[#ffb900] text-white '
: 'bg-gray-50 text-gray-600 hover:bg-gray-100 border border-gray-100'}
`}
>
{category}
</button>
))}
</div>
{/* باکس جستجو */}
<div className="relative w-full lg:w-80 shrink-0">
<Search className="absolute right-4 top-1/2 -translate-y-1/2 text-gray-400" size={18} />
<input
type="text"
placeholder="جستجو در مقالات..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full bg-gray-50 border border-gray-100 rounded-full py-3 pr-11 pl-4 text-sm font-medium text-gray-700 placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 focus:bg-white transition-all"
/>
</div>
</div>
{/* گرید مقالات */}
<div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-4 gap-2 md:gap-5">
{filteredArticles.map((article) => (
<div key={article.title} className="transform hover:-translate-y-1 transition-transform duration-300">
<ArticleCard article={article} />
</div>
))}
</div>
{/* حالت خالی (وقتی مقاله‌ای با فیلتر یا جستجو پیدا نشد) */}
{filteredArticles.length === 0 && (
<div className="flex flex-col justify-center items-center py-20 bg-white rounded-3xl border border-gray-100 border-dashed mt-8 text-center px-4">
<div className="bg-gray-50 p-6 rounded-full mb-4">
<Search size={40} className="text-gray-300" />
</div>
<h3 className="text-xl font-bold text-gray-700 mb-2">مقالهای پیدا نشد!</h3>
<p className="text-gray-500 text-sm">
با کلمه جستجو شده یا دستهبندی انتخاب شده، مقالهای وجود ندارد. لطفا فیلترها را تغییر دهید.
</p>
<button
onClick={() => { setActiveCategory('همه'); setSearchQuery(''); }}
className="mt-6 px-6 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 font-semibold rounded-xl transition-colors text-sm"
>
پاک کردن فیلترها
</button>
</div>
)}
</div>
</main>
);
}