Import source: app/src/pages/CategoryPage
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user