Files
Alexey Pavlov 03c10eab6e feat: серии + count-up в Stats
- SeriesGrid: карточки серий с иконками (Sparkles/Plug/Zap/Layers) и цветовыми темами
- /series/[slug]: страница серии с интро и сеткой статей в порядке из article_ids
- Stats: count-up анимация (easeOutQuart 1.2s) при появлении в viewport через IntersectionObserver
- sitemap.xml: добавлены /notes и все серии
2026-05-31 10:10:18 +03:00

60 lines
2.3 KiB
JavaScript

import Link from 'next/link';
import { Sparkles, Plug, Zap, Layers, ArrowRight } from 'lucide-react';
const ICONS = { Sparkles, Plug, Zap, Layers };
const COLORS = {
emerald: { bg: 'rgb(16 185 129 / 0.1)', dot: '#10b981', text: '#059669' },
teal: { bg: 'rgb(20 184 166 / 0.1)', dot: '#14b8a6', text: '#0d9488' },
amber: { bg: 'rgb(245 158 11 / 0.1)', dot: '#f59e0b', text: '#d97706' },
indigo: { bg: 'rgb(99 102 241 / 0.1)', dot: '#6366f1', text: '#4f46e5' },
};
export default function SeriesGrid({ series }) {
if (!series || series.length === 0) return null;
return (
<section className="container-wide pb-12">
<div className="flex items-center justify-between mb-4 sm:mb-5">
<h2 className="text-xs sm:text-sm font-medium uppercase tracking-widest mute">
Серии
</h2>
</div>
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-5">
{series.map(s => {
const Icon = ICONS[s.icon] || Layers;
const c = COLORS[s.color] || COLORS.emerald;
return (
<Link
key={s.id}
href={`/series/${s.slug}`}
className="article-card group p-5 sm:p-6 flex flex-col"
>
<div className="flex items-center gap-3 mb-3">
<div
className="w-10 h-10 rounded-lg flex items-center justify-center"
style={{ background: c.bg }}
>
<Icon className="w-5 h-5" style={{ color: c.dot }} />
</div>
<span className="text-xs mute">
{s.articles_count} {s.articles_count === 1 ? 'материал' : 'материалов'}
</span>
</div>
<h3 className="text-lg sm:text-xl font-bold ink mb-2 leading-snug group-hover:accent transition-colors">
{s.title}
</h3>
{s.intro && (
<p className="mute text-sm leading-relaxed mb-4 line-clamp-3 flex-1">
{s.intro}
</p>
)}
<div className="inline-flex items-center gap-1 text-sm font-medium" style={{ color: c.text }}>
Открыть серию <ArrowRight className="w-3.5 h-3.5" />
</div>
</Link>
);
})}
</div>
</section>
);
}