feat: PollModal + HashtagSuggest UI

PollModal:
- Вопрос + 2-10 вариантов ответа
- Типы: обычный / викторина (с правильным ответом и объяснением)
- Настройки: анонимность, несколько ответов
- Отложенная публикация через datetime-local
- Кнопка «📊 Опрос» в ChannelView (только для TG каналов)

HashtagSuggest:
- Появляется под сгенерированным постом
- Запрос в /api/generate/hashtags → Claude Haiku
- Клик по тегу — выбор, кнопка «Добавить в пост»
- Обновление тегов, закрытие панели
This commit is contained in:
Ник (Claude)
2026-06-11 19:55:24 +03:00
parent 675d04c5ab
commit d0fd328011
5 changed files with 376 additions and 1 deletions
+30 -1
View File
@@ -11,6 +11,8 @@ import PostPreview from './PostPreview';
import PostTemplates from './PostTemplates';
import ChannelAnalytics from './ChannelAnalytics';
import FromUrlModal from './FromUrlModal';
import PollModal from './PollModal';
import HashtagSuggest from './HashtagSuggest';
const GOAL_LABELS = {
educational: 'Обучение', news: 'Новости',
@@ -58,6 +60,7 @@ export default function ChannelView({ channel }) {
// Photo search modal
const [showPhotoSearch, setShowPhotoSearch] = useState(false);
const [showFromUrl, setShowFromUrl] = useState(false);
const [showPoll, setShowPoll] = useState(false);
// Трансформации
const [transforming, setTransforming] = useState(false);
@@ -383,6 +386,15 @@ export default function ChannelView({ channel }) {
<Link2 className="w-3.5 h-3.5" />
По ссылке
</button>
{channel.platform === 'telegram' && (
<button
onClick={() => setShowPoll(true)}
className="text-xs inline-flex items-center gap-1 text-gray-400 hover:text-accent transition-colors"
>
<span>📊</span>
Опрос
</button>
)}
<button
onClick={fetchIdeas}
disabled={loadingIdeas}
@@ -526,7 +538,12 @@ export default function ChannelView({ channel }) {
</div>
)}
{/* Картинка к посту */}
{/* Хештеги */}
<HashtagSuggest
channelId={channel.id}
postText={post}
onAppend={text => setPost(p => (p || '') + text)}
/>
{image && (
<div className="mt-4">
<div className="relative">
@@ -699,6 +716,18 @@ export default function ChannelView({ channel }) {
onApply={applyFromUrl}
/>
{showPoll && (
<PollModal
channel={channel}
onClose={() => setShowPoll(false)}
onPublished={r => {
setShowPoll(false);
// Уведомление
if (r.scheduled) alert(`Опрос запланирован на ${new Date(r.scheduled_at).toLocaleString('ru-RU')}`);
}}
/>
)}
{/* Photo search modal */}
<PhotoSearchModal
open={showPhotoSearch}