import { useEffect, useState } from 'react'; import { Trash2, UserPlus } from 'lucide-react'; import { api } from '../lib/api.js'; const fieldCls = 'w-full rounded-md border px-3 py-2 text-sm bg-transparent border-slate-300 dark:border-slate-700'; function PasswordForm() { const [form, setForm] = useState({ currentPassword: '', newPassword: '', confirm: '' }); const [message, setMessage] = useState(null); // { type: 'ok' | 'error', text } const [busy, setBusy] = useState(false); async function handleSubmit(e) { e.preventDefault(); setMessage(null); if (form.newPassword !== form.confirm) { setMessage({ type: 'error', text: 'Новые пароли не совпадают' }); return; } if (form.newPassword.length < 8) { setMessage({ type: 'error', text: 'Новый пароль должен быть не короче 8 символов' }); return; } setBusy(true); try { await api.changePassword(form.currentPassword, form.newPassword); setMessage({ type: 'ok', text: 'Пароль изменён' }); setForm({ currentPassword: '', newPassword: '', confirm: '' }); } catch (err) { setMessage({ type: 'error', text: err.message === 'current password is incorrect' ? 'Текущий пароль указан неверно' : 'Не удалось изменить пароль', }); } finally { setBusy(false); } } return (

Сменить пароль

setForm({ ...form, currentPassword: e.target.value })} className={fieldCls} />
setForm({ ...form, newPassword: e.target.value })} className={fieldCls} />
setForm({ ...form, confirm: e.target.value })} className={fieldCls} />
{message && (

{message.text}

)}
); } function AdminsSection() { const [admins, setAdmins] = useState([]); const [me, setMe] = useState(null); const [loading, setLoading] = useState(true); const [form, setForm] = useState({ username: '', password: '' }); const [error, setError] = useState(''); const [busy, setBusy] = useState(false); async function load() { setLoading(true); const [list, meData] = await Promise.all([api.adminGetAdmins(), api.me()]); setAdmins(list); setMe(meData); setLoading(false); } useEffect(() => { load(); }, []); async function handleCreate(e) { e.preventDefault(); setError(''); if (!form.username.trim()) { setError('Укажите логин'); return; } if (form.password.length < 8) { setError('Пароль должен быть не короче 8 символов'); return; } setBusy(true); try { await api.adminCreateAdminUser(form.username.trim(), form.password); setForm({ username: '', password: '' }); load(); } catch (err) { setError(err.message === 'this username is already taken' ? 'Такой логин уже занят' : 'Не удалось создать администратора'); } finally { setBusy(false); } } async function handleDelete(id) { if (!window.confirm('Удалить этого администратора без возможности восстановления?')) return; try { await api.adminDeleteAdminUser(id); load(); } catch (err) { window.alert( err.message === 'you cannot delete your own account while logged in' ? 'Нельзя удалить самого себя, пока вы вошли под этим аккаунтом' : err.message === 'cannot delete the last remaining admin' ? 'Нельзя удалить последнего администратора - должен остаться хотя бы один' : 'Не удалось удалить' ); } } if (loading) return

Загружаем список администраторов...

; return (

Администраторы

{admins.map((a) => (
{a.username} {me?.id === a.id && (вы)} {me?.id !== a.id && ( )}
))}
setForm({ ...form, username: e.target.value })} className={fieldCls} /> setForm({ ...form, password: e.target.value })} className={fieldCls} /> {error &&

{error}

}
); } export default function Settings() { return (

Настройки

); }