From b8b57e451b2276ff6bbd25db566d0c3ca3bae783 Mon Sep 17 00:00:00 2001 From: andrei Date: Mon, 2 Jun 2025 21:48:28 +0500 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD-=D0=BF?= =?UTF-8?q?=D0=B0=D0=BD=D0=B5=D0=BB=D1=8C=20=D0=B8=20API=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлены компоненты для админ-панели и API для управления пользователями. --- web-app/index.html | 2 +- web-app/src/Api/usersApi.js | 6 ++++ web-app/src/App/AdminRoute.jsx | 26 +++++++++++++++-- web-app/src/App/AppRouter.jsx | 1 + .../Components/Pages/AdminPage/AdminPage.jsx | 28 +++++++++++++++++++ .../Pages/AdminPage/useAdminPage.js | 21 ++++++++++++++ .../Pages/AdminPage/useAdminPageUI.js | 16 +++++++++++ .../Components/Pages/HomePage/HomePage.jsx | 1 - .../Pages/HomePage/useHomePageUI.js | 2 +- .../Pages/ProfilePage/ProfilePage.jsx | 5 +++- 10 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 web-app/src/Components/Pages/AdminPage/useAdminPage.js create mode 100644 web-app/src/Components/Pages/AdminPage/useAdminPageUI.js diff --git a/web-app/index.html b/web-app/index.html index fa92d9c..cf3092e 100644 --- a/web-app/index.html +++ b/web-app/index.html @@ -3,7 +3,7 @@ - Линза ➕ + Visus ➕ diff --git a/web-app/src/Api/usersApi.js b/web-app/src/Api/usersApi.js index 51d249d..6ddb0b4 100644 --- a/web-app/src/Api/usersApi.js +++ b/web-app/src/Api/usersApi.js @@ -7,6 +7,11 @@ export const usersApi = createApi({ baseQuery: baseQueryWithAuth, tagTypes: ['User'], endpoints: (builder) => ({ + getAllUsers: builder.query({ + query: () => '/users/', + providesTags: ['User'], + refetchOnMountOrArgChange: 5, + }), getAuthenticatedUserData: builder.query({ query: () => '/users/my-data/', providesTags: ['User'], @@ -34,4 +39,5 @@ export const { useGetAuthenticatedUserDataQuery, useChangePasswordMutation, useUpdateUserMutation, + useGetAllUsersQuery, } = usersApi; \ No newline at end of file diff --git a/web-app/src/App/AdminRoute.jsx b/web-app/src/App/AdminRoute.jsx index 5765f7d..a3d4214 100644 --- a/web-app/src/App/AdminRoute.jsx +++ b/web-app/src/App/AdminRoute.jsx @@ -1,10 +1,30 @@ import { Navigate, Outlet } from "react-router-dom"; -import { useSelector } from "react-redux"; +import {useGetAuthenticatedUserDataQuery} from "../Api/usersApi.js"; +import LoadingIndicator from "../Components/Widgets/LoadingIndicator/LoadingIndicator.jsx"; +import {Alert} from "antd"; const AdminRoute = () => { - const { user } = useSelector((state) => state.auth); + const { + data: user, + isLoading: isUserLoading, + isError: isUserError, + } = useGetAuthenticatedUserDataQuery(undefined, { + pollingInterval: 60000, + }); - if (!user || user.role.title !== "Администратор") { + if (isUserLoading) { + return ; + } + + if (isUserError) { + return ; + } + + if (!user) { + return ; + } + + if (!user.role || user.role.title !== "Администратор") { return ; } diff --git a/web-app/src/App/AppRouter.jsx b/web-app/src/App/AppRouter.jsx index 602b013..8bef81c 100644 --- a/web-app/src/App/AppRouter.jsx +++ b/web-app/src/App/AppRouter.jsx @@ -9,6 +9,7 @@ import IssuesPage from "../Components/Pages/IssuesPage/IssuesPage.jsx"; import AppointmentsPage from "../Components/Pages/AppointmentsPage/AppointmentsPage.jsx"; import ProfilePage from "../Components/Pages/ProfilePage/ProfilePage.jsx"; import AdminRoute from "./AdminRoute.jsx"; +import AdminPage from "../Components/Pages/AdminPage/AdminPage.jsx"; const AppRouter = () => ( diff --git a/web-app/src/Components/Pages/AdminPage/AdminPage.jsx b/web-app/src/Components/Pages/AdminPage/AdminPage.jsx index e69de29..0c7c9da 100644 --- a/web-app/src/Components/Pages/AdminPage/AdminPage.jsx +++ b/web-app/src/Components/Pages/AdminPage/AdminPage.jsx @@ -0,0 +1,28 @@ +import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx"; +import {Typography} from "antd"; +import useAdminPage from "./useAdminPage.js"; +import {ControlOutlined} from "@ant-design/icons"; +import useAdminPageUI from "./useAdminPageUI.js"; + + +const AdminPage = () => { + const adminPageData = useAdminPage(); + const adminPageUI = useAdminPageUI(); + + + return ( +
+ {adminPageData.isLoading ? ( + + ) : ( + <> + + Панель администратора + + + )} +
+ ) +}; + +export default AdminPage; \ No newline at end of file diff --git a/web-app/src/Components/Pages/AdminPage/useAdminPage.js b/web-app/src/Components/Pages/AdminPage/useAdminPage.js new file mode 100644 index 0000000..91e9b81 --- /dev/null +++ b/web-app/src/Components/Pages/AdminPage/useAdminPage.js @@ -0,0 +1,21 @@ +import {useGetAllUsersQuery} from "../../../Api/usersApi.js"; + + +const useAdminPage = () => { + + const { + data: users = [], + isLoading, + isError, + } = useGetAllUsersQuery(undefined, { + pollingInterval: 10000, + }); + + return { + users, + isLoading, + isError, + }; +}; + +export default useAdminPage; \ No newline at end of file diff --git a/web-app/src/Components/Pages/AdminPage/useAdminPageUI.js b/web-app/src/Components/Pages/AdminPage/useAdminPageUI.js new file mode 100644 index 0000000..20870b0 --- /dev/null +++ b/web-app/src/Components/Pages/AdminPage/useAdminPageUI.js @@ -0,0 +1,16 @@ +import {Grid} from "antd"; + + +const {useBreakpoint} = Grid; + +const useAdminPageUI = () => { + const screens = useBreakpoint(); + + const containerStyle = {padding: screens.xs ? 16 : 24}; + + return { + containerStyle, + }; +}; + +export default useAdminPageUI; \ No newline at end of file diff --git a/web-app/src/Components/Pages/HomePage/HomePage.jsx b/web-app/src/Components/Pages/HomePage/HomePage.jsx index 84818d3..3cc0b40 100644 --- a/web-app/src/Components/Pages/HomePage/HomePage.jsx +++ b/web-app/src/Components/Pages/HomePage/HomePage.jsx @@ -32,7 +32,6 @@ ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend) const HomePage = () => { const homePageData = useHomePage(); const homePageUI = useHomePageUI(homePageData.appointments, homePageData.scheduledAppointments, homePageData.patients); - // const selectedScheduledAppointment = useSelector((state) => state.appointmentsUI.selectedScheduledAppointment); if (homePageData.isError) { return ( diff --git a/web-app/src/Components/Pages/HomePage/useHomePageUI.js b/web-app/src/Components/Pages/HomePage/useHomePageUI.js index 1e50cc5..1369638 100644 --- a/web-app/src/Components/Pages/HomePage/useHomePageUI.js +++ b/web-app/src/Components/Pages/HomePage/useHomePageUI.js @@ -4,7 +4,7 @@ import dayjs from "dayjs"; import isBetween from "dayjs/plugin/isBetween"; import {useSelector} from "react-redux"; // Import isBetween plugin -dayjs.extend(isBetween); // Extend dayjs with isBetween +dayjs.extend(isBetween); const { useBreakpoint } = Grid; diff --git a/web-app/src/Components/Pages/ProfilePage/ProfilePage.jsx b/web-app/src/Components/Pages/ProfilePage/ProfilePage.jsx index 0abce05..8e0d127 100644 --- a/web-app/src/Components/Pages/ProfilePage/ProfilePage.jsx +++ b/web-app/src/Components/Pages/ProfilePage/ProfilePage.jsx @@ -1,5 +1,5 @@ import {Button, Card, Col, Form, Input, Modal, Row, Space, Typography, Result} from "antd"; -import {EditOutlined} from "@ant-design/icons"; +import {EditOutlined, UserOutlined} from "@ant-design/icons"; import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx"; import useProfilePage from "./useProfilePage.js"; import useProfilePageUI from "./useProfilePageUI.js"; @@ -44,6 +44,9 @@ const ProfilePage = () => { ) : ( <> + + Главная страница + Профиль