feat(AutogenPanel): «Очередь тем» → «Планируется завтра»
Блок теперь показывает черновики сегодняшней генерации: - миниатюра обложки + название + категория - кнопка «Редактировать» → /admin/articles/:id - кнопка удалить черновик - предупреждение если сгенерировано < 4 статей - пустое состояние «появятся в 17:00 МСК» - ссылка «Все черновики →» на /admin/drafts
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
'use client';
|
||||
import Link from 'next/link';
|
||||
import { useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { Play, Plus, Trash2, RefreshCw, Clock, CheckCircle, XCircle, Zap } from 'lucide-react';
|
||||
@@ -291,74 +292,65 @@ export default function AutogenPanel({ status, queue, topics, categories = [] })
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Очередь тем */}
|
||||
{/* Планируется завтра — черновики сегодняшней генерации */}
|
||||
<div className="bg-white dark:bg-neutral-900 rounded-xl border border-neutral-200 dark:border-neutral-800">
|
||||
<div className="flex items-center justify-between px-5 py-4 border-b border-neutral-100 dark:border-neutral-800">
|
||||
<h2 className="text-sm font-semibold text-neutral-900 dark:text-neutral-100">
|
||||
Очередь тем <span className="text-neutral-400 font-normal">({pendingQueue.length})</span>
|
||||
</h2>
|
||||
<button
|
||||
onClick={() => setShowAddForm(v => !v)}
|
||||
className="inline-flex items-center gap-1 px-3 py-1.5 rounded-lg border border-neutral-200 dark:border-neutral-700 text-sm hover:bg-neutral-50 dark:hover:bg-neutral-800 transition-colors"
|
||||
>
|
||||
<Plus className="w-3.5 h-3.5" /> Добавить тему
|
||||
</button>
|
||||
<div>
|
||||
<h2 className="text-sm font-semibold text-neutral-900 dark:text-neutral-100">
|
||||
Планируется завтра
|
||||
<span className="ml-2 text-neutral-400 font-normal text-xs">
|
||||
{pendingQueue.length > 0 ? `${pendingQueue.length} из 4 готово` : 'генерация в 17:00 МСК'}
|
||||
</span>
|
||||
</h2>
|
||||
<p className="text-xs text-neutral-400 mt-0.5">
|
||||
Черновики которые выйдут завтра. Редактируй до 07:00 — потом авто-публикация.
|
||||
</p>
|
||||
</div>
|
||||
<Link href="/admin/drafts"
|
||||
className="inline-flex items-center gap-1 px-3 py-1.5 rounded-lg border border-neutral-200 dark:border-neutral-700 text-sm hover:bg-neutral-50 dark:hover:bg-neutral-800 transition-colors text-neutral-600 dark:text-neutral-400">
|
||||
Все черновики →
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{showAddForm && (
|
||||
<div className="px-5 py-4 border-b border-neutral-100 dark:border-neutral-800 bg-neutral-50 dark:bg-neutral-800/50">
|
||||
<div className="flex gap-3">
|
||||
<select
|
||||
value={newCat}
|
||||
onChange={e => setNewCat(e.target.value)}
|
||||
className="px-3 py-2 rounded-lg border border-neutral-200 dark:border-neutral-700 bg-white dark:bg-neutral-800 text-sm focus:outline-none focus:ring-2 focus:ring-emerald-500 shrink-0"
|
||||
>
|
||||
{Object.entries(CAT_LABELS).map(([v, l]) => (
|
||||
<option key={v} value={v}>{l.icon} {l.name}</option>
|
||||
))}
|
||||
</select>
|
||||
<input
|
||||
type="text"
|
||||
value={newTopic}
|
||||
onChange={e => setNewTopic(e.target.value)}
|
||||
onKeyDown={e => e.key === 'Enter' && addTopic()}
|
||||
placeholder="Тема статьи..."
|
||||
className="flex-1 px-3 py-2 rounded-lg border border-neutral-200 dark:border-neutral-700 bg-white dark:bg-neutral-800 text-sm focus:outline-none focus:ring-2 focus:ring-emerald-500"
|
||||
autoFocus
|
||||
/>
|
||||
<button
|
||||
onClick={addTopic}
|
||||
disabled={addingTopic || !newTopic.trim()}
|
||||
className="px-4 py-2 rounded-lg bg-emerald-500 hover:bg-emerald-600 disabled:opacity-50 text-white text-sm font-medium transition-colors shrink-0"
|
||||
>
|
||||
{addingTopic ? '...' : 'Добавить'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="divide-y divide-neutral-100 dark:divide-neutral-800">
|
||||
{pendingQueue.length === 0 && !showAddForm && (
|
||||
{pendingQueue.length === 0 && (
|
||||
<div className="px-5 py-8 text-center text-sm text-neutral-400">
|
||||
Очередь пуста — темы берутся из банка автоматически
|
||||
<div className="text-2xl mb-2">⏳</div>
|
||||
Черновики появятся сегодня в 17:00 МСК
|
||||
</div>
|
||||
)}
|
||||
{pendingQueue.map(item => {
|
||||
const cat = CAT_LABELS[item.category];
|
||||
const cat = CAT_LABELS[item.category] || { icon: '📝', name: item.category, color: 'neutral' };
|
||||
return (
|
||||
<div key={item.id} className="flex items-center gap-3 px-5 py-3">
|
||||
<span className="text-lg shrink-0">{cat?.icon || '📝'}</span>
|
||||
<div key={item.id} className="flex items-center gap-3 px-5 py-3.5 hover:bg-neutral-50 dark:hover:bg-neutral-800/50 transition-colors">
|
||||
{item.cover_url
|
||||
? <img src={item.cover_url} alt="" className="w-12 h-9 rounded-md object-cover shrink-0 bg-neutral-100" />
|
||||
: <div className="w-12 h-9 rounded-md bg-neutral-100 dark:bg-neutral-800 flex items-center justify-center text-xl shrink-0">{cat.icon}</div>
|
||||
}
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="text-sm text-neutral-900 dark:text-neutral-100 truncate">{item.topic}</div>
|
||||
<div className="text-xs text-neutral-400">{cat?.name} · приоритет {item.priority}</div>
|
||||
<div className="text-sm font-medium text-neutral-900 dark:text-neutral-100 truncate">{item.title || '—'}</div>
|
||||
<div className="text-xs text-neutral-400 mt-0.5">{cat.icon} {cat.name}</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1 shrink-0">
|
||||
<Link href={`/admin/articles/${item.id}`}
|
||||
className="px-2.5 py-1.5 rounded-lg text-xs border border-neutral-200 dark:border-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors">
|
||||
Редактировать
|
||||
</Link>
|
||||
<button onClick={() => removeTopic(item.id)}
|
||||
className="p-1.5 rounded text-neutral-300 hover:text-red-500 transition-colors" title="Удалить черновик">
|
||||
<Trash2 className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
<button onClick={() => removeTopic(item.id)} className="p-1.5 rounded text-neutral-300 hover:text-red-500 transition-colors">
|
||||
<Trash2 className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{pendingQueue.length > 0 && pendingQueue.length < 4 && (
|
||||
<div className="px-5 py-3 bg-amber-50 dark:bg-amber-950/20 border-t border-amber-100 dark:border-amber-900/30 text-xs text-amber-700 dark:text-amber-400 rounded-b-xl">
|
||||
⚠️ Сгенерировано {pendingQueue.length} из 4 статей. Запусти генерацию вручную для недостающих категорий.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Банк тем */}
|
||||
|
||||
Reference in New Issue
Block a user