diff --git a/web-app/src/Api/appointmentsApi.js b/web-app/src/Api/appointmentsApi.js
index e2db163..a813205 100644
--- a/web-app/src/Api/appointmentsApi.js
+++ b/web-app/src/Api/appointmentsApi.js
@@ -7,7 +7,7 @@ export const appointmentsApi = createApi({
tagTypes: ['Appointment'],
endpoints: (builder) => ({
getAppointments: builder.query({
- query: () => '/appointments/',
+ query: (doctor_id) => `/appointments/doctor/${doctor_id}/`,
providesTags: ['Appointment'],
refetchOnMountOrArgChange: 5,
}),
diff --git a/web-app/src/Api/scheduledAppointmentsApi.js b/web-app/src/Api/scheduledAppointmentsApi.js
index c4b232c..1a2eedf 100644
--- a/web-app/src/Api/scheduledAppointmentsApi.js
+++ b/web-app/src/Api/scheduledAppointmentsApi.js
@@ -7,7 +7,7 @@ export const scheduledAppointmentsApi = createApi({
tagTypes: ['ScheduledAppointment'],
endpoints: (builder) => ({
getScheduledAppointments: builder.query({
- query: () => `/scheduled_appointments/`,
+ query: (doctor_id) => `/scheduled_appointments/doctor/${doctor_id}/`,
providesTags: ['ScheduledAppointment'],
}),
createScheduledAppointment: builder.mutation({
diff --git a/web-app/src/Api/usersApi.js b/web-app/src/Api/usersApi.js
index 6ddb0b4..583bc44 100644
--- a/web-app/src/Api/usersApi.js
+++ b/web-app/src/Api/usersApi.js
@@ -19,7 +19,7 @@ export const usersApi = createApi({
}),
changePassword: builder.mutation({
query: (data) => ({
- url: "/users/change-password",
+ url: "/users/change-password/",
method: "POST",
body: data,
}),
diff --git a/web-app/src/App/PrivateRoute.jsx b/web-app/src/App/PrivateRoute.jsx
index e0a2f51..5b255ba 100644
--- a/web-app/src/App/PrivateRoute.jsx
+++ b/web-app/src/App/PrivateRoute.jsx
@@ -1,14 +1,19 @@
-import {Navigate, Outlet} from "react-router-dom";
-import {useSelector} from "react-redux";
+import { Navigate, Outlet } from "react-router-dom";
+import { useSelector } from "react-redux";
+import LoadingIndicator from "../Components/Widgets/LoadingIndicator/LoadingIndicator.jsx";
const PrivateRoute = () => {
- const {user} = useSelector((state) => state.auth);
+ const { user, userData, isLoading } = useSelector((state) => state.auth);
- if (!user) {
- return ;
+ if (isLoading) {
+ return ;
}
- return ;
+ if (!user || !userData) {
+ return ;
+ }
+
+ return ;
};
export default PrivateRoute;
\ No newline at end of file
diff --git a/web-app/src/Components/Dummies/AppointmentFormModal/useAppointmentFormModalUI.js b/web-app/src/Components/Dummies/AppointmentFormModal/useAppointmentFormModalUI.js
index 5e3fe5d..f4e1859 100644
--- a/web-app/src/Components/Dummies/AppointmentFormModal/useAppointmentFormModalUI.js
+++ b/web-app/src/Components/Dummies/AppointmentFormModal/useAppointmentFormModalUI.js
@@ -9,7 +9,12 @@ import { Grid } from "antd";
const { useBreakpoint } = Grid;
const useAppointmentFormModalUI = (createAppointment, patients, cancelAppointment, useGetByPatientIdQuery) => {
- const dispatch = useDispatch();
+ const dispatch = useDispatch()
+
+ const {
+ userData
+ } = useSelector((state) => state.auth);
+
const { modalVisible, scheduledData } = useSelector((state) => state.appointmentsUI);
const [form] = Form.useForm();
const screens = useBreakpoint();
@@ -24,7 +29,7 @@ const useAppointmentFormModalUI = (createAppointment, patients, cancelAppointmen
const [searchPreviousAppointments, setSearchPreviousAppointments] = useState("");
const editor = useRef(null);
- const { data: appointments = [] } = useGetAppointmentsQuery(undefined, {
+ const { data: appointments = [] } = useGetAppointmentsQuery((userData.id), {
pollingInterval: 20000,
});
diff --git a/web-app/src/Components/Dummies/UpdateUserModalForm/UpdateUserModalForm.jsx b/web-app/src/Components/Dummies/UpdateUserModalForm/UpdateUserModalForm.jsx
new file mode 100644
index 0000000..f366d66
--- /dev/null
+++ b/web-app/src/Components/Dummies/UpdateUserModalForm/UpdateUserModalForm.jsx
@@ -0,0 +1,96 @@
+import {Button, Form, Input, Modal, Select, Space, Typography} from "antd";
+import useUpdateUserModalFormUI from "./useUpdateUserModalFormUI.js";
+import useUpdateUserModalForm from "./useUpdateUserModalForm.js";
+
+
+const UpdateUserModalForm = () => {
+ const editProfileModalData = useUpdateUserModalForm();
+ const editProfileModalUI = useUpdateUserModalFormUI(editProfileModalData.updateUser, editProfileModalData.updatePassword);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ {editProfileModalUI.isCurrentUser && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ({
+ validator(_, value) {
+ if (value && value !== getFieldValue("new_password")) {
+ return Promise.reject("Пароли не совпадают");
+ }
+ return Promise.resolve();
+ },
+ }),
+ ]}>
+
+
+
+
+
+
+
+
+
+
+ )
+};
+
+export default UpdateUserModalForm;
\ No newline at end of file
diff --git a/web-app/src/Components/Dummies/UpdateUserModalForm/useUpdateUserModalForm.js b/web-app/src/Components/Dummies/UpdateUserModalForm/useUpdateUserModalForm.js
new file mode 100644
index 0000000..3196bb9
--- /dev/null
+++ b/web-app/src/Components/Dummies/UpdateUserModalForm/useUpdateUserModalForm.js
@@ -0,0 +1,28 @@
+import {useChangePasswordMutation, useUpdateUserMutation} from "../../../Api/usersApi.js";
+import {useGetRolesQuery} from "../../../Api/rolesApi.js";
+
+
+const useUpdateUserModalForm = () => {
+ const {
+ data: roles = [],
+ isLoading: isLoadingRoles,
+ isError: isErrorRoles,
+ } = useGetRolesQuery(undefined, {
+ pollingInterval: 60000,
+ });
+
+ const [updateUser, {isLoading: isUserUpdating}] = useUpdateUserMutation();
+ const [updatePassword, {isLoading: isPasswordUpdating}] = useChangePasswordMutation();
+
+ return {
+ roles,
+ isLoadingRoles,
+ isErrorRoles,
+ updateUser,
+ updatePassword,
+ isUserUpdating,
+ isPasswordUpdating,
+ };
+};
+
+export default useUpdateUserModalForm;
\ No newline at end of file
diff --git a/web-app/src/Components/Dummies/UpdateUserModalForm/useUpdateUserModalFormUI.js b/web-app/src/Components/Dummies/UpdateUserModalForm/useUpdateUserModalFormUI.js
new file mode 100644
index 0000000..1b63d9f
--- /dev/null
+++ b/web-app/src/Components/Dummies/UpdateUserModalForm/useUpdateUserModalFormUI.js
@@ -0,0 +1,89 @@
+import {useDispatch, useSelector} from "react-redux";
+import {setSelectedUser} from "../../../Redux/Slices/usersSlice.js";
+import {Form, notification} from "antd";
+import {useEffect} from "react";
+
+
+const useUpdateUserModalFormUI = (updateUser, updatePassword) => {
+ const dispatch = useDispatch();
+ const [userForm] = Form.useForm();
+ const [passwordForm] = Form.useForm();
+
+ const {
+ selectedUser,
+ isCurrentUser,
+ } = useSelector((state) => state.usersUI);
+
+ useEffect(() => {
+ if (selectedUser) {
+ userForm.setFieldsValue(selectedUser);
+ }
+ }, [selectedUser, userForm]);
+
+ const isModalOpen = selectedUser !== null;
+
+ const handleCancel = () => {
+ dispatch(setSelectedUser(null));
+ };
+
+ const handleUserSubmit = async () => {
+ const values = userForm.getFieldsValue();
+
+ try {
+ await updateUser({userId: selectedUser.id, ...values}).unwrap();
+
+ notification.success({
+ message: "Успех",
+ description: "Профиль успешно обновлен.",
+ placement: "topRight",
+ });
+ userForm.resetFields();
+ dispatch(setSelectedUser(null));
+ } catch (error) {
+ notification.error({
+ message: "Ошибка",
+ description: error?.data?.detail || "Не удалось обновить профиль.",
+ placement: "topRight",
+ });
+ }
+ };
+
+ const handlePasswordSubmit = async () => {
+ const values = passwordForm.getFieldsValue();
+
+ try {
+ await updatePassword({user_id: selectedUser.id, ...values}).unwrap();
+
+ notification.success({
+ message: "Успех",
+ description: "Пароль успешно обновлен.",
+ placement: "topRight",
+ });
+ passwordForm.resetFields();
+ dispatch(setSelectedUser(null));
+ } catch (error) {
+ notification.error({
+ message: "Ошибка",
+ description: error?.data?.detail || "Не удалось обновить пароль.",
+ placement: "topRight",
+ });
+ }
+ };
+
+ const resetForms = () => {
+ passwordForm.resetFields();
+ };
+
+ return {
+ isModalOpen,
+ userForm,
+ passwordForm,
+ isCurrentUser,
+ handleCancel,
+ handleUserSubmit,
+ handlePasswordSubmit,
+ resetForms,
+ };
+};
+
+export default useUpdateUserModalFormUI;
\ No newline at end of file
diff --git a/web-app/src/Components/Layouts/useMainLayout.js b/web-app/src/Components/Layouts/useMainLayout.js
index 2a3b287..553d823 100644
--- a/web-app/src/Components/Layouts/useMainLayout.js
+++ b/web-app/src/Components/Layouts/useMainLayout.js
@@ -1,14 +1,7 @@
-import {useGetAuthenticatedUserDataQuery} from "../../Api/usersApi.js";
+import { useSelector } from "react-redux";
const useMainLayout = () => {
-
- const {
- data: user,
- isLoading: isUserLoading,
- isError: isUserError,
- } = useGetAuthenticatedUserDataQuery(undefined, {
- pollingInterval: 20000,
- });
+ const { userData: user, isLoading: isUserLoading, error: isUserError } = useSelector((state) => state.auth);
return {
user,
diff --git a/web-app/src/Components/Pages/AdminPage/AdminPage.jsx b/web-app/src/Components/Pages/AdminPage/AdminPage.jsx
index 504e807..48d3c33 100644
--- a/web-app/src/Components/Pages/AdminPage/AdminPage.jsx
+++ b/web-app/src/Components/Pages/AdminPage/AdminPage.jsx
@@ -1,18 +1,15 @@
-import {useState} from "react";
-import {Table, Typography, Button, Modal, Form, Input, Select, Alert, Result} from "antd";
+import {Table, Button, Result, Typography} 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";
+import UpdateUserModalForm from "../../Dummies/UpdateUserModalForm/UpdateUserModalForm.jsx";
-const {Title} = Typography;
-const {Option} = Select;
const AdminPage = () => {
const adminPageData = useAdminPage();
const adminPageUI = useAdminPageUI();
- const [errorMessage, setErrorMessage] = useState(null);
const columns = [
{
@@ -55,35 +52,6 @@ const AdminPage = () => {
},
];
- 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
@@ -95,9 +63,9 @@ const AdminPage = () => {
) : (
<>
-
+
Панель администратора
-
+