From 69226cbbdef2bece7c6710e16837b38646a3ce2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=20=28Claude=29?= Date: Tue, 9 Jun 2026 08:39:32 +0300 Subject: [PATCH] fix: Link2 undefined crash + goal multi-select + custom goal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ChannelView.js: - Добавлен Link2 в import lucide-react (ReferenceError при открытии канала) - Отображение goal учитывает множественные значения через split(',') app/page.js: - Аналогичный фикс отображения goal (split → map → join) channels/new/page.js: - Цель канала: single-select → multi-select (можно выбрать несколько) - Кастомная цель: поле + кнопка «+», Enter, чипы с удалением - Сохраняется как CSV строка (goal: goals.join(',')) DB: - channels.goal varchar(50) → varchar(255) для длинных кастомных значений --- app/channels/new/page.js | 78 +++++++++++++++++++++++++++++++-------- app/page.js | 2 +- components/ChannelView.js | 4 +- 3 files changed, 65 insertions(+), 19 deletions(-) diff --git a/app/channels/new/page.js b/app/channels/new/page.js index 481fc3f..d7e4fd3 100644 --- a/app/channels/new/page.js +++ b/app/channels/new/page.js @@ -49,7 +49,8 @@ export default function NewChannelPage() { const [name, setName] = useState(''); const [niche, setNiche] = useState(''); const [audience, setAudience] = useState(''); - const [goal, setGoal] = useState('educational'); + const [goals, setGoals] = useState(['educational']); // multi-select, отправляем как CSV + const [customGoal, setCustomGoal] = useState(''); // поле для своей цели const [language, setLanguage] = useState('ru'); // Шаг 2 — стиль @@ -70,7 +71,7 @@ export default function NewChannelPage() { setBusy(true); setError(''); const data = { - name, niche, audience, goal, language, region: 'ru', + name, niche, audience, goal: goals.join(','), language, region: 'ru', style: { tone, formality, humor, post_length: postLength, @@ -150,22 +151,67 @@ export default function NewChannelPage() { />
- +
- {GOALS.map(g => ( - - ))} + {GOALS.map(g => { + const on = goals.includes(g.v); + return ( + + ); + })}
+ {/* Своя цель */} +
+ setCustomGoal(e.target.value)} + onKeyDown={e => { + if (e.key === 'Enter') { + e.preventDefault(); + const v = customGoal.trim(); + if (v && !goals.includes(v)) setGoals([...goals, v]); + setCustomGoal(''); + } + }} + /> + +
+ {/* Выбранные кастомные цели — чипы */} + {goals.filter(g => !GOALS.find(x => x.v === g)).length > 0 && ( +
+ {goals.filter(g => !GOALS.find(x => x.v === g)).map(g => ( + + {g} + + + ))} +
+ )}
diff --git a/app/page.js b/app/page.js index 43e2c1e..8e4d152 100644 --- a/app/page.js +++ b/app/page.js @@ -68,7 +68,7 @@ export default async function HomePage() { {ch.name} - {GOAL_LABELS[ch.goal] || ch.goal} + {(ch.goal || '').split(',').map(g => GOAL_LABELS[g.trim()] || g.trim()).join(' · ')}
{ch.niche && ( diff --git a/components/ChannelView.js b/components/ChannelView.js index 5f9a1b8..695f523 100644 --- a/components/ChannelView.js +++ b/components/ChannelView.js @@ -4,7 +4,7 @@ import Link from 'next/link'; import { ArrowLeft, Sparkles, Wand2, Copy, Check, Loader2, Settings, Image as ImageIcon, RefreshCw, Scissors, Maximize2, Zap, Heart, - MessageSquare, Pencil, X, Send, Clock, Search, Camera, ExternalLink + MessageSquare, Pencil, X, Send, Clock, Search, Camera, ExternalLink, Link2 } from 'lucide-react'; import PhotoSearchModal from './PhotoSearchModal'; import PostPreview from './PostPreview'; @@ -330,7 +330,7 @@ export default function ChannelView({ channel }) {

{channel.name}

- {GOAL_LABELS[channel.goal] || channel.goal} + {(channel.goal || '').split(',').map(g => GOAL_LABELS[g.trim()] || g.trim()).join(' · ')} {channel.niche &&

{channel.niche}

}