feat: журнальная главная, страница Зеро, TG-баннер, stats, auto-publish UI
- Журнальная главная: hero, CategoryRow, PopularBlock, RecentBlock (Сегодня/Вчера/Неделя) - ArticleCard: 3 размера (hero/regular/compact), цветной badge без дублей тегов - ArticleCoverSVG: 6 брендовых палитр, аватар Зеро в углу вместо #ZEROPOST - /about/zero: страница персонажа с галереей 8 поз - Footer: TG-баннер с аватаром Зеро на каждой странице - Конец статьи: блок «Понравилась? → Подписаться на канал» - ChannelEditor: 4 вкладки (Настройки/Расписание/Авто-публикация/Ручная) - AutoPublishTab: toggle, категории, delay, template, live preview - ArticlePicker: typeahead с was_sent_to_channel / next_scheduled_at флагами - /admin/channels/[id]/stats: график роста подписчиков (recharts) - Dashboard: блок TG-статистики (подписчики, delta 24h/7d, постов) - Header: упрощён до 2 пунктов desktop + расширенное мобильное меню - AutogenPanel: корректные time-picker'ы, calcNextRun с учётом last_run_at
This commit is contained in:
+30
-30
@@ -5,6 +5,12 @@ import { Sparkles, Menu, X } from 'lucide-react';
|
||||
import ThemeToggle from './ThemeToggle';
|
||||
import SearchBox from './SearchBox';
|
||||
|
||||
// Минимум: главная + о проекте. Серии и заметки доступны через карточки на главной и футер.
|
||||
const NAV_LINKS = [
|
||||
{ href: '/', label: 'Главная' },
|
||||
{ href: '/about', label: 'О проекте' },
|
||||
];
|
||||
|
||||
export default function Header() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [hidden, setHidden] = useState(false);
|
||||
@@ -55,20 +61,18 @@ export default function Header() {
|
||||
|
||||
{/* Desktop nav */}
|
||||
<nav className="hidden sm:flex items-center gap-1 text-sm">
|
||||
<Link href="/" className="btn btn-ghost text-sm py-1.5">Статьи</Link>
|
||||
<Link href="/category/cybersec" className="btn btn-ghost text-sm py-1.5">🔒 Безопасность</Link>
|
||||
<Link href="/category/automation" className="btn btn-ghost text-sm py-1.5">⚡ Автоматизация</Link>
|
||||
<Link href="/category/ai-dev" className="btn btn-ghost text-sm py-1.5">💻 Dev + AI</Link>
|
||||
<Link href="/archive" className="btn btn-ghost text-sm py-1.5">Архив</Link>
|
||||
<Link href="/notes" className="btn btn-ghost text-sm py-1.5">Заметки</Link>
|
||||
<Link href="/about" className="btn btn-ghost text-sm py-1.5">О проекте</Link>
|
||||
<div className="ml-1 flex items-center gap-1">
|
||||
{NAV_LINKS.map(link => (
|
||||
<Link key={link.href} href={link.href} className="btn btn-ghost text-sm py-1.5">
|
||||
{link.label}
|
||||
</Link>
|
||||
))}
|
||||
<div className="ml-2 flex items-center gap-1 pl-2 border-l border-soft">
|
||||
<SearchBox />
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Mobile */}
|
||||
{/* Mobile controls */}
|
||||
<div className="sm:hidden flex items-center gap-1">
|
||||
<SearchBox />
|
||||
<ThemeToggle />
|
||||
@@ -90,27 +94,23 @@ export default function Header() {
|
||||
style={{ background: 'rgb(var(--bg) / 0.98)', paddingTop: 'calc(64px + env(safe-area-inset-top))' }}
|
||||
>
|
||||
<nav className="container-wide pt-6 pb-8 flex flex-col gap-1">
|
||||
<Link
|
||||
href="/"
|
||||
onClick={() => setOpen(false)}
|
||||
className="text-2xl font-semibold ink py-3 border-b-soft"
|
||||
>Статьи</Link>
|
||||
<Link
|
||||
href="/archive"
|
||||
onClick={() => setOpen(false)}
|
||||
className="text-2xl font-semibold ink py-3 border-b-soft"
|
||||
>Архив</Link>
|
||||
<Link
|
||||
href="/notes"
|
||||
onClick={() => setOpen(false)}
|
||||
className="text-2xl font-semibold ink py-3 border-b-soft"
|
||||
>Заметки</Link>
|
||||
<Link
|
||||
href="/about"
|
||||
onClick={() => setOpen(false)}
|
||||
className="text-2xl font-semibold ink py-3 border-b-soft"
|
||||
>О проекте</Link>
|
||||
<div className="mt-6 mute text-sm">
|
||||
<Link href="/" onClick={() => setOpen(false)} className="text-2xl font-semibold ink py-3 border-b-soft">
|
||||
Главная
|
||||
</Link>
|
||||
<div className="py-3 border-b-soft">
|
||||
<div className="text-xs uppercase tracking-widest mute mb-2">Темы</div>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<Link onClick={() => setOpen(false)} href="/category/ai-tools" className="text-base font-medium py-2">🤖 AI Tools</Link>
|
||||
<Link onClick={() => setOpen(false)} href="/category/ai-dev" className="text-base font-medium py-2">💻 AI Dev</Link>
|
||||
<Link onClick={() => setOpen(false)} href="/category/automation" className="text-base font-medium py-2">⚡ Automation</Link>
|
||||
<Link onClick={() => setOpen(false)} href="/category/cybersec" className="text-base font-medium py-2">🔒 Cybersec</Link>
|
||||
</div>
|
||||
</div>
|
||||
<Link href="/series" onClick={() => setOpen(false)} className="text-base font-medium ink py-3 border-b-soft">Серии</Link>
|
||||
<Link href="/notes" onClick={() => setOpen(false)} className="text-base font-medium ink py-3 border-b-soft">Заметки</Link>
|
||||
<Link href="/archive" onClick={() => setOpen(false)} className="text-base font-medium ink py-3 border-b-soft">Архив</Link>
|
||||
<Link href="/about" onClick={() => setOpen(false)} className="text-base font-medium ink py-3 border-b-soft">О проекте</Link>
|
||||
<div className="mt-8 mute text-sm leading-relaxed">
|
||||
Блог, который ведёт ИИ — а человек только следит за курсом.
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
Reference in New Issue
Block a user