Разработка админ-панели EventHubFrontAdmin v1.0 #1
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { Card, Descriptions, Spin, Button, Tag, Space, Modal, Form, Input, Select, message } from 'antd';
|
||||
import { EditOutlined } from '@ant-design/icons';
|
||||
import { useAdmin, useUpdateAdmin } from '../../hooks/useAdmins';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const AdminDetailPage: React.FC = () => {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const navigate = useNavigate();
|
||||
const { data: admin, isLoading } = useAdmin(id || '');
|
||||
const updateAdmin = useUpdateAdmin();
|
||||
|
||||
const [editModal, setEditModal] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
// Очистка значения
|
||||
const clean = (val: any) => (val === '-' || val === 'undefined' ? undefined : val);
|
||||
|
||||
// Заполнение формы при открытии
|
||||
useEffect(() => {
|
||||
if (editModal && admin) {
|
||||
setTimeout(() => {
|
||||
form.setFieldsValue({
|
||||
nickname: clean(admin.nickname),
|
||||
email: clean(admin.email),
|
||||
role: clean(admin.role),
|
||||
status: clean(admin.status),
|
||||
timezone: clean(admin.timezone),
|
||||
language: clean(admin.language),
|
||||
phone: clean(admin.phone),
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
}, [editModal, admin, form]);
|
||||
|
||||
const handleSave = () => {
|
||||
form.validateFields().then((values) => {
|
||||
const payload = Object.fromEntries(
|
||||
Object.entries(values).filter(([_, v]) => v !== '' && v !== undefined && v !== null)
|
||||
);
|
||||
updateAdmin.mutate(
|
||||
{ id: id!, data: payload },
|
||||
{
|
||||
onSuccess: () => {
|
||||
setEditModal(false);
|
||||
message.success('Данные обновлены');
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const isBadValue = (val: any) =>
|
||||
val === '-' || val === 'undefined' || val === '' || val === null || val === undefined;
|
||||
|
||||
const formatDate = (dateStr: string) => {
|
||||
if (isBadValue(dateStr)) return '-';
|
||||
const d = dayjs(dateStr);
|
||||
return d.isValid() ? d.format('DD.MM.YYYY HH:mm') : dateStr;
|
||||
};
|
||||
|
||||
const roleColors: Record<string, string> = {
|
||||
superadmin: 'red',
|
||||
admin: 'blue',
|
||||
moderator: 'purple',
|
||||
support: 'cyan',
|
||||
};
|
||||
|
||||
if (isLoading) return <Spin size="large" style={{ display: 'block', margin: '100px auto' }} />;
|
||||
if (!admin) return <p>Администратор не найден</p>;
|
||||
|
||||
return (
|
||||
<Card
|
||||
title={`Администратор ${!isBadValue(admin.nickname) ? admin.nickname : admin.email || admin.id}`}
|
||||
extra={
|
||||
<Button icon={<EditOutlined />} onClick={() => setEditModal(true)}>
|
||||
Редактировать
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Descriptions bordered column={1} size="small">
|
||||
<Descriptions.Item label="ID">{admin.id}</Descriptions.Item>
|
||||
<Descriptions.Item label="Email">{admin.email}</Descriptions.Item>
|
||||
<Descriptions.Item label="Ник">{isBadValue(admin.nickname) ? '-' : admin.nickname}</Descriptions.Item>
|
||||
<Descriptions.Item label="Роль">
|
||||
<Tag color={roleColors[admin.role] || 'default'}>{admin.role}</Tag>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Статус">
|
||||
<Tag color={admin.status === 'active' ? 'green' : 'red'}>{admin.status}</Tag>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Часовой пояс">{isBadValue(admin.timezone) ? '-' : admin.timezone}</Descriptions.Item>
|
||||
<Descriptions.Item label="Язык">{isBadValue(admin.language) ? '-' : admin.language}</Descriptions.Item>
|
||||
<Descriptions.Item label="Телефон">{isBadValue(admin.phone) ? '-' : admin.phone}</Descriptions.Item>
|
||||
<Descriptions.Item label="Аватар URL">{isBadValue(admin.avatar_url) ? '-' : admin.avatar_url}</Descriptions.Item>
|
||||
<Descriptions.Item label="Настройки">{isBadValue(admin.preferences) ? '-' : JSON.stringify(admin.preferences)}</Descriptions.Item>
|
||||
<Descriptions.Item label="Последний вход">{formatDate(admin.last_login)}</Descriptions.Item>
|
||||
<Descriptions.Item label="Создано">{formatDate(admin.created_at)}</Descriptions.Item>
|
||||
<Descriptions.Item label="Обновлено">{formatDate(admin.updated_at)}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<Button style={{ marginTop: 16 }} onClick={() => navigate('/admins')}>Назад к списку</Button>
|
||||
|
||||
<Modal
|
||||
title="Редактировать администратора"
|
||||
open={editModal}
|
||||
onCancel={() => setEditModal(false)}
|
||||
onOk={handleSave}
|
||||
confirmLoading={updateAdmin.isPending}
|
||||
destroyOnHidden
|
||||
>
|
||||
<Form form={form} layout="vertical" preserve={false}>
|
||||
<Form.Item name="nickname" label="Ник">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item name="email" label="Email">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item name="role" label="Роль">
|
||||
<Select>
|
||||
<Select.Option value="superadmin">superadmin</Select.Option>
|
||||
<Select.Option value="admin">admin</Select.Option>
|
||||
<Select.Option value="moderator">moderator</Select.Option>
|
||||
<Select.Option value="support">support</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="status" label="Статус">
|
||||
<Select>
|
||||
<Select.Option value="active">active</Select.Option>
|
||||
<Select.Option value="blocked">blocked</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="timezone" label="Часовой пояс">
|
||||
<Select placeholder="Выберите пояс" allowClear>
|
||||
<Select.Option value="UTC">UTC</Select.Option>
|
||||
<Select.Option value="Europe/Moscow">Europe/Moscow (Москва)</Select.Option>
|
||||
<Select.Option value="Europe/London">Europe/London (Лондон)</Select.Option>
|
||||
<Select.Option value="Europe/Berlin">Europe/Berlin (Берлин)</Select.Option>
|
||||
<Select.Option value="America/New_York">America/New_York (Нью-Йорк)</Select.Option>
|
||||
<Select.Option value="Asia/Tokyo">Asia/Tokyo (Токио)</Select.Option>
|
||||
<Select.Option value="Asia/Shanghai">Asia/Shanghai (Шанхай)</Select.Option>
|
||||
<Select.Option value="Australia/Sydney">Australia/Sydney (Сидней)</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="language" label="Язык">
|
||||
<Select placeholder="Выберите язык" allowClear>
|
||||
<Select.Option value="ru">Русский</Select.Option>
|
||||
<Select.Option value="en">English</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="phone" label="Телефон">
|
||||
<Input placeholder="+7 (999) 123-45-67" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminDetailPage;
|
||||
Reference in New Issue
Block a user