'use client'; import { useState } from 'react'; import { useRouter } from 'next/navigation'; import Link from 'next/link'; import { ArrowLeft, Save, Trash2, Loader2, Image as ImageIcon, Type, Palette, Plus, X, Sparkles, Plug } from 'lucide-react'; const GOALS = [ { v: 'educational', label: 'Обучение', desc: 'Объясняем, разбираем' }, { v: 'news', label: 'Новости', desc: 'Что произошло' }, { v: 'entertainment', label: 'Развлечение', desc: 'Лёгкий контент, мемы' }, { v: 'expert', label: 'Экспертный', desc: 'Глубокий анализ, инсайты' }, { v: 'sales', label: 'Продажи', desc: 'Подвести к покупке' }, ]; const TONES = [ { v: 'friendly', label: 'Дружелюбный' }, { v: 'serious', label: 'Серьёзный' }, { v: 'ironic', label: 'Ироничный' }, { v: 'provocative', label: 'Провокационный' }, { v: 'academic', label: 'Академичный' }, ]; const LENGTHS = [ { v: 'short', label: 'Короткий', desc: 'до 300' }, { v: 'medium', label: 'Средний', desc: '300-800' }, { v: 'long', label: 'Длинный', desc: '800-2000' }, ]; const HUMOR = [ { v: 'none', label: 'Без юмора' }, { v: 'dry', label: 'Сухой/ирония' }, { v: 'moderate', label: 'Умеренный' }, { v: 'playful', label: 'Игривый' }, ]; const EMOJI = [ { v: 'none', label: 'Без эмодзи' }, { v: 'moderate', label: 'Умеренно' }, { v: 'active', label: 'Активно' }, ]; const IMAGE_STYLES = [ { v: 'realistic-photo', label: 'Реалистичное фото', desc: 'Стоковая фотография' }, { v: 'flat-illustration', label: 'Плоская иллюстрация', desc: 'Editorial vector' }, { v: '3d-render', label: '3D рендер', desc: 'Pixar-like' }, { v: 'cartoon', label: 'Мультяшный', desc: 'Comic book' }, { v: 'minimal', label: 'Минимализм', desc: 'Один элемент' }, { v: 'abstract', label: 'Абстракция', desc: 'Без объектов' }, { v: 'sketch', label: 'Скетч', desc: 'Карандашный рисунок' }, { v: 'cyberpunk', label: 'Киберпанк', desc: 'Неон, будущее' }, ]; const IMAGE_PALETTES = [ { v: 'auto', label: 'Авто' }, { v: 'dark', label: 'Тёмная' }, { v: 'light', label: 'Светлая' }, { v: 'warm', label: 'Тёплая' }, { v: 'cool', label: 'Холодная' }, { v: 'mono', label: 'Монохром' }, { v: 'vibrant', label: 'Яркая' }, ]; const TABS = [ { id: 'content', label: 'Контент', icon: Type }, { id: 'images', label: 'Картинки', icon: ImageIcon }, { id: 'connect', label: 'Подключение', icon: Plug }, ]; export default function ChannelEdit({ channel }) { const router = useRouter(); const style = channel.style || {}; const [tab, setTab] = useState('content'); // Контент const [name, setName] = useState(channel.name || ''); const [niche, setNiche] = useState(channel.niche || ''); const [audience, setAudience] = useState(channel.audience || ''); const [goals, setGoals] = useState( channel.goal ? channel.goal.split(',').map(g => g.trim()).filter(Boolean) : ['educational'] ); const [customGoal, setCustomGoal] = useState(''); const [language, setLanguage] = useState(channel.language || 'ru'); const [tone, setTone] = useState(style.tone || 'friendly'); const [formality, setFormality] = useState(style.formality || 'informal'); const [humor, setHumor] = useState(style.humor || 'moderate'); const [postLength, setPostLength] = useState(style.post_length || 'medium'); const [emojiLevel, setEmojiLevel] = useState(style.emoji_level || 'moderate'); const [hashtagsMode, setHashtagsMode] = useState(style.hashtags_mode || 'end'); const [bannedWords, setBannedWords] = useState((style.banned_words || []).join(', ')); const [bannedTopics, setBannedTopics] = useState((style.banned_topics || []).join(', ')); // Картинки const [imageEnabled, setImageEnabled] = useState(style.image_enabled ?? false); const [imageStyle, setImageStyle] = useState(style.image_style || 'flat-illustration'); const [imagePalette, setImagePalette] = useState(style.image_palette || 'auto'); const [imageCustomColors, setImageCustomColors] = useState(style.image_custom_colors || ''); const [imagePromptInstructions, setImagePromptInstructions] = useState(style.image_prompt_instructions || ''); // Подключение const [botToken, setBotToken] = useState(channel.bot_token || ''); const [tgChannelId, setTgChannelId] = useState(channel.tg_channel_id || ''); const [tgUsername, setTgUsername] = useState(channel.tg_username || ''); const [vkToken, setVkToken] = useState(channel.vk_access_token || ''); const [tokenVerifying, setTokenVerifying] = useState(false); const [tokenStatus, setTokenStatus] = useState(null); // null | 'ok' | 'error' const [saving, setSaving] = useState(false); const [deleting, setDeleting] = useState(false); const [error, setError] = useState(''); const [toast, setToast] = useState(''); async function save() { setSaving(true); setError(''); try { const data = { name, niche, audience, goal: goals.join(','), language, bot_token: botToken.trim() || null, tg_channel_id: tgChannelId.trim() || null, tg_username: tgUsername.trim() || null, vk_access_token: vkToken.trim() || null, style: { tone, formality, humor, post_length: postLength, emoji_level: emojiLevel, hashtags_mode: hashtagsMode, banned_words: bannedWords.split(',').map(s => s.trim()).filter(Boolean), banned_topics: bannedTopics.split(',').map(s => s.trim()).filter(Boolean), image_enabled: imageEnabled, image_style: imageStyle, image_palette: imagePalette, image_custom_colors: imageCustomColors.trim() || null, image_prompt_instructions: imagePromptInstructions.trim() || null, }, }; const res = await fetch(`/api/channels/${channel.id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }); if (!res.ok) throw new Error(await res.text()); setToast('Сохранено'); setTimeout(() => setToast(''), 2500); router.refresh(); } catch (e) { setError(e.message); } finally { setSaving(false); } } async function del() { if (!confirm(`Удалить канал «${channel.name}»? Это действие необратимо.`)) return; setDeleting(true); try { await fetch(`/api/channels/${channel.id}`, { method: 'DELETE' }); router.push('/'); } catch (e) { setError(e.message); setDeleting(false); } } return (
К каналу

Настройки канала

{toast && {toast}}
{error && (
{error}
)} {/* Tabs */}
{TABS.map(({ id, label, icon: Icon }) => ( ))}
{/* TAB: Контент */} {tab === 'content' && (
setName(e.target.value)} />