Files
zeropost-tool/app/page.js
T
Alexey Pavlov 5dd975a9cd feat: zeropost-tool — Next.js 16 кабинет
- Auth: iron-session, регистрация/логин по email+password
- Дашборд со списком каналов
- 3-шаговая анкета создания канала (база/стиль/примеры+табу)
- Страница канала с генератором постов через polling
- Тёмная тема, Tailwind 3.4, accent emerald
- Прокси-API к zeropost-engine с x-user-id
- Совместимость с Next 16 async cookies/params
2026-05-31 08:38:10 +03:00

101 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { redirect } from 'next/navigation';
import Link from 'next/link';
import { requireUser } from '@/lib/session';
import { engine } from '@/lib/engine';
import Header from '@/components/Header';
import { Plus, MessageSquare, Users, Target } from 'lucide-react';
const GOAL_LABELS = {
educational: 'Обучение',
news: 'Новости',
entertainment: 'Развлечение',
expert: 'Экспертный',
sales: 'Продажи',
};
export default async function HomePage() {
const user = await requireUser();
if (!user) redirect('/login');
let channels = [];
try {
channels = await engine.listChannels(user.id);
} catch (err) {
console.error('listChannels failed:', err.message);
}
return (
<>
<Header user={user} />
<main className="max-w-6xl mx-auto p-4 sm:p-6">
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-2xl font-bold">Мои каналы</h1>
<p className="text-sm text-gray-500 mt-1">
Управляй контентом и публикациями
</p>
</div>
<Link href="/channels/new" className="btn-primary">
<Plus className="w-4 h-4" />
Добавить канал
</Link>
</div>
{channels.length === 0 ? (
<div className="card p-12 text-center">
<div className="inline-flex items-center justify-center w-14 h-14 rounded-full bg-surface2 mb-4">
<MessageSquare className="w-7 h-7 text-gray-500" />
</div>
<h2 className="text-lg font-semibold mb-1">Пока пусто</h2>
<p className="text-sm text-gray-500 mb-6">
Создай первый канал, чтобы начать генерировать посты
</p>
<Link href="/channels/new" className="btn-primary">
<Plus className="w-4 h-4" />
Создать канал
</Link>
</div>
) : (
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
{channels.map(ch => (
<Link
key={ch.id}
href={`/channels/${ch.id}`}
className="card p-5 hover:border-accent/40 transition-colors group"
>
<div className="flex items-start justify-between mb-3">
<h3 className="font-semibold group-hover:text-accent transition-colors">
{ch.name}
</h3>
<span className="text-xs px-2 py-0.5 rounded-full bg-surface2 text-gray-400">
{GOAL_LABELS[ch.goal] || ch.goal}
</span>
</div>
{ch.niche && (
<p className="text-xs text-gray-500 line-clamp-2 mb-3">
{ch.niche}
</p>
)}
<div className="flex items-center gap-4 text-xs text-gray-500">
{ch.audience && (
<span className="flex items-center gap-1">
<Users className="w-3 h-3" />
Есть ЦА
</span>
)}
{ch.style?.example_posts?.length > 0 && (
<span className="flex items-center gap-1">
<Target className="w-3 h-3 text-accent" />
{ch.style.example_posts.length} пример{ch.style.example_posts.length === 1 ? '' : 'а'}
</span>
)}
</div>
</Link>
))}
</div>
)}
</main>
</>
);
}