import React, { useState, useEffect } from 'react'; import { useUser } from '../context/UserContext'; import EditCampaignModal from '../modals/EditCampaignModal'; import CreateCampaignModal from '../modals/CreateCampaignModal'; import Paginator from '../components/Paginator'; import styles from '../styles/Common.module.css'; const PAGE_SIZE = 10; function CampaignPage() { const { token, user } = useUser(); const [campaigns, setCampaigns] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [loading, setLoading] = useState(false); const [error, setError] = useState(''); const [editCampaign, setEditCampaign] = useState(null); const [editLoading, setEditLoading] = useState(false); const [deleteLoading, setDeleteLoading] = useState(null); const [createCampaign, setCreateCampaign] = useState(null); const [createLoading, setCreateLoading] = useState(false); const [groups, setGroups] = useState([]); const [versions, setVersions] = useState([]); const [smtpServers, setSmtpServers] = useState([]); useEffect(() => { fetchCampaigns(page); // eslint-disable-next-line }, [page]); useEffect(() => { fetchGroups(); fetchVersions(); fetchSmtpServers(); // eslint-disable-next-line }, []); const fetchCampaigns = async (page) => { setLoading(true); setError(''); try { const offset = (page - 1) * PAGE_SIZE; const res = await fetch(`/api/mail/campaigns?limit=${PAGE_SIZE}&offset=${offset}`, { headers: token ? { Authorization: `Bearer ${token}` } : {} }); const data = await res.json(); if (!res.ok) { setError(data.error || 'Ошибка загрузки'); setCampaigns([]); setTotal(0); } else { setCampaigns(Array.isArray(data.rows) ? data.rows : []); setTotal(data.count || 0); } } catch (e) { setError('Ошибка сети'); setCampaigns([]); setTotal(0); } finally { setLoading(false); } }; const fetchGroups = async () => { try { const res = await fetch('/api/mail/mailing-groups', { headers: token ? { Authorization: `Bearer ${token}` } : {} }); const data = await res.json(); if (res.ok && Array.isArray(data.rows)) { setGroups(data.rows); } else if (res.ok && Array.isArray(data)) { setGroups(data); } else { setGroups([]); } } catch { setGroups([]); } }; const fetchVersions = async () => { try { const res = await fetch('/api/mail/email-template-versions', { headers: token ? { Authorization: `Bearer ${token}` } : {} }); const data = await res.json(); if (res.ok && Array.isArray(data.rows)) { setVersions(data.rows); } else if (res.ok && Array.isArray(data)) { setVersions(data); } else { setVersions([]); } } catch { setVersions([]); } }; const fetchSmtpServers = async () => { try { const res = await fetch('/api/mail/smtp-servers', { headers: token ? { Authorization: `Bearer ${token}` } : {} }); const data = await res.json(); if (res.ok && Array.isArray(data.rows)) { setSmtpServers(data.rows); } else if (res.ok && Array.isArray(data)) { setSmtpServers(data); } else { setSmtpServers([]); } } catch { setSmtpServers([]); } }; const handleDelete = async (id) => { if (!window.confirm('Удалить кампанию?')) return; setDeleteLoading(id); try { const res = await fetch(`/api/mail/campaigns/${id}`, { method: 'DELETE', headers: token ? { Authorization: `Bearer ${token}` } : {} }); if (!res.ok) { const data = await res.json(); alert(data.error || 'Ошибка удаления'); } else { fetchCampaigns(page); } } catch (e) { alert('Ошибка сети'); } finally { setDeleteLoading(null); } }; const handleEdit = (c) => { setEditCampaign(c); }; const handleEditSave = async (e) => { e.preventDefault(); setEditLoading(true); try { const res = await fetch(`/api/mail/campaigns/${editCampaign.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) }, body: JSON.stringify(editCampaign) }); if (!res.ok) { const data = await res.json(); alert(data.error || 'Ошибка обновления'); } else { setEditCampaign(null); fetchCampaigns(page); } } catch (e) { alert('Ошибка сети'); } finally { setEditLoading(false); } }; const handleCreate = () => { setCreateCampaign({ group_id: null, template_version_id: null, subject_override: '', status: 'draft', scheduled_at: '', smtp_server_id: null, user_id: user?.id // Добавляем user_id }); }; const handleCreateSave = async (e) => { e.preventDefault(); setCreateLoading(true); try { const res = await fetch('/api/mail/campaigns', { method: 'POST', headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) }, body: JSON.stringify(createCampaign) }); if (!res.ok) { const data = await res.json(); alert(data.error || 'Ошибка создания'); } else { setCreateCampaign(null); fetchCampaigns(page); } } catch (e) { alert('Ошибка сети'); } finally { setCreateLoading(false); } }; const getGroupName = (id) => groups.find(g => g.id === id)?.name || id; const getVersionName = (id) => { const v = versions.find(v => v.id === id); return v ? `#${v.id} ${v.subject}` : id; }; return (

Кампания

{loading &&
Загрузка...
} {error &&
{error}
} {!loading && !error && ( <> {campaigns.map(c => ( ))} {campaigns.length === 0 && ( )}
ID Группа Версия шаблона Тема Статус Запланировано Действия
{c.id} {getGroupName(c.group_id)} {getVersionName(c.template_version_id)} {c.subject_override || ''} {c.status} {c.scheduled_at ? new Date(c.scheduled_at).toLocaleString() : ''}
📧
Нет кампаний
Создайте первую кампанию для начала работы
)} {editCampaign && ( setEditCampaign(null)} campaign={editCampaign} groups={groups} versions={versions} smtpServers={smtpServers} loading={editLoading} onChange={setEditCampaign} onSave={handleEditSave} getVersionName={getVersionName} /> )} {createCampaign && ( setCreateCampaign(null)} campaign={createCampaign} groups={groups} versions={versions} smtpServers={smtpServers} loading={createLoading} onChange={setCreateCampaign} onSave={handleCreateSave} getVersionName={getVersionName} /> )}
); } export default CampaignPage;