'use client'; import { useState, useEffect, useCallback } from 'react'; import { MessageCircle, RefreshCw, Send, X, Ban, CheckCheck, Loader2, Bell, BellOff } from 'lucide-react'; const STATUS_TABS = [ { v: 'new', label: 'Новые', color: 'text-accent' }, { v: 'all', label: 'Все', color: 'text-gray-400' }, { v: 'replied', label: 'Отвечено', color: 'text-green-400' }, { v: 'ignored', label: 'Игнорировано', color: 'text-gray-500' }, ]; const TYPE_ICONS = { question: '❓', praise: '👍', complaint: '😤', spam: '🚫', other: '💬', }; const TYPE_COLORS = { question: 'border-blue-500/30 bg-blue-500/5', praise: 'border-green-500/30 bg-green-500/5', complaint: 'border-red-500/30 bg-red-500/5', spam: 'border-gray-600 bg-gray-800/50 opacity-60', other: 'border-border', }; function fmtDate(s) { const d = new Date(s); const now = new Date(); const diff = now - d; if (diff < 60000) return 'только что'; if (diff < 3600000) return Math.floor(diff/60000) + ' мин назад'; if (diff < 86400000) return Math.floor(diff/3600000) + 'ч назад'; return d.toLocaleDateString('ru-RU'); } export default function InboxTab({ channel }) { const [tab, setTab] = useState('new'); const [messages, setMessages] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(true); const [replyId, setReplyId] = useState(null); const [replyText,setReplyText]= useState(''); const [sending, setSending] = useState(false); const [webhookOk,setWebhookOk]= useState(channel.tg_webhook_enabled); const [setupping,setSetuppping]= useState(false); const load = useCallback(async (t = tab) => { setLoading(true); try { const res = await fetch(`/api/inbox/channel/${channel.id}?status=${t}&limit=40`).then(r => r.json()); setMessages(res.messages || []); setTotal(res.total || 0); } catch {} setLoading(false); }, [channel.id, tab]); useEffect(() => { load(tab); }, [tab]); async function setupWebhook() { setSetuppping(true); try { const res = await fetch(`/api/inbox/channel/${channel.id}/setup-webhook`, { method: 'POST' }).then(r => r.json()); if (res.ok) { setWebhookOk(true); load(tab); } else alert(res.error || 'Ошибка'); } catch { alert('Ошибка соединения'); } setSetuppping(false); } async function sendReply(msg) { if (!replyText.trim()) return; setSending(true); try { const res = await fetch(`/api/inbox/message/${msg.id}/reply`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: replyText }), }).then(r => r.json()); if (res.ok) { setReplyId(null); setReplyText(''); load(tab); } else alert(res.error || 'Ошибка'); } catch { alert('Ошибка'); } setSending(false); } async function setStatus(msgId, status) { await fetch(`/api/inbox/message/${msgId}/status`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status }), }); load(tab); } const newCount = messages.filter(m => m.status === 'new').length; return (
{/* Webhook setup */} {!webhookOk && (
Webhook не настроен
Нужно подключить webhook чтобы получать комментарии
)} {webhookOk && (
Webhook активен — получаем комментарии
)} {/* Tabs */}
{STATUS_TABS.map(t => ( ))}
{/* Messages */} {loading &&
} {!loading && messages.length === 0 && (
{tab === 'new' ? 'Новых комментариев нет' : 'Нет сообщений'}
)} {!loading && messages.map(msg => (
{/* Header */}
{TYPE_ICONS[msg.ai_type] || '💬'}
{msg.from_name || msg.from_username || 'Аноним'} {msg.from_username && ( @{msg.from_username} )}
{msg.status === 'replied' && } {fmtDate(msg.created_at)}
{/* Text */}

{msg.text}

{/* AI Reply Suggestion */} {msg.ai_reply && msg.status === 'new' && (
✨ Предложенный ответ AI

{msg.ai_reply}

)} {/* Reply form */} {replyId === msg.id ? (