ads-marketing/frontend/src/pages/SmtpServersPage.js
2025-07-23 17:45:31 +05:00

239 lines
8.0 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { useUser } from '../context/UserContext';
import EditSmtpModal from '../modals/EditSmtpModal';
import CreateSmtpModal from '../modals/CreateSmtpModal';
import Paginator from '../components/Paginator';
const PAGE_SIZE = 10;
function SmtpServersPage() {
const { token, user } = useUser();
const [servers, setServers] = useState([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [editServer, setEditServer] = useState(null);
const [editLoading, setEditLoading] = useState(false);
const [deleteLoading, setDeleteLoading] = useState(null);
const [createServer, setCreateServer] = useState(null);
const [createLoading, setCreateLoading] = useState(false);
useEffect(() => {
fetchServers(page);
// eslint-disable-next-line
}, [page]);
const fetchServers = async (page) => {
if (!token) {
setError('Нет авторизации');
setServers([]);
setTotal(0);
return;
}
setLoading(true);
setError('');
try {
const offset = (page - 1) * PAGE_SIZE;
const res = await fetch(`/api/mail/smtp-servers?limit=${PAGE_SIZE}&offset=${offset}`, {
headers: { Authorization: `Bearer ${token}` }
});
const data = await res.json();
if (!res.ok) {
setError(data.error || 'Ошибка загрузки SMTP-серверов');
setServers([]);
setTotal(0);
} else {
setServers(Array.isArray(data) ? data : data.rows || []);
setTotal(data.count || (Array.isArray(data) ? data.length : 0));
}
} catch (e) {
setError('Ошибка сети');
setServers([]);
setTotal(0);
} finally {
setLoading(false);
}
};
const handleDelete = async (id) => {
if (!token) {
alert('Нет авторизации');
return;
}
if (!window.confirm('Удалить SMTP-сервер?')) return;
setDeleteLoading(id);
try {
const res = await fetch(`/api/mail/smtp-servers/${id}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${token}` }
});
if (!res.ok) {
const data = await res.json();
alert(data.error || 'Ошибка удаления');
} else {
fetchServers(page);
}
} catch (e) {
alert('Ошибка сети');
} finally {
setDeleteLoading(null);
}
};
const handleEdit = (server) => {
setEditServer(server);
};
const handleEditSave = async (e) => {
e.preventDefault();
if (!token) {
alert('Нет авторизации');
return;
}
setEditLoading(true);
try {
const { group_id, ...serverData } = editServer;
const res = await fetch(`/api/mail/smtp-servers/${editServer.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: JSON.stringify({ ...serverData, user_id: user?.id })
});
if (!res.ok) {
const data = await res.json();
alert(data.error || 'Ошибка обновления');
} else {
setEditServer(null);
fetchServers(page);
}
} catch (e) {
alert('Ошибка сети');
} finally {
setEditLoading(false);
}
};
const handleCreate = () => {
setCreateServer({
name: '', host: '', port: 587, secure: false, username: '', password: '', from_email: ''
});
};
const handleCreateSave = async (e) => {
e.preventDefault();
if (!token) {
alert('Нет авторизации');
return;
}
setCreateLoading(true);
try {
const { group_id, ...serverData } = createServer;
const res = await fetch('/api/mail/smtp-servers', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: JSON.stringify({ ...serverData, user_id: user?.id })
});
if (!res.ok) {
const data = await res.json();
alert(data.error || 'Ошибка создания');
} else {
setCreateServer(null);
fetchServers(page);
}
} catch (e) {
alert('Ошибка сети');
} finally {
setCreateLoading(false);
}
};
return (
<div>
<div style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', marginBottom: 12 }}>
<button onClick={handleCreate} style={addBtnStyle}>+ Добавить SMTP-сервер</button>
</div>
<h2>SMTP-серверы</h2>
{loading && <div>Загрузка...</div>}
{error && <div style={{ color: 'red' }}>{error}</div>}
{!loading && !error && (
<>
<table style={{ width: '100%', borderCollapse: 'collapse', marginTop: 16, background: '#fff', borderRadius: 8, overflow: 'hidden' }}>
<thead style={{ background: '#f3f4f6' }}>
<tr>
<th style={thStyle}>ID</th>
<th style={thStyle}>Название</th>
<th style={thStyle}>Host</th>
<th style={thStyle}>Port</th>
<th style={thStyle}>Secure</th>
<th style={thStyle}>Пользователь</th>
<th style={thStyle}>Отправитель</th>
<th style={thStyle}></th>
</tr>
</thead>
<tbody>
{servers.map(s => (
<tr key={s.id} style={{ borderBottom: '1px solid #e5e7eb' }}>
<td style={tdStyle}>{s.id}</td>
<td style={tdStyle}>{s.name}</td>
<td style={tdStyle}>{s.host}</td>
<td style={tdStyle}>{s.port}</td>
<td style={tdStyle}>{s.secure ? 'Да' : 'Нет'}</td>
<td style={tdStyle}>{s.username}</td>
<td style={tdStyle}>{s.from_email}</td>
<td style={tdStyle}>
<button onClick={() => handleEdit(s)} style={btnStyle}>Редактировать</button>
<button onClick={() => handleDelete(s.id)} style={btnStyle} disabled={deleteLoading === s.id}>
{deleteLoading === s.id ? 'Удаление...' : 'Удалить'}
</button>
</td>
</tr>
))}
{servers.length === 0 && (
<tr><td colSpan={8} style={{ textAlign: 'center', color: '#9ca3af', padding: 24 }}>Нет данных</td></tr>
)}
</tbody>
</table>
<Paginator
page={page}
total={total}
pageSize={PAGE_SIZE}
onPageChange={setPage}
/>
</>
)}
{editServer && (
<EditSmtpModal
isOpen={!!editServer}
onClose={() => setEditServer(null)}
server={editServer}
loading={editLoading}
onChange={setEditServer}
onSave={handleEditSave}
/>
)}
{createServer && (
<CreateSmtpModal
isOpen={!!createServer}
onClose={() => setCreateServer(null)}
server={createServer}
loading={createLoading}
onChange={setCreateServer}
onSave={handleCreateSave}
/>
)}
</div>
);
}
const thStyle = { padding: '10px 16px', textAlign: 'left', fontWeight: 600, borderBottom: '2px solid #e5e7eb', background: '#f3f4f6' };
const tdStyle = { padding: '10px 16px', background: '#fff' };
const btnStyle = { marginRight: 8, padding: '6px 12px', borderRadius: 6, border: 'none', background: '#6366f1', color: '#fff', cursor: 'pointer', fontWeight: 500 };
const addBtnStyle = { background: 'linear-gradient(90deg, #6366f1 0%, #06b6d4 100%)', color: '#fff', border: 'none', borderRadius: 8, padding: '10px 22px', fontSize: 16, fontWeight: 600, cursor: 'pointer', boxShadow: '0 2px 8px 0 rgba(99,102,241,0.10)', transition: 'background 0.2s' };
export default SmtpServersPage;