feat(categories): admin section + dynamic categories everywhere

New /admin/categories page:
  - list with icon, name, slug, color preview, article/topic counters
  - new/edit form (slug locked after creation since it's FK in articles/topics)
  - 12 color palette, sort_order, archive toggle (soft delete)
  - hard delete only when archived AND no articles/topics attached

AdminNav: new pin 'Категории' (FolderPlus) in 'Контент' group, before Статьи.

Dynamic categories — hardcoded CAT_LABELS removed from:
  - components/admin/AutogenPanel.js — now accepts categories prop, builds
    lookup map from DB, supports all 12 palette colors
  - app/page.js — CATEGORY_ORDER hardcode removed; renders categories in
    sort_order from DB, skips empty ones

Plumbing: app/admin/api/categories/[...path]/route.js — catch-all proxy
This commit is contained in:
Aleksei Pavlov
2026-06-19 11:57:35 +03:00
parent 0b4895bb97
commit 3f6cd28798
6 changed files with 371 additions and 20 deletions
+10 -8
View File
@@ -17,7 +17,7 @@ import { Sparkles, ArrowRight } from 'lucide-react';
export const dynamic = 'force-dynamic';
const CATEGORY_ORDER = ['ai-tools', 'ai-dev', 'automation', 'cybersec'];
// CATEGORY_ORDER теперь приходит из БД (categories) — sort_order определяет порядок
export default async function HomePage() {
let home = { hero: null, byCategory: {}, popular: [], recent: [] };
@@ -142,13 +142,15 @@ export default async function HomePage() {
</Reveal>
)}
{/* КАТЕГОРИЙНЫЕ РЯДЫ */}
{CATEGORY_ORDER.map(cat => (
<Reveal key={cat}>
<div className="reveal">
<CategoryRow category={cat} articles={byCategory[cat] || []} />
</div>
</Reveal>
{/* КАТЕГОРИЙНЫЕ РЯДЫ — порядок и состав из БД через sort_order */}
{categories.map(cat => (
(byCategory[cat.slug] || []).length > 0 && (
<Reveal key={cat.slug}>
<div className="reveal">
<CategoryRow category={cat.slug} articles={byCategory[cat.slug] || []} />
</div>
</Reveal>
)
))}
{/* ПОПУЛЯРНОЕ ЗА МЕСЯЦ */}