Files
teknav-bak/app/src/pages/CategoryPage.jsx
T
arsam 3ed344f3a9 Import source: app/src/pages/CategoryPage
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:24:57 +03:30

63 lines
3.7 KiB
React
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.
import { useState, useEffect } from 'react';
import { TeknavData } from '../../teknav-data.js';
import { useNav, EmptyState } from '../../teknav-ui.jsx';
import { LazyDiagram } from '../../src/components/lazy-diagram.jsx';
import { ArticleRow } from '../../teknav-articles.jsx';
import { contentApi } from '../../src/lib/content-api.js';
export function CategoryPage({ slug }) {
const { navigate } = useNav();
const [cat, setCat] = useState(() => TeknavData.categories.find(c => c.slug === slug));
const [articles, setArticles] = useState(() => contentApi.fallbackArticles().filter(a => a.category === slug));
useEffect(() => {
let cancelled = false;
setCat(TeknavData.categories.find(c => c.slug === slug));
setArticles(contentApi.fallbackArticles().filter(a => a.category === slug));
Promise.all([
contentApi.getCategory(slug).catch(() => null),
contentApi.listArticles({ category: slug, limit: 100 }).catch(() => null),
]).then(([category, result]) => {
if (cancelled) return;
if (category) setCat({ ...(TeknavData.categories.find(c => c.slug === slug) ?? {}), ...category, id: category.slug });
if (result?.items) setArticles(result.items);
});
return () => { cancelled = true; };
}, [slug]);
if (!cat) return <EmptyState title="دسته‌بندی یافت نشد" />;
return (
<div style={{ paddingTop: 64, background: '#FAF7F0', minHeight: '100vh', fontFamily: 'Vazirmatn,sans-serif' }}>
<div style={{ background: `linear-gradient(135deg, ${cat.color}18 0%, #F4EFE6 100%)`, borderBottom: '1px solid #E4DDD2', padding: '48px 24px', direction: 'rtl' }}>
<div style={{ maxWidth: 1280, margin: '0 auto', display: 'grid', gridTemplateColumns: '1fr 320px', gap: 40, alignItems: 'center' }} className="cat-hero-grid">
<div>
<div style={{ display: 'inline-block', background: cat.color + '20', color: cat.color, padding: '4px 14px', borderRadius: 4, fontSize: 11, fontWeight: 700, marginBottom: 16 }}>دسته‌بندی</div>
<h1 style={{ fontSize: 'clamp(28px,5vw,42px)', fontWeight: 900, color: '#263238', margin: '0 0 12px', fontFamily: 'Vazirmatn,sans-serif' }}>{cat.name}</h1>
<p style={{ fontSize: 16, color: '#5F6B6D', lineHeight: 1.8, margin: '0 0 24px', maxWidth: 500 }}>{cat.description}</p>
<div style={{ display: 'flex', gap: 32, flexWrap: 'wrap' }}>
{[['تعداد مقاله', cat.articleCount], ['نویسنده فعال', cat.authorCount], ['میانگین زمان مطالعه', cat.avgReadTime + ' دقیقه']].map(([l, v]) => (
<div key={l}>
<div style={{ fontSize: 22, fontWeight: 800, color: cat.color }}>{v}</div>
<div style={{ fontSize: 12, color: '#5F6B6D' }}>{l}</div>
</div>
))}
</div>
</div>
<div style={{ background: '#fff', borderRadius: 12, padding: 20, boxShadow: '0 4px 20px rgba(0,0,0,0.06)' }}>
<LazyDiagram type={cat.diagram} />
</div>
</div>
</div>
<div style={{ maxWidth: 1280, margin: '0 auto', padding: '40px 24px', direction: 'rtl' }}>
<h2 style={{ fontSize: 20, fontWeight: 700, color: '#263238', margin: '0 0 24px' }}>مقاله‌های {cat.name} ({articles.length})</h2>
{articles.length === 0 ? <EmptyState title="مقاله‌ای در این دسته وجود ندارد" /> : (
articles.map((a, i) => <ArticleRow key={a.id} article={a} idx={i} />)
)}
</div>
<style>{`.cat-hero-grid { grid-template-columns: 1fr 320px; } @media(max-width:768px){ .cat-hero-grid { grid-template-columns: 1fr !important; } }`}</style>
</div>
);
}