'use client'; import { useState, useEffect, useCallback } from 'react'; import { Clock, Check, X, Edit3, Trash2, RefreshCw, Loader2, Calendar, Image as ImgIcon, Zap } from 'lucide-react'; import Link from 'next/link'; const STATUS_TABS = [ { v: 'pending', label: 'Ожидают', color: 'text-accent' }, { v: 'approved', label: 'Одобрено', color: 'text-green-400' }, { v: 'rejected', label: 'Отклонено', color: 'text-gray-500' }, ]; function timeAgo(s) { const d = new Date(s), now = new Date(); const diff = now - d; if (diff < 3600000) return Math.floor(diff / 60000) + ' мин назад'; if (diff < 86400000) return Math.floor(diff / 3600000) + 'ч назад'; return d.toLocaleDateString('ru-RU'); } export default function DraftsPage() { const [tab, setTab] = useState('pending'); const [drafts, setDrafts] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading]= useState(true); const [editing, setEditing]= useState(null); // draft id const [editText,setEditText]=useState(''); const [schedMap,setSchedMap]=useState({}); // draftId → scheduledAt const [busy, setBusy] = useState({}); const load = useCallback(async (t = tab) => { setLoading(true); try { const res = await fetch(`/api/drafts?status=${t}&limit=50`).then(r => r.json()); setDrafts(res.drafts || []); setTotal(res.total || 0); } catch {} setLoading(false); }, [tab]); useEffect(() => { load(tab); }, [tab]); async function doApprove(id) { setBusy(b => ({ ...b, [id]: true })); const res = await fetch(`/api/drafts/${id}/approve`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ scheduled_at: schedMap[id] || null }), }).then(r => r.json()); setBusy(b => ({ ...b, [id]: false })); if (res.ok) load(tab); else alert(res.error); } async function doReject(id) { setBusy(b => ({ ...b, [id]: true })); await fetch(`/api/drafts/${id}/reject`, { method: 'POST' }); setBusy(b => ({ ...b, [id]: false })); load(tab); } async function doDelete(id) { if (!confirm('Удалить черновик?')) return; await fetch(`/api/drafts/${id}`, { method: 'DELETE' }); load(tab); } async function saveEdit(id) { await fetch(`/api/drafts/${id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: editText }), }); setEditing(null); load(tab); } const pendingCount = tab === 'pending' ? total : 0; return (

Черновики

{tab === 'pending' && total > 0 ? `${total} ${total === 1 ? 'пост ждёт' : 'поста ждут'} одобрения` : 'Авто-генерированные и пакетные посты на проверку'}

{/* Табы */}
{STATUS_TABS.map(t => ( ))}
{loading &&
} {!loading && drafts.length === 0 && (
{tab === 'pending' ? <>Нет черновиков. Включите авто-генерацию в настройках канала или сгенерируйте вручную. : 'Нет записей'}
)}
{drafts.map(draft => (
{/* Header */}
{draft.channel_name} {draft.platform && {draft.platform}}
{timeAgo(draft.created_at)}
{/* Тема */} {draft.topic && (
💡 {draft.topic}
)} {/* Текст */} {editing === draft.id ? (