feat: Добавлена страница администрирования пользователей
Добавлены функции создания пользователей. Исправлены ошибки при загрузке данных.
This commit is contained in:
parent
d0d5bc2798
commit
c14ecf1767
20
web-app/src/Api/registerApi.js
Normal file
20
web-app/src/Api/registerApi.js
Normal file
@ -0,0 +1,20 @@
|
||||
import {baseQueryWithAuth} from "./baseQuery.js";
|
||||
import {createApi} from "@reduxjs/toolkit/query/react";
|
||||
|
||||
|
||||
export const registerApi = createApi({
|
||||
reducerPath: 'registerApi',
|
||||
baseQuery: baseQueryWithAuth,
|
||||
tagTypes: ['Register'],
|
||||
endpoints: (builder) => ({
|
||||
register: builder.mutation({
|
||||
query: (credentials) => ({
|
||||
url: '/register/',
|
||||
method: 'POST',
|
||||
body: credentials,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const {useRegisterMutation} = registerApi;
|
||||
18
web-app/src/Api/rolesApi.js
Normal file
18
web-app/src/Api/rolesApi.js
Normal file
@ -0,0 +1,18 @@
|
||||
import {createApi} from "@reduxjs/toolkit/query/react";
|
||||
import {baseQueryWithAuth} from "./baseQuery.js";
|
||||
|
||||
|
||||
export const rolesApi = createApi({
|
||||
reducerPath: 'rolesApi',
|
||||
baseQuery: baseQueryWithAuth,
|
||||
tagTypes: ['Roles'],
|
||||
endpoints: (builder) => ({
|
||||
getRoles: builder.query({
|
||||
query: () => '/roles/',
|
||||
providesTags: ['Roles'],
|
||||
refetchOnMountOrArgChange: 5,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const {useGetRolesQuery} = rolesApi;
|
||||
@ -1,7 +1,7 @@
|
||||
import { Navigate, Outlet } from "react-router-dom";
|
||||
import {Navigate, Outlet} from "react-router-dom";
|
||||
import {useGetAuthenticatedUserDataQuery} from "../Api/usersApi.js";
|
||||
import LoadingIndicator from "../Components/Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
||||
import {Alert} from "antd";
|
||||
import {Result} from "antd";
|
||||
|
||||
const AdminRoute = () => {
|
||||
const {
|
||||
@ -13,22 +13,22 @@ const AdminRoute = () => {
|
||||
});
|
||||
|
||||
if (isUserLoading) {
|
||||
return <LoadingIndicator />;
|
||||
return <LoadingIndicator/>;
|
||||
}
|
||||
|
||||
if (isUserError) {
|
||||
return <Alert message="Ошибка загрузки данных пользователя" type="error" showIcon />;
|
||||
return <Result status="500" title="500" subTitle="Произошла ошибка при загрузке данных пользователя"/>;
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return <Navigate to="/login" />;
|
||||
return <Navigate to="/login"/>;
|
||||
}
|
||||
|
||||
if (!user.role || user.role.title !== "Администратор") {
|
||||
return <Navigate to="/" />;
|
||||
return <Navigate to="/"/>;
|
||||
}
|
||||
|
||||
return <Outlet />;
|
||||
return <Outlet/>;
|
||||
};
|
||||
|
||||
export default AdminRoute;
|
||||
@ -1,4 +1,4 @@
|
||||
import {Alert, Layout, Menu} from "antd";
|
||||
import {Alert, Layout, Menu, Result} from "antd";
|
||||
import {Outlet} from "react-router-dom";
|
||||
import {
|
||||
HomeOutlined,
|
||||
@ -42,7 +42,7 @@ const MainLayout = () => {
|
||||
);
|
||||
|
||||
if (mainLayoutData.isUserError) {
|
||||
return <Alert message="Произошла ошибка" type="error" showIcon/>
|
||||
return <Result status="500" title="500" subTitle="Произошла ошибка при загрузке данных"/>
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -1,14 +1,93 @@
|
||||
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
||||
import {Typography} from "antd";
|
||||
import useAdminPage from "./useAdminPage.js";
|
||||
import {useState} from "react";
|
||||
import {Table, Typography, Button, Modal, Form, Input, Select, Alert, Result} from "antd";
|
||||
import {ControlOutlined} from "@ant-design/icons";
|
||||
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
||||
import useAdminPage from "./useAdminPage.js";
|
||||
import useAdminPageUI from "./useAdminPageUI.js";
|
||||
import CreateUserModalForm from "./Components/CreateUserModalForm/CreateUserModalForm.jsx";
|
||||
|
||||
const {Title} = Typography;
|
||||
const {Option} = Select;
|
||||
|
||||
const AdminPage = () => {
|
||||
const adminPageData = useAdminPage();
|
||||
const adminPageUI = useAdminPageUI();
|
||||
const [errorMessage, setErrorMessage] = useState(null);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "ID",
|
||||
dataIndex: "id",
|
||||
key: "id",
|
||||
},
|
||||
{
|
||||
title: "Фамилия",
|
||||
dataIndex: "last_name",
|
||||
key: "lastName",
|
||||
sorter: (a, b) => a.last_name.localeCompare(b.last_name),
|
||||
},
|
||||
{
|
||||
title: "Имя",
|
||||
dataIndex: "first_name",
|
||||
key: "firstName",
|
||||
sorter: (a, b) => a.first_name.localeCompare(b.first_name),
|
||||
},
|
||||
{
|
||||
title: "Отчество",
|
||||
dataIndex: "patronymic",
|
||||
key: "patronymic",
|
||||
},
|
||||
{
|
||||
title: "Роль",
|
||||
dataIndex: ["role", "title"],
|
||||
key: "role",
|
||||
filters: adminPageData.roles.map(role => ({text: role.title, value: role.title})),
|
||||
onFilter: (value, record) => record.role.title === value,
|
||||
},
|
||||
{
|
||||
title: "Действия",
|
||||
key: "actions",
|
||||
render: (_, record) => (
|
||||
<Button type="link" onClick={() => adminPageUI.openEditModal(record)}>
|
||||
Редактировать
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const handleEditSubmit = async (values) => {
|
||||
try {
|
||||
await adminPageData.updateUser({
|
||||
id: adminPageUI.selectedUser.id,
|
||||
fullName: values.fullName,
|
||||
password: values.password || undefined, // Отправляем пароль только если он указан
|
||||
role: {title: values.role},
|
||||
});
|
||||
adminPageUI.closeEditModal();
|
||||
setErrorMessage(null);
|
||||
} catch (error) {
|
||||
setErrorMessage("Ошибка при обновлении пользователя");
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreateSubmit = async (values) => {
|
||||
try {
|
||||
await adminPageData.createUser({
|
||||
fullName: values.fullName,
|
||||
email: values.email,
|
||||
password: values.password,
|
||||
role: {title: values.role},
|
||||
});
|
||||
adminPageUI.closeCreateModal();
|
||||
setErrorMessage(null);
|
||||
} catch (error) {
|
||||
setErrorMessage("Ошибка при создании пользователя");
|
||||
}
|
||||
};
|
||||
|
||||
if (adminPageData.isError) {
|
||||
return <Result status="500" title="500" subTitle="Произошла ошибка при загрузке данных"/>
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={adminPageUI.containerStyle}>
|
||||
@ -16,13 +95,29 @@ const AdminPage = () => {
|
||||
<LoadingIndicator/>
|
||||
) : (
|
||||
<>
|
||||
<Typography.Title level={1}>
|
||||
<Title level={1}>
|
||||
<ControlOutlined/> Панель администратора
|
||||
</Typography.Title>
|
||||
</Title>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={adminPageUI.openCreateModal}
|
||||
style={{marginBottom: 16}}
|
||||
>
|
||||
Создать пользователя
|
||||
</Button>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={adminPageData.users}
|
||||
rowKey="id"
|
||||
pagination={{pageSize: 10}}
|
||||
loading={adminPageData.isLoading}
|
||||
/>
|
||||
|
||||
<CreateUserModalForm/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export default AdminPage;
|
||||
@ -0,0 +1,82 @@
|
||||
import {Button, Form, Input, Modal, Select, Tooltip, Typography} from "antd";
|
||||
import useCreateUserModalForm from "./useCreateUserModalForm.js";
|
||||
import useCreateUserModalFormUI from "./useCreateUserModalFormUI.js";
|
||||
import {InfoCircleOutlined} from "@ant-design/icons";
|
||||
|
||||
|
||||
const CreateUserModalForm = () => {
|
||||
const createUserModalFormData = useCreateUserModalForm();
|
||||
const createUserModalFormUI = useCreateUserModalFormUI(createUserModalFormData.registerUser);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Создать пользователя"
|
||||
open={createUserModalFormUI.modalVisible}
|
||||
onCancel={createUserModalFormUI.handleCancel}
|
||||
footer={null}
|
||||
>
|
||||
<Form
|
||||
form={createUserModalFormUI.form}
|
||||
onFinish={createUserModalFormUI.handleFinish}
|
||||
layout="vertical"
|
||||
>
|
||||
<Form.Item label="Фамилия" name="last_name" rules={[{required: true, message: "Введите фамилию"}]}>
|
||||
<Input/>
|
||||
</Form.Item>
|
||||
<Form.Item label="Имя" name="first_name" rules={[{required: true, message: "Введите имя"}]}>
|
||||
<Input/>
|
||||
</Form.Item>
|
||||
<Form.Item label="Отчество" name="patronymic">
|
||||
<Input/>
|
||||
</Form.Item>
|
||||
<Form.Item label="Логин" name="login" rules={[{required: true, message: "Введите логин"}]}>
|
||||
<Input/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="role_id"
|
||||
label="Роль"
|
||||
rules={[{required: true, message: "Выберите роль"}]}
|
||||
>
|
||||
<Select>
|
||||
{createUserModalFormData.roles.map((role) => (
|
||||
<Select.Option key={role.id} value={role.id}>
|
||||
{role.title}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Tooltip
|
||||
title="Пароль должен содержать не менее 8 символов, включая хотя бы одну букву и одну цифру и один специальный символ"
|
||||
>
|
||||
<Typography.Title level={3} style={{width: 30}}>
|
||||
<InfoCircleOutlined/>
|
||||
</Typography.Title>
|
||||
</Tooltip>
|
||||
<Form.Item label="Пароль" name="password" rules={[{required: true, message: "Введите пароль"}]}>
|
||||
<Input.Password/>
|
||||
</Form.Item>
|
||||
<Form.Item label="Подтвердите пароль" name="confirm_password"
|
||||
rules={[{required: true, message: "Подтвердите пароль"}, ({getFieldValue}) => ({
|
||||
validator(_, value) {
|
||||
if (!value || getFieldValue("password") === value) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject(new Error("Пароли не совпадают"));
|
||||
},
|
||||
}),]}>
|
||||
<Input.Password/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit" loading={createUserModalFormData.isLoading}>
|
||||
Создать
|
||||
</Button>
|
||||
<Button onClick={createUserModalFormUI.handleCancel} style={{marginLeft: 8}}>
|
||||
Отмена
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
};
|
||||
|
||||
export default CreateUserModalForm;
|
||||
@ -0,0 +1,24 @@
|
||||
import {useGetRolesQuery} from "../../../../../Api/rolesApi.js";
|
||||
import {useRegisterMutation} from "../../../../../Api/registerApi.js";
|
||||
|
||||
|
||||
const useCreateUserModalForm = () => {
|
||||
const {
|
||||
data: roles = [],
|
||||
isLoading: isLoadingRoles,
|
||||
isError: isErrorRoles,
|
||||
} = useGetRolesQuery(undefined, {
|
||||
pollingInterval: 60000,
|
||||
});
|
||||
|
||||
const [registerUser] = useRegisterMutation();
|
||||
|
||||
return {
|
||||
roles,
|
||||
isLoadingRoles,
|
||||
isErrorRoles,
|
||||
registerUser,
|
||||
};
|
||||
};
|
||||
|
||||
export default useCreateUserModalForm;
|
||||
@ -0,0 +1,47 @@
|
||||
import {useDispatch, useSelector} from "react-redux";
|
||||
import {closeModal} from "../../../../../Redux/Slices/adminSlice.js";
|
||||
import {Form, notification} from "antd";
|
||||
|
||||
const useCreateUserModalFormUI = (registerUser) => {
|
||||
const dispatch = useDispatch();
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const {
|
||||
modalVisible,
|
||||
} = useSelector(state => state.adminUI);
|
||||
|
||||
const handleCancel = () => {
|
||||
dispatch(closeModal());
|
||||
};
|
||||
|
||||
const handleFinish = async () => {
|
||||
const values = form.getFieldsValue();
|
||||
|
||||
try {
|
||||
console.log(values);
|
||||
await registerUser(values).unwrap();
|
||||
notification.success({
|
||||
message: "Пользователь зарегистрирован",
|
||||
description: "Пользователь успешно зарегистрирован",
|
||||
placement: "topRight",
|
||||
});
|
||||
form.resetFields();
|
||||
handleCancel();
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: "Ошибка регистрации пользователя",
|
||||
description: error?.data?.detail || "Не удалось зарегистрировать пользователя",
|
||||
placement: "topRight",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
form,
|
||||
modalVisible,
|
||||
handleCancel,
|
||||
handleFinish,
|
||||
};
|
||||
};
|
||||
|
||||
export default useCreateUserModalFormUI;
|
||||
@ -1,20 +1,28 @@
|
||||
import {useGetAllUsersQuery} from "../../../Api/usersApi.js";
|
||||
|
||||
import {useGetRolesQuery} from "../../../Api/rolesApi.js";
|
||||
|
||||
const useAdminPage = () => {
|
||||
|
||||
const {
|
||||
data: users = [],
|
||||
isLoading,
|
||||
isError,
|
||||
data: users = [], isLoading, isError,
|
||||
} = useGetAllUsersQuery(undefined, {
|
||||
pollingInterval: 10000,
|
||||
});
|
||||
|
||||
const {data: roles = [], isLoading: isLoadingRoles, isError: isErrorRoles} = useGetRolesQuery(undefined, {
|
||||
pollingInterval: 60000,
|
||||
});
|
||||
|
||||
// const [updateUser, { isLoading: isUpdating, isError: isUpdateError }] = useUpdateUserMutation();
|
||||
// const [createUser, { isLoading: isCreating, isError: isCreateError }] = useCreateUserMutation();
|
||||
|
||||
return {
|
||||
users,
|
||||
isLoading,
|
||||
isError,
|
||||
roles,
|
||||
isLoading: isLoading || isLoadingRoles,
|
||||
isError: isError || isErrorRoles,
|
||||
updateUser: () => {
|
||||
}, isUpdating: false, isUpdateError: false, createUser: () => {
|
||||
}, isCreating: false, isCreateError: false,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -1,15 +1,57 @@
|
||||
import {Grid} from "antd";
|
||||
|
||||
import {useState} from "react";
|
||||
import {Grid, Form} from "antd";
|
||||
import {useDispatch} from "react-redux";
|
||||
import {openModal} from "../../../Redux/Slices/adminSlice.js";
|
||||
|
||||
const {useBreakpoint} = Grid;
|
||||
|
||||
const useAdminPageUI = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const screens = useBreakpoint();
|
||||
const [editModalVisible, setEditModalVisible] = useState(false);
|
||||
const [createModalVisible, setCreateModalVisible] = useState(false);
|
||||
const [selectedUser, setSelectedUser] = useState(null);
|
||||
const [editForm] = Form.useForm();
|
||||
const [createForm] = Form.useForm();
|
||||
|
||||
const containerStyle = {padding: screens.xs ? 16 : 24};
|
||||
|
||||
const openEditModal = (user) => {
|
||||
setSelectedUser(user);
|
||||
editForm.setFieldsValue({
|
||||
fullName: user.fullName,
|
||||
role: user.role?.title || "",
|
||||
});
|
||||
setEditModalVisible(true);
|
||||
};
|
||||
|
||||
const closeEditModal = () => {
|
||||
setEditModalVisible(false);
|
||||
setSelectedUser(null);
|
||||
editForm.resetFields();
|
||||
};
|
||||
|
||||
const openCreateModal = () => {
|
||||
dispatch(openModal());
|
||||
};
|
||||
|
||||
const closeCreateModal = () => {
|
||||
setCreateModalVisible(false);
|
||||
createForm.resetFields();
|
||||
};
|
||||
|
||||
return {
|
||||
containerStyle,
|
||||
editModalVisible,
|
||||
createModalVisible,
|
||||
selectedUser,
|
||||
editForm,
|
||||
createForm,
|
||||
openEditModal,
|
||||
closeEditModal,
|
||||
openCreateModal,
|
||||
closeCreateModal,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -18,7 +18,6 @@ const useCalendarCellUI = () => {
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
// Styles
|
||||
const containerStyle = {
|
||||
height: "100%",
|
||||
cursor: isCompressed ? "pointer" : "default",
|
||||
@ -61,14 +60,12 @@ const useCalendarCellUI = () => {
|
||||
color: "#1890ff",
|
||||
};
|
||||
|
||||
// Static configuration
|
||||
const labels = {
|
||||
pastAppointment: "Прошедший прием",
|
||||
scheduledAppointment: "Запланированный прием",
|
||||
notSpecified: "Не указан",
|
||||
};
|
||||
|
||||
// Formatting functions
|
||||
const getAppointmentTime = (datetime) => {
|
||||
return datetime ? dayjs(datetime).format("HH:mm") : labels.notSpecified;
|
||||
};
|
||||
|
||||
@ -70,10 +70,9 @@ const useLensIssueFormUI = (visible, onCancel, onSubmit, patients, lenses) => {
|
||||
setSelectedLens(null);
|
||||
setIssueDate(dayjs(new Date()));
|
||||
} catch (errorInfo) {
|
||||
console.error("Validation Failed:", errorInfo);
|
||||
notification.error({
|
||||
message: "Ошибка валидации",
|
||||
description: "Проверьте правильность заполнения полей.",
|
||||
description: errorInfo?.data?.detail || "Проверьте правильность заполнения полей.",
|
||||
placement: "topRight",
|
||||
});
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ const useIssues = () => {
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: "Ошибка выдачи линзы",
|
||||
description: error.data?.message || "Не удалось выдать линзу пациенту.",
|
||||
description: error?.data?.detail || "Не удалось выдать линзу пациенту.",
|
||||
placement: "topRight",
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import {useEffect} from "react";
|
||||
import {Form} from "antd";
|
||||
import {Form, notification} from "antd";
|
||||
|
||||
|
||||
const useLensFormUI = (lensTypes, visible, onCancel, onSubmit, lens) => {
|
||||
@ -19,7 +19,7 @@ const useLensFormUI = (lensTypes, visible, onCancel, onSubmit, lens) => {
|
||||
const modalStyle = {
|
||||
marginTop: 20,
|
||||
};
|
||||
const formItemStyle = { width: "100%" };
|
||||
const formItemStyle = {width: "100%"};
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
@ -27,6 +27,11 @@ const useLensFormUI = (lensTypes, visible, onCancel, onSubmit, lens) => {
|
||||
onSubmit(values);
|
||||
form.resetFields();
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: "Ошибка",
|
||||
description: error?.data?.detail || lens ? "Не удалось обновить линзу" : "Не удалось создать линзу",
|
||||
placement: "topRight",
|
||||
});
|
||||
console.log("Validation Failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
@ -35,7 +35,7 @@ const useLenses = () => {
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: "Ошибка удаления",
|
||||
description: error.data?.message || "Не удалось удалить линзу",
|
||||
description: error?.data?.detail || "Не удалось удалить линзу",
|
||||
placement: "topRight",
|
||||
});
|
||||
}
|
||||
@ -63,7 +63,7 @@ const useLenses = () => {
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: "Ошибка",
|
||||
description: error.data?.message || "Произошла ошибка при сохранении",
|
||||
description: error?.data?.detail || "Произошла ошибка при сохранении",
|
||||
placement: "topRight",
|
||||
});
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ const useLoginPage = () => {
|
||||
localStorage.setItem("access_token", token);
|
||||
dispatch(setUser({ token }));
|
||||
} catch (error) {
|
||||
const errorMessage = error?.data?.message || "Не удалось войти";
|
||||
const errorMessage = error?.data?.detail || "Не удалось войти";
|
||||
dispatch(setError(errorMessage));
|
||||
notification.error({
|
||||
message: "Ошибка при входе",
|
||||
|
||||
@ -22,7 +22,7 @@ const usePatients = () => {
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: "Ошибка удаления",
|
||||
description: error.data?.message || "Не удалось удалить пациента",
|
||||
description: error?.data?.detail || "Не удалось удалить пациента",
|
||||
placement: "topRight",
|
||||
});
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ const useProfilePage = () => {
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: "Ошибка",
|
||||
description: error?.data?.message || "Не удалось обновить профиль.",
|
||||
description: error?.data?.detail || "Не удалось обновить профиль.",
|
||||
placement: "topRight",
|
||||
});
|
||||
}
|
||||
@ -72,7 +72,7 @@ const useProfilePage = () => {
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: "Ошибка",
|
||||
description: error?.data?.message || "Не удалось изменить пароль.",
|
||||
description: error?.data?.detail || "Не удалось изменить пароль.",
|
||||
placement: "topRight",
|
||||
});
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ const useScheduledAppointmentsViewModalUI = (cancelAppointment) => {
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: "Ошибка",
|
||||
description: error.data?.message || "Не удалось отменить прием.",
|
||||
description: error?.data?.detail || "Не удалось отменить прием.",
|
||||
placement: "topRight",
|
||||
});
|
||||
}
|
||||
|
||||
30
web-app/src/Redux/Slices/adminSlice.js
Normal file
30
web-app/src/Redux/Slices/adminSlice.js
Normal file
@ -0,0 +1,30 @@
|
||||
import {createSlice} from '@reduxjs/toolkit';
|
||||
|
||||
const initialState = {
|
||||
modalVisible: false,
|
||||
selectedUser: null,
|
||||
};
|
||||
|
||||
const adminSlice = createSlice({
|
||||
name: 'adminUI',
|
||||
initialState,
|
||||
reducers: {
|
||||
setSelectedUser(state, action) {
|
||||
state.selectedUser = action.payload;
|
||||
},
|
||||
openModal(state) {
|
||||
state.modalVisible = true;
|
||||
},
|
||||
closeModal(state) {
|
||||
state.modalVisible = false;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
openModal,
|
||||
closeModal,
|
||||
setSelectedUser,
|
||||
} = adminSlice.actions;
|
||||
|
||||
export default adminSlice.reducer;
|
||||
@ -17,6 +17,9 @@ import {usersApi} from "../Api/usersApi.js";
|
||||
import usersReducer from "./Slices/usersSlice.js";
|
||||
import {authApi} from "../Api/authApi.js";
|
||||
import authReducer from "./Slices/authSlice.js";
|
||||
import {rolesApi} from "../Api/rolesApi.js";
|
||||
import adminReducer from "./Slices/adminSlice.js";
|
||||
import {registerApi} from "../Api/registerApi.js";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@ -48,6 +51,12 @@ export const store = configureStore({
|
||||
|
||||
auth: authReducer,
|
||||
[authApi.reducerPath]: authApi.reducer,
|
||||
|
||||
adminUI: adminReducer,
|
||||
|
||||
[rolesApi.reducerPath]: rolesApi.reducer,
|
||||
|
||||
[registerApi.reducerPath]: registerApi.reducer
|
||||
},
|
||||
middleware: (getDefaultMiddleware) => (
|
||||
getDefaultMiddleware().concat(
|
||||
@ -62,6 +71,8 @@ export const store = configureStore({
|
||||
appointmentTypesApi.middleware,
|
||||
usersApi.middleware,
|
||||
authApi.middleware,
|
||||
rolesApi.middleware,
|
||||
registerApi.middleware,
|
||||
)
|
||||
),
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user