'use client'; import { useState, useEffect, useMemo } from 'react'; import UserEditModal from '@/components/UserEditModal'; import { PageLayout, DataTable, StatusBadge, Modal } from '@/components/ui'; const RL: Record = { admin: 'Администратор', authority_inspector: 'Инспектор', favt_inspector: 'Инспектор ФАВТ', operator_manager: 'Менеджер оператора', operator_user: 'Оператор', mro_manager: 'Менеджер ТОиР', mro_specialist: 'Специалист ТОиР', mro_user: 'Специалист ТОиР', engineer: 'Инженер', inspector: 'Инспектор' }; const RC: Record = { admin: 'bg-green-500', authority_inspector: 'bg-blue-500', favt_inspector: 'bg-blue-500', operator_manager: 'bg-orange-500', operator_user: 'bg-orange-400', mro_manager: 'bg-purple-500', mro_specialist: 'bg-purple-400', mro_user: 'bg-purple-400', engineer: 'bg-teal-500', inspector: 'bg-indigo-500' }; const DEMO_USERS = [ { id: '1', display_name: 'Иванов Иван Иванович', email: 'ivanov@company.ru', role: 'admin', organization_name: 'АО «Авиакомпания»', status: 'active', last_login: '2024-12-01T10:00:00Z' }, { id: '2', display_name: 'Петрова Мария Сергеевна', email: 'petrova@favt.gov.ru', role: 'authority_inspector', organization_name: 'ФАВТ', status: 'active', last_login: '2024-12-02T09:15:00Z' }, { id: '3', display_name: 'Сидоров Пётр Андреевич', email: 'sidorov@operator.ru', role: 'operator_manager', organization_name: 'ООО «АвиаСервис»', status: 'active', last_login: '2024-11-28T14:20:00Z' }, { id: '4', display_name: 'Козлова Анна Викторовна', email: 'kozlova@mro.ru', role: 'mro_manager', organization_name: 'ПАО «ТОиР»', status: 'active', last_login: '2024-12-01T08:00:00Z' }, { id: '5', display_name: 'Новиков Алексей Дмитриевич', email: 'novikov@company.ru', role: 'engineer', organization_name: 'АО «Авиакомпания»', status: 'active', last_login: '2024-11-30T16:45:00Z' }, { id: '6', display_name: 'Морозова Елена Игоревна', email: 'morozova@favt.gov.ru', role: 'inspector', organization_name: 'Ространснадзор', status: 'active', last_login: '2024-11-29T11:00:00Z' }, { id: '7', display_name: 'Волков Дмитрий Николаевич', email: 'volkov@operator.ru', role: 'operator_user', organization_name: 'ООО «АвиаСервис»', status: 'active', last_login: '2024-11-27T12:30:00Z' }, { id: '8', display_name: 'Соколова Ольга Павловна', email: 'sokolova@mro.ru', role: 'mro_specialist', organization_name: 'ПАО «ТОиР»', status: 'inactive', last_login: '2024-10-15T09:00:00Z' }, { id: '9', display_name: 'Лебедев Андрей Владимирович', email: 'lebedev@company.ru', role: 'operator_user', organization_name: 'АО «Авиакомпания»', status: 'active', last_login: '2024-12-02T07:20:00Z' }, { id: '10', display_name: 'Кузнецова Татьяна Александровна', email: 'kuznetsova@favt.gov.ru', role: 'favt_inspector', organization_name: 'Минтранс / ФАВТ', status: 'active', last_login: '2024-12-01T15:10:00Z' }, ]; export default function UsersPage() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [roleFilter, setRoleFilter] = useState(); const [orgFilter, setOrgFilter] = useState(''); const [search, setSearch] = useState(''); const [addOpen, setAddOpen] = useState(false); const [addForm, setAddForm] = useState({ display_name: '', email: '', role: 'operator_user', organization_name: '' }); const [editingUser, setEditingUser] = useState(null); useEffect(() => { setLoading(true); fetch('/api/v1/users') .then(r => r.json()) .then(d => setUsers(Array.isArray(d?.items) && d.items.length > 0 ? d.items : DEMO_USERS)) .catch(() => setUsers(DEMO_USERS)) .finally(() => setLoading(false)); }, []); const filtered = useMemo(() => { let list = users; if (roleFilter) list = list.filter(u => u.role === roleFilter); if (orgFilter) list = list.filter(u => (u.organization_name || '').toLowerCase().includes(orgFilter.toLowerCase())); if (search) { const q = search.toLowerCase(); list = list.filter(u => (u.display_name || '').toLowerCase().includes(q) || (u.email || '').toLowerCase().includes(q) ); } return list; }, [users, roleFilter, orgFilter, search]); const handleSaveEdit = (payload: any) => { if (editingUser?.id) setUsers(prev => prev.map(u => u.id === editingUser.id ? { ...u, ...payload } : u)); setEditingUser(null); }; const handleAdd = () => { setUsers(prev => [{ ...addForm, id: String(Date.now()), organization_name: addForm.organization_name || '—', status: 'active', last_login: null }, ...prev]); setAddOpen(false); setAddForm({ display_name: '', email: '', role: 'operator_user', organization_name: '' }); }; const handleDelete = (id: string) => { if (!confirm('Удалить пользователя?')) return; setUsers(prev => prev.filter(u => u.id !== id)); }; const handleExport = () => { const headers = ['ФИО', 'Email', 'Роль', 'Организация', 'Статус', 'Последний вход']; const rows = filtered.map(u => [ u.display_name || '', u.email || '', RL[u.role] || u.role, u.organization_name || '', u.status === 'active' ? 'Активен' : 'Неактивен', u.last_login ? new Date(u.last_login).toLocaleString('ru-RU') : '—', ]); const csv = [headers.join(';'), ...rows.map(r => r.join(';'))].join('\n'); const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'users.csv'; a.click(); URL.revokeObjectURL(url); }; const rolesForFilter = Array.from(new Set(users.map(u => u.role).filter(Boolean))); return ( setSearch(e.target.value)} className="input-field w-56" /> setOrgFilter(e.target.value)} className="input-field w-48" /> } > {loading ?
⏳ Загрузка...
: filtered.length > 0 ? (
{filtered.map(u => ( ))}
ФИОEmailРоль ОрганизацияСтатусПоследний входДействия
{u.display_name || '—'} {u.email || '—'} {u.organization_name || '—'} {u.status === 'active' ? 'Активен' : 'Неактивен'} {u.last_login ? new Date(u.last_login).toLocaleString('ru-RU') : '—'}
) :
ℹ️Нет пользователей
} setEditingUser(null)} user={editingUser} onSave={handleSaveEdit} /> setAddOpen(false)} title="Добавить пользователя" size="md" footer={<>}>
setAddForm(f => ({ ...f, display_name: e.target.value }))} className="input-field w-full mt-1" placeholder="Иванов И. И." />
setAddForm(f => ({ ...f, email: e.target.value }))} className="input-field w-full mt-1" placeholder="user@company.ru" />
setAddForm(f => ({ ...f, organization_name: e.target.value }))} className="input-field w-full mt-1" placeholder="Организация" />
); }