From 0a148421206eedea9da06b9279ea7065fce03f52 Mon Sep 17 00:00:00 2001 From: andrei Date: Tue, 13 May 2025 14:14:51 +0500 Subject: [PATCH] =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B0=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20gitea?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/database/migrations/env.py | 2 - api/app/domain/entities/register.py | 2 +- api/app/domain/models/roles.py | 2 +- api/app/infrastructure/users_service.py | 13 +- web-app/src/Api/appointmentsApi.js | 27 +++ web-app/src/Api/scheduledAppointmentsApi.js | 25 +++ web-app/src/App/App.jsx | 9 +- web-app/src/App/AppRouter.jsx | 12 +- .../src/{Components => App}/PrivateRoute.jsx | 0 .../src/Components/Dummies/LensListCard.jsx | 2 +- .../Components/Layouts/AppointmentsLayout.jsx | 166 ------------------ .../Pages/AppointmentsCalendarPage.jsx | 80 --------- .../AppointmentsPage/AppointmentsPage.jsx | 76 ++++++++ .../AppointmentsCalendarTab.jsx | 40 +++++ .../useAppointmentCalendarUI.js | 61 +++++++ .../AppointmentsTableTab.jsx} | 8 +- .../Pages/AppointmentsPage/useAppointments.js | 29 +++ .../AppointmentsPage/useAppointmentsUI.js | 68 +++++++ .../LensIssueFormModal/LensIssueFormModal.jsx | 10 +- ...sIssueFormModal.js => useLensIssueForm.js} | 4 +- ...ueFormModalUI.js => useLensIssueFormUI.js} | 4 +- .../LensFormModal/LensFormModal.jsx | 10 +- .../Components/LensFormModal/useLensForm.js} | 6 +- .../LensFormModal/useLensFormUI.js} | 4 +- .../LensViewModal/LensViewModal.jsx | 2 +- .../Components/LensesTab/LensesTab.jsx} | 10 +- .../Components/LensesTab}/useLenses.js | 4 +- .../Components/LensesTab}/useLensesUI.js | 4 +- .../Components/SetFormModal/SetFormModal.jsx | 10 +- .../Components/SetFormModal/useSetForm.js} | 8 +- .../Components/SetFormModal/useSetFormUI.js} | 4 +- .../Components/SetsTab/SetsTab.jsx} | 8 +- .../Components/SetsTab}/useSets.js | 6 +- .../Components/SetsTab}/useSetsUI.js | 2 +- .../LensesSetsPage/LensesSetsPage.jsx} | 12 +- .../Pages/{ => LoginPage}/LoginPage.jsx | 2 +- .../PatientFormModal/PatientFormModal.jsx | 4 +- ...ientFormModalUI.js => usePatientFormUI.js} | 4 +- .../src/Components/Widgets/CalendarCell.jsx | 12 +- web-app/src/Redux/Slices/appointmentsSlice.js | 57 ++++++ web-app/src/Redux/store.js | 8 +- .../appointments/getAllAppointments.js | 8 - .../src/old_api/lens_issues/addLensIssue.js | 8 - .../old_api/lens_issues/getAllLensIssues.js | 8 - .../src/old_api/lens_types/getAllLensTypes.js | 8 - .../src/old_api/lenses/getNotIssuedLenses.js | 8 - .../src/old_api/patients/getAllPatients.js | 8 - .../getAllScheduledAppointments.js | 8 - .../set_content/getSetContentBySetId.js | 8 - 49 files changed, 483 insertions(+), 398 deletions(-) create mode 100644 web-app/src/Api/appointmentsApi.js create mode 100644 web-app/src/Api/scheduledAppointmentsApi.js rename web-app/src/{Components => App}/PrivateRoute.jsx (100%) delete mode 100644 web-app/src/Components/Layouts/AppointmentsLayout.jsx delete mode 100644 web-app/src/Components/Pages/AppointmentsCalendarPage.jsx create mode 100644 web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx create mode 100644 web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx create mode 100644 web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/useAppointmentCalendarUI.js rename web-app/src/Components/Pages/{AppointmentsTablePage.jsx => AppointmentsPage/Components/AppointmentTableTab/AppointmentsTableTab.jsx} (66%) create mode 100644 web-app/src/Components/Pages/AppointmentsPage/useAppointments.js create mode 100644 web-app/src/Components/Pages/AppointmentsPage/useAppointmentsUI.js rename web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/{useLensIssueFormModal.js => useLensIssueForm.js} (88%) rename web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/{useLensIssueFormModalUI.js => useLensIssueFormUI.js} (98%) rename web-app/src/Components/Pages/{LensesPage => LensesSetsPage/Components/LensesTab}/Components/LensFormModal/LensFormModal.jsx (95%) rename web-app/src/Components/Pages/{LensesPage/Components/LensFormModal/useLensFormModal.js => LensesSetsPage/Components/LensesTab/Components/LensFormModal/useLensForm.js} (50%) rename web-app/src/Components/Pages/{LensesPage/Components/LensFormModal/useLensFormModalUI.js => LensesSetsPage/Components/LensesTab/Components/LensFormModal/useLensFormUI.js} (89%) rename web-app/src/Components/Pages/{LensesPage => LensesSetsPage/Components/LensesTab}/Components/LensViewModal/LensViewModal.jsx (97%) rename web-app/src/Components/Pages/{LensesPage/LensesPage.jsx => LensesSetsPage/Components/LensesTab/LensesTab.jsx} (98%) rename web-app/src/Components/Pages/{LensesPage => LensesSetsPage/Components/LensesTab}/useLenses.js (95%) rename web-app/src/Components/Pages/{LensesPage => LensesSetsPage/Components/LensesTab}/useLensesUI.js (96%) rename web-app/src/Components/Pages/{SetsPage => LensesSetsPage/Components/SetsTab}/Components/SetFormModal/SetFormModal.jsx (94%) rename web-app/src/Components/Pages/{SetsPage/Components/SetFormModal/useSetFormModal.js => LensesSetsPage/Components/SetsTab/Components/SetFormModal/useSetForm.js} (72%) rename web-app/src/Components/Pages/{SetsPage/Components/SetFormModal/useSetFormModalUI.js => LensesSetsPage/Components/SetsTab/Components/SetFormModal/useSetFormUI.js} (96%) rename web-app/src/Components/Pages/{SetsPage/SetsPage.jsx => LensesSetsPage/Components/SetsTab/SetsTab.jsx} (93%) rename web-app/src/Components/Pages/{SetsPage => LensesSetsPage/Components/SetsTab}/useSets.js (96%) rename web-app/src/Components/Pages/{SetsPage => LensesSetsPage/Components/SetsTab}/useSetsUI.js (97%) rename web-app/src/Components/{Layouts/LensesLayout.jsx => Pages/LensesSetsPage/LensesSetsPage.jsx} (64%) rename web-app/src/Components/Pages/{ => LoginPage}/LoginPage.jsx (97%) rename web-app/src/Components/Pages/PatientsPage/Components/PatientFormModal/{usePatientFormModalUI.js => usePatientFormUI.js} (94%) create mode 100644 web-app/src/Redux/Slices/appointmentsSlice.js delete mode 100644 web-app/src/old_api/appointments/getAllAppointments.js delete mode 100644 web-app/src/old_api/lens_issues/addLensIssue.js delete mode 100644 web-app/src/old_api/lens_issues/getAllLensIssues.js delete mode 100644 web-app/src/old_api/lens_types/getAllLensTypes.js delete mode 100644 web-app/src/old_api/lenses/getNotIssuedLenses.js delete mode 100644 web-app/src/old_api/patients/getAllPatients.js delete mode 100644 web-app/src/old_api/scheduled_appointments/getAllScheduledAppointments.js delete mode 100644 web-app/src/old_api/set_content/getSetContentBySetId.js diff --git a/api/app/database/migrations/env.py b/api/app/database/migrations/env.py index 48f397e..65b324d 100644 --- a/api/app/database/migrations/env.py +++ b/api/app/database/migrations/env.py @@ -1,4 +1,3 @@ - from logging.config import fileConfig from alembic import context @@ -22,7 +21,6 @@ def get_url(): async def run_migrations_online(): connectable = create_async_engine(get_url(), poolclass=pool.NullPool, future=True) - async with connectable.connect() as connection: await connection.run_sync(do_run_migrations) diff --git a/api/app/domain/entities/register.py b/api/app/domain/entities/register.py index e44bc47..d982841 100644 --- a/api/app/domain/entities/register.py +++ b/api/app/domain/entities/register.py @@ -6,7 +6,7 @@ from pydantic import BaseModel class RegisterEntity(BaseModel): first_name: str last_name: str - patronymic: Optional[str] + patronymic: Optional[str] = None role_id: int login: str password: str diff --git a/api/app/domain/models/roles.py b/api/app/domain/models/roles.py index 98bcf91..5506610 100644 --- a/api/app/domain/models/roles.py +++ b/api/app/domain/models/roles.py @@ -1,4 +1,4 @@ -from sqlalchemy import Column, Integer, VARCHAR +from sqlalchemy import Column, VARCHAR from sqlalchemy.orm import relationship from app.domain.models.base import BaseModel diff --git a/api/app/infrastructure/users_service.py b/api/app/infrastructure/users_service.py index ab7b20c..3003c3d 100644 --- a/api/app/infrastructure/users_service.py +++ b/api/app/infrastructure/users_service.py @@ -1,4 +1,5 @@ import re +from typing import Optional from fastapi import HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession @@ -12,18 +13,18 @@ from app.domain.models import User class UsersService: def __init__(self, db: AsyncSession): - self.user_repository = UsersRepository(db) - self.role_repository = RolesRepository(db) + self.users_repository = UsersRepository(db) + self.roles_repository = RolesRepository(db) - async def register_user(self, register_entity: RegisterEntity) -> UserEntity: - role = await self.role_repository.get_by_id(register_entity.role_id) + async def register_user(self, register_entity: RegisterEntity) -> Optional[UserEntity]: + role = await self.roles_repository.get_by_id(register_entity.role_id) if not role: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='The role with this ID was not found' ) - user = await self.user_repository.get_by_login(register_entity.login) + user = await self.users_repository.get_by_login(register_entity.login) if user: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -45,7 +46,7 @@ class UsersService: ) user_model.set_password(register_entity.password) - created_user = await self.user_repository.create(user_model) + created_user = await self.users_repository.create(user_model) return UserEntity( id=created_user.id, diff --git a/web-app/src/Api/appointmentsApi.js b/web-app/src/Api/appointmentsApi.js new file mode 100644 index 0000000..edce0e7 --- /dev/null +++ b/web-app/src/Api/appointmentsApi.js @@ -0,0 +1,27 @@ +import {createApi, fetchBaseQuery} from "@reduxjs/toolkit/query/react"; +import CONFIG from "../Core/сonfig.js"; + + +export const appointmentsApi = createApi({ + reducerPath: 'appointmentsApi', + baseQuery: fetchBaseQuery({ + baseUrl: CONFIG.BASE_URL, + prepareHeaders: (headers) => { + const token = localStorage.getItem('access_token'); + if (token) headers.set('Authorization', `Bearer ${token}`); + return headers; + } + }), + tagTypes: ['Appointment'], + endpoints: (builder) => ({ + getAppointments: builder.query({ + query: () => '/appointments/', + providesTags: ['Appointment'], + refetchOnMountOrArgChange: 5 + }), + }), +}); + +export const { + useGetAppointmentsQuery, +} = appointmentsApi; \ No newline at end of file diff --git a/web-app/src/Api/scheduledAppointmentsApi.js b/web-app/src/Api/scheduledAppointmentsApi.js new file mode 100644 index 0000000..ea301f7 --- /dev/null +++ b/web-app/src/Api/scheduledAppointmentsApi.js @@ -0,0 +1,25 @@ +import {createApi, fetchBaseQuery} from "@reduxjs/toolkit/query/react"; +import CONFIG from "../Core/сonfig.js"; + + +export const scheduledAppointmentsApi = createApi({ + reducerPath: 'scheduledAppointmentsApi', + baseQuery: fetchBaseQuery({ + baseUrl: CONFIG.BASE_URL, + prepareHeaders: (headers) => { + const token = localStorage.getItem('access_token'); + if (token) headers.set('Authorization', `Bearer ${token}`); + return headers; + } + }), + tagTypes: ['ScheduledAppointment'], + endpoints: (builder) => ({ + getScheduledAppointments: builder.query({ + query: () => `/scheduledAppointments`, + }), + }), +}); + +export const { + useGetScheduledAppointmentsQuery, +} = scheduledAppointmentsApi; \ No newline at end of file diff --git a/web-app/src/App/App.jsx b/web-app/src/App/App.jsx index 5227a34..67d3d75 100644 --- a/web-app/src/App/App.jsx +++ b/web-app/src/App/App.jsx @@ -4,12 +4,19 @@ import {AuthProvider} from "../Hooks/AuthContext.jsx"; import "/src/Styles/app.css"; import {Provider} from "react-redux"; import store from "../Redux/store.js"; +import dayjs from "dayjs"; +import locale from 'antd/locale/ru_RU'; +import {ConfigProvider} from "antd"; + +dayjs.locale('ru'); const App = () => ( - + + + diff --git a/web-app/src/App/AppRouter.jsx b/web-app/src/App/AppRouter.jsx index 27b9365..85721ba 100644 --- a/web-app/src/App/AppRouter.jsx +++ b/web-app/src/App/AppRouter.jsx @@ -1,12 +1,12 @@ import {Routes, Route, Navigate} from "react-router-dom"; -import PrivateRoute from "../Components/PrivateRoute.jsx"; -import LoginPage from "../Components/Pages/LoginPage.jsx"; +import PrivateRoute from "./PrivateRoute.jsx"; +import LoginPage from "../Components/Pages/LoginPage/LoginPage.jsx"; import MainLayout from "../Components/Layouts/MainLayout.jsx"; import PatientsPage from "../Components/Pages/PatientsPage/PatientsPage.jsx"; import HomePage from "../Components/Pages/HomePage.jsx"; -import LensesLayout from "../Components/Layouts/LensesLayout.jsx"; +import LensesSetsPage from "../Components/Pages/LensesSetsPage/LensesSetsPage.jsx"; import IssuesPage from "../Components/Pages/IssuesPage/IssuesPage.jsx"; -import AppointmentsLayout from "../Components/Layouts/AppointmentsLayout.jsx"; +import AppointmentsPage from "../Components/Pages/AppointmentsPage/AppointmentsPage.jsx"; const AppRouter = () => ( @@ -16,9 +16,9 @@ const AppRouter = () => ( }> }> }/> - }/> + }/> }/> - }/> + }/> }/> diff --git a/web-app/src/Components/PrivateRoute.jsx b/web-app/src/App/PrivateRoute.jsx similarity index 100% rename from web-app/src/Components/PrivateRoute.jsx rename to web-app/src/App/PrivateRoute.jsx diff --git a/web-app/src/Components/Dummies/LensListCard.jsx b/web-app/src/Components/Dummies/LensListCard.jsx index 1965745..ff8dea8 100644 --- a/web-app/src/Components/Dummies/LensListCard.jsx +++ b/web-app/src/Components/Dummies/LensListCard.jsx @@ -2,7 +2,7 @@ import {Card, Popconfirm, Tooltip} from "antd"; import PropTypes from "prop-types"; import {DeleteOutlined, EditOutlined, EyeOutlined} from "@ant-design/icons"; import {useState} from "react"; -import LensViewModal from "../Pages/LensesPage/Components/LensViewModal/LensViewModal.jsx"; +import LensViewModal from "../Pages/LensesSetsPage/Components/LensesTab/Components/LensViewModal/LensViewModal.jsx"; import {LensPropType} from "../../Types/lensPropType.js"; const LensListCard = ({lens, handleEditLens, handleDeleteLens}) => { diff --git a/web-app/src/Components/Layouts/AppointmentsLayout.jsx b/web-app/src/Components/Layouts/AppointmentsLayout.jsx deleted file mode 100644 index 4eb6230..0000000 --- a/web-app/src/Components/Layouts/AppointmentsLayout.jsx +++ /dev/null @@ -1,166 +0,0 @@ -import {useEffect, useState} from "react"; -import {Button, Grid, Tabs, Typography} from "antd"; -import {Splitter} from "antd"; -import { - CalendarOutlined, TableOutlined, MenuFoldOutlined, MenuUnfoldOutlined, -} from "@ant-design/icons"; -import AppointmentsCalendarPage from "../Pages/AppointmentsCalendarPage.jsx"; -import AppointmentsTablePage from "../Pages/AppointmentsTablePage.jsx"; -import getAllAppointments from "../../old_api/appointments/getAllAppointments.js"; -import getAllScheduledAppointments from "../../old_api/scheduled_appointments/getAllScheduledAppointments.js"; -import {useAuth} from "../../Hooks/AuthContext.jsx"; -import LoadingIndicator from "../Widgets/LoadingIndicator.jsx"; -import {cacheInfo, getCachedInfo, getCacheTimestamp} from "../../Utils/cachedInfoUtils.js"; - -const {useBreakpoint} = Grid; - -const AppointmentsLayout = () => { - const [collapsed, setCollapsed] = useState(true); - const [siderWidth, setSiderWidth] = useState(250); - const [hovered, setHovered] = useState(false); - - const screens = useBreakpoint(); - const {api} = useAuth(); - - const [loading, setLoading] = useState(true); - - const [appointments, setAppointments] = useState([]); - const [scheduledAppointments, setScheduledAppointments] = useState([]); - - const toggleSider = () => setCollapsed(!collapsed); - - useEffect(() => { - loadDataWithCache(); - }, []); - - useEffect(() => { - const interval = setInterval(loadData, 5000); - return () => clearInterval(interval); - }, []); - - const loadData = async () => { - await fetchAppointments(); - await fetchScheduledAppointments(); - setLoading(false); - }; - - const loadDataWithCache = async () => { - await fetchAppointmentsWithCache(); - await fetchScheduledAppointmentsWithCache(); - }; - - const fetchAppointmentsWithCache = async () => { - const cachedData = getCachedInfo("appointmentsData"); - const cacheTimestamp = getCacheTimestamp("appointmentsData"); - - if (cachedData && cacheTimestamp && (Date.now() - cacheTimestamp) < 60 * 1000) { - setAppointments(cachedData); - return; - } - - await fetchAppointments(); - }; - - const fetchAppointments = async () => { - const data = await getAllAppointments(api); - setAppointments(data); - cacheInfo("appointmentsData", data); - }; - - const fetchScheduledAppointmentsWithCache = async () => { - const cachedData = getCachedInfo("scheduledAppointmentsData"); - const cacheTimestamp = getCacheTimestamp("scheduledAppointmentsData"); - - if (cachedData && cacheTimestamp && (Date.now() - cacheTimestamp) < 60 * 1000) { - setScheduledAppointments(cachedData); - return; - } - - await fetchScheduledAppointments(); - }; - - const fetchScheduledAppointments = async () => { - const data = await getAllScheduledAppointments(api); - setScheduledAppointments(data); - cacheInfo("scheduledAppointmentsData", data); - }; - - const items = [{ - key: "1", - label: "Календарь приемов", - children: , - icon: , - }, { - key: "2", - label: "Таблица приемов", - children: , - icon: , - },]; - - if (loading) { - return () - } - - return ( - <> - - - - - - {!collapsed && !screens.xs && ( - - - Предстоящие события - -

Здесь будут предстоящие приемы...

-
- )} -
-
setHovered(true)} - onMouseLeave={() => setHovered(false)} - > - -
- - ); -}; - -export default AppointmentsLayout; \ No newline at end of file diff --git a/web-app/src/Components/Pages/AppointmentsCalendarPage.jsx b/web-app/src/Components/Pages/AppointmentsCalendarPage.jsx deleted file mode 100644 index 54d935f..0000000 --- a/web-app/src/Components/Pages/AppointmentsCalendarPage.jsx +++ /dev/null @@ -1,80 +0,0 @@ -import {Calendar, Grid, ConfigProvider, Badge, Modal, Tag, Tooltip} from "antd"; -import {useState} from "react"; -import dayjs from "dayjs"; -import 'dayjs/locale/ru'; -import locale from 'antd/es/locale/ru_RU'; -import updateLocale from 'dayjs/plugin/updateLocale'; -import PropTypes, {arrayOf} from "prop-types"; -import CalendarCell from "../Widgets/CalendarCell.jsx"; -import {AppointmentPropType} from "../../Types/appointmentPropType.js"; -import {ScheduledAppointmentPropType} from "../../Types/scheduledAppointmentPropType.js"; - -const {useBreakpoint} = Grid; - -dayjs.extend(updateLocale); -dayjs.updateLocale('ru', { - weekStart: 1 -}); - -const AppointmentsCalendarPage = ({appointments, scheduledAppointments}) => { - const screens = useBreakpoint(); - const [selectedDate, setSelectedDate] = useState(dayjs(new Date())); - const [modalVisible, setModalVisible] = useState(false); - const [selectedAppointments, setSelectedAppointments] = useState([]); - const [selectedAppointment, setSelectedAppointment] = useState(null); - - const dateCellRender = (value) => { - const date = value.format('YYYY-MM-DD'); - const appointmentsForDate = appointments.filter(app => - dayjs(app.appointment_datetime).format('YYYY-MM-DD') === date - ); - const scheduledForDate = scheduledAppointments.filter(app => - dayjs(app.scheduled_datetime).format('YYYY-MM-DD') === date - ); - - return ( - { - }} - onItemClick={() => { - }} - /> - ); - }; - - const onSelect = (date) => { - setSelectedDate(date); - const selectedDateStr = date.format('YYYY-MM-DD'); - const appointmentsForDate = appointments.filter(app => - dayjs(app.appointment_datetime).format('YYYY-MM-DD') === selectedDateStr - ); - const scheduledForDate = scheduledAppointments.filter(app => - dayjs(app.scheduled_datetime).format('YYYY-MM-DD') === selectedDateStr - ); - setSelectedAppointments([...appointmentsForDate, ...scheduledForDate]); - setModalVisible(true); - }; - - return ( - -
- - -
-
- ); -}; - -AppointmentsCalendarPage.propTypes = { - appointments: PropTypes.arrayOf(AppointmentPropType).isRequired, - scheduledAppointments: PropTypes.arrayOf(ScheduledAppointmentPropType).isRequired, -}; - -export default AppointmentsCalendarPage; \ No newline at end of file diff --git a/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx b/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx new file mode 100644 index 0000000..e9b922f --- /dev/null +++ b/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx @@ -0,0 +1,76 @@ +import {Button, Tabs, Typography} from "antd"; +import {Splitter} from "antd"; +import { + CalendarOutlined, TableOutlined, MenuFoldOutlined, MenuUnfoldOutlined, +} from "@ant-design/icons"; +import AppointmentsCalendarTab from "./Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx"; +import AppointmentsTableTab from "./Components/AppointmentTableTab/AppointmentsTableTab.jsx"; +import useAppointmentsUI from "./useAppointmentsUI.js"; + + +const AppointmentsPage = () => { + const appointmentsPageUI = useAppointmentsUI(); + + const items = [{ + key: "1", + label: "Календарь приемов", + children: , + icon: , + }, { + key: "2", + label: "Таблица приемов", + children: , + icon: , + },]; + + return ( + <> + + + + + + {appointmentsPageUI.showSplitterPanel && ( + + + Предстоящие события + +

Здесь будут предстоящие приемы...

+
+ )} +
+
+ +
+ + ); +}; + +export default AppointmentsPage; \ No newline at end of file diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx new file mode 100644 index 0000000..bf40a19 --- /dev/null +++ b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx @@ -0,0 +1,40 @@ +import {Calendar} from "antd"; +import 'dayjs/locale/ru'; +import CalendarCell from "../../../../Widgets/CalendarCell.jsx"; +import useAppointments from "../../useAppointments.js"; +import useAppointmentCalendarUI from "./useAppointmentCalendarUI.js"; + + +const AppointmentsCalendarTab = () => { + const appointmentsData = useAppointments(); + const appointmentsCalendarUI = useAppointmentCalendarUI(appointmentsData.appointments, appointmentsData.scheduledAppointments); + + const dateCellRender = (value) => { + const appointmentsForDate = appointmentsCalendarUI.getAppointmentsByListAndDate(appointmentsData.appointments, value); + const scheduledForDate = appointmentsCalendarUI.getAppointmentsByListAndDate(appointmentsData.scheduledAppointments, value); + + return ( + { + }} + onItemClick={() => { + }} + /> + ); + }; + + return ( +
+ +
+ ); +}; + +export default AppointmentsCalendarTab; \ No newline at end of file diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/useAppointmentCalendarUI.js b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/useAppointmentCalendarUI.js new file mode 100644 index 0000000..f7edd9c --- /dev/null +++ b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/useAppointmentCalendarUI.js @@ -0,0 +1,61 @@ +import {useDispatch, useSelector} from "react-redux"; +import dayjs from "dayjs"; +import { + openModal, + setSelectedAppointments, + setSelectedDate +} from "../../../../../Redux/Slices/appointmentsSlice.js"; +import {Grid} from "antd"; + +const {useBreakpoint} = Grid; + +const useAppointmentCalendarUI = (appointments, scheduledAppointments) => { + const dispatch = useDispatch(); + const { + modalVisible, + selectedAppointments, + selectedAppointment, + } = useSelector(state => state.appointmentsUI); + const selectedDate = dayjs(useSelector(state => state.appointmentsUI.selectedDate)); + + + const screens = useBreakpoint(); + const fullScreenCalendar = !screens.xs; + + const calendarContainerStyle = {padding: 20}; + + const onSelect = (date) => { + const selectedDateStr = date.format('YYYY-MM-DD'); + dispatch(setSelectedDate(selectedDateStr)); + + console.log(appointments) + const appointmentsForDate = appointments.filter(app => + dayjs(app.appointment_datetime).format('YYYY-MM-DD') === selectedDateStr + ); + console.log(appointmentsForDate) + + const scheduledForDate = scheduledAppointments.filter(app => + dayjs(app.scheduled_datetime).format('YYYY-MM-DD') === selectedDateStr + ); + + dispatch(setSelectedAppointments([...appointmentsForDate, ...scheduledForDate])); + dispatch(openModal()); + }; + + const getAppointmentsByListAndDate = (list, value) => { + const date = value.format('YYYY-MM-DD'); + return list.filter(app => + dayjs(app.appointment_datetime).format('YYYY-MM-DD') === date + ); + } + + return { + selectedDate, + fullScreenCalendar, + calendarContainerStyle, + onSelect, + getAppointmentsByListAndDate, + }; +}; + +export default useAppointmentCalendarUI; \ No newline at end of file diff --git a/web-app/src/Components/Pages/AppointmentsTablePage.jsx b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentTableTab/AppointmentsTableTab.jsx similarity index 66% rename from web-app/src/Components/Pages/AppointmentsTablePage.jsx rename to web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentTableTab/AppointmentsTableTab.jsx index 1a5a908..5f3ae27 100644 --- a/web-app/src/Components/Pages/AppointmentsTablePage.jsx +++ b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentTableTab/AppointmentsTableTab.jsx @@ -1,10 +1,8 @@ -import {useAuth} from "../../Hooks/AuthContext.jsx"; +import {useAuth} from "../../../../../Hooks/AuthContext.jsx"; import {useEffect, useState} from "react"; -import getAllAppointments from "../../old_api/appointments/getAllAppointments.js"; -import {notification} from "antd"; -const AppointmentsTablePage = () => { +const AppointmentsTableTab = () => { const {api} = useAuth(); const [appointments, setAppointments] = useState([]); @@ -23,4 +21,4 @@ const AppointmentsTablePage = () => { ); }; -export default AppointmentsTablePage; \ No newline at end of file +export default AppointmentsTableTab; \ No newline at end of file diff --git a/web-app/src/Components/Pages/AppointmentsPage/useAppointments.js b/web-app/src/Components/Pages/AppointmentsPage/useAppointments.js new file mode 100644 index 0000000..a0723a5 --- /dev/null +++ b/web-app/src/Components/Pages/AppointmentsPage/useAppointments.js @@ -0,0 +1,29 @@ +import {useGetAppointmentsQuery} from "../../../Api/appointmentsApi.js"; + + +const useAppointments = () => { + const { + data: appointments = [], + isLoadingAppointments, + isErrorAppointments, + } = useGetAppointmentsQuery(undefined, { + pollingInterval: 20000, + }); + + const { + data: scheduledAppointments = [], + isLoadingScheduledAppointments, + isErrorScheduledAppointments, + } = useGetAppointmentsQuery(undefined, { + pollingInterval: 20000, + }); + + return { + appointments, + scheduledAppointments, + isLoading: isLoadingAppointments || isLoadingScheduledAppointments, + isError: isErrorAppointments || isErrorScheduledAppointments, + }; +}; + +export default useAppointments; \ No newline at end of file diff --git a/web-app/src/Components/Pages/AppointmentsPage/useAppointmentsUI.js b/web-app/src/Components/Pages/AppointmentsPage/useAppointmentsUI.js new file mode 100644 index 0000000..662b85c --- /dev/null +++ b/web-app/src/Components/Pages/AppointmentsPage/useAppointmentsUI.js @@ -0,0 +1,68 @@ +import {useDispatch, useSelector} from "react-redux"; +import {Grid} from "antd"; +import {setHovered, toggleSider} from "../../../Redux/Slices/appointmentsSlice.js"; +import {useEffect, useMemo} from "react"; + +const {useBreakpoint} = Grid; + +const useAppointmentsUI = () => { + const dispatch = useDispatch(); + const { + collapsed, + siderWidth, + hovered, + } = useSelector(state => state.appointmentsUI); + const screens = useBreakpoint(); + + useEffect(() => { + document.title = "Приемы"; + }, []); + + const splitterStyle = {flex: 1}; + const splitterContentPanelStyle = {padding: 16}; + const splitterSiderPanelStyle = {padding: "16px", borderLeft: "1px solid #ddd", overflowY: "auto"}; + const siderTitleStyle = {marginBottom: 36}; + const siderButtonContainerStyle = { + position: "fixed", + right: 0, + top: "50%", + transform: "translateY(-50%)", + transition: "right 0.3s ease", + zIndex: 1000, + display: screens.xs ? "none" : "block", + }; + const siderButtonStyle = { + width: hovered ? 250 : 50, + padding: hovered ? "0 20px" : "0", + overflow: "hidden", + textAlign: "left", + transition: "width 0.3s ease, padding 0.3s ease", + borderRadius: "4px 0 0 4px", + }; + + const handleToggleSider = () => dispatch(toggleSider()); + const handleHoverSider = () => dispatch(setHovered(true)); + const handleLeaveSider = () => dispatch(setHovered(false)); + + const siderButtonText = useMemo(() => hovered ? (collapsed ? "Показать предстоящие события" : "Скрыть предстоящие события") : "", [collapsed, hovered]); + const showSplitterPanel = useMemo(() => !collapsed && !screens.xs, [collapsed, screens]); + + return { + collapsed, + siderWidth, + hovered, + showSplitterPanel, + siderButtonText, + splitterStyle, + splitterContentPanelStyle, + splitterSiderPanelStyle, + siderTitleStyle, + siderButtonContainerStyle, + siderButtonStyle, + handleToggleSider, + handleHoverSider, + handleLeaveSider, + }; +}; + +export default useAppointmentsUI; \ No newline at end of file diff --git a/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/LensIssueFormModal.jsx b/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/LensIssueFormModal.jsx index 9a7b3f7..f9734b7 100644 --- a/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/LensIssueFormModal.jsx +++ b/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/LensIssueFormModal.jsx @@ -2,13 +2,13 @@ import { Modal, Input, Button, Typography, Collapse, Steps, Row, Alert, Col, DatePicker, Spin } from "antd"; import PropTypes from "prop-types"; -import useLensIssueFormModal from "./useLensIssueFormModal.js"; -import useLensIssueFormModalUI from "./useLensIssueFormModalUI.js"; +import useLensIssueForm from "./useLensIssueForm.js"; +import useLensIssueFormUI from "./useLensIssueFormUI.js"; import {useMemo} from "react"; const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { - const lensIssueFormModalData = useLensIssueFormModal(); - const lensIssueFormModalUI = useLensIssueFormModalUI(visible, onCancel, onSubmit, lensIssueFormModalData.patients, lensIssueFormModalData.lenses); + const lensIssueFormModalData = useLensIssueForm(); + const lensIssueFormModalUI = useLensIssueFormUI(visible, onCancel, onSubmit, lensIssueFormModalData.patients, lensIssueFormModalData.lenses); const patientsItems = lensIssueFormModalUI.filteredPatients.map((patient) => ({ key: patient.id, @@ -182,7 +182,7 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { }, { title: 'Выбор линзы', content: SelectLensStep, }, { - title: 'Подтверждение', content: , + title: 'Подтверждение', content: ConfirmStep, }]; return ( diff --git a/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueFormModal.js b/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueForm.js similarity index 88% rename from web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueFormModal.js rename to web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueForm.js index 06cebc4..13eb194 100644 --- a/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueFormModal.js +++ b/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueForm.js @@ -2,7 +2,7 @@ import {useGetPatientsQuery} from "../../../../../Api/patientsApi.js"; import {useGetNotIssuedLensesQuery} from "../../../../../Api/lensesApi.js"; -const useLensIssueFormModal = () => { +const useLensIssueForm = () => { const {data: patients = [], isLoading: isLoadingPatients, isError: isErrorPatients} = useGetPatientsQuery(undefined); const {data: lenses = [], isLoading: isLoadingLenses, isError: isErrorLenses} = useGetNotIssuedLensesQuery(undefined); @@ -14,4 +14,4 @@ const useLensIssueFormModal = () => { }; }; -export default useLensIssueFormModal; \ No newline at end of file +export default useLensIssueForm; \ No newline at end of file diff --git a/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueFormModalUI.js b/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueFormUI.js similarity index 98% rename from web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueFormModalUI.js rename to web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueFormUI.js index 255112d..4474891 100644 --- a/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueFormModalUI.js +++ b/web-app/src/Components/Pages/IssuesPage/Components/LensIssueFormModal/useLensIssueFormUI.js @@ -4,7 +4,7 @@ import {Grid, notification} from "antd"; const {useBreakpoint} = Grid; -const useLensIssueFormModalUI = (visible, onCancel, onSubmit, patients, lenses) => { +const useLensIssueFormUI = (visible, onCancel, onSubmit, patients, lenses) => { const screens = useBreakpoint(); const [searchPatientString, setSearchPatientString] = useState(""); @@ -193,4 +193,4 @@ const useLensIssueFormModalUI = (visible, onCancel, onSubmit, patients, lenses) }; }; -export default useLensIssueFormModalUI; \ No newline at end of file +export default useLensIssueFormUI; \ No newline at end of file diff --git a/web-app/src/Components/Pages/LensesPage/Components/LensFormModal/LensFormModal.jsx b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensFormModal/LensFormModal.jsx similarity index 95% rename from web-app/src/Components/Pages/LensesPage/Components/LensFormModal/LensFormModal.jsx rename to web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensFormModal/LensFormModal.jsx index 993c616..c289d6f 100644 --- a/web-app/src/Components/Pages/LensesPage/Components/LensFormModal/LensFormModal.jsx +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensFormModal/LensFormModal.jsx @@ -1,13 +1,13 @@ import {Col, Form, InputNumber, Modal, Row, Select} from "antd"; import PropTypes from "prop-types"; -import {LensPropType} from "../../../../../Types/lensPropType.js"; -import useLensFormModal from "./useLensFormModal.js"; -import useLensFormModalUI from "./useLensFormModalUI.js"; +import {LensPropType} from "../../../../../../../Types/lensPropType.js"; +import useLensForm from "./useLensForm.js"; +import useLensFormUI from "./useLensFormUI.js"; const LensFormModal = ({visible, onCancel, onSubmit, lens}) => { - const lensFormData = useLensFormModal(); - const lensFormUI = useLensFormModalUI(lensFormData.lensTypes, visible, onCancel, onSubmit, lens); + const lensFormData = useLensForm(); + const lensFormUI = useLensFormUI(lensFormData.lensTypes, visible, onCancel, onSubmit, lens); return ( { +const useLensForm = () => { const {data: lensTypes = [], isLoading, isError} = useGetLensTypesQuery(undefined); return {lensTypes, isLoading, isError}; }; -export default useLensFormModal; \ No newline at end of file +export default useLensForm; \ No newline at end of file diff --git a/web-app/src/Components/Pages/LensesPage/Components/LensFormModal/useLensFormModalUI.js b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensFormModal/useLensFormUI.js similarity index 89% rename from web-app/src/Components/Pages/LensesPage/Components/LensFormModal/useLensFormModalUI.js rename to web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensFormModal/useLensFormUI.js index 6047b03..f547eea 100644 --- a/web-app/src/Components/Pages/LensesPage/Components/LensFormModal/useLensFormModalUI.js +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensFormModal/useLensFormUI.js @@ -2,7 +2,7 @@ import {useEffect} from "react"; import {Form} from "antd"; -const useLensFormModalUI = (lensTypes, visible, onCancel, onSubmit, lens) => { +const useLensFormUI = (lensTypes, visible, onCancel, onSubmit, lens) => { const [form] = Form.useForm(); useEffect(() => { @@ -45,4 +45,4 @@ const useLensFormModalUI = (lensTypes, visible, onCancel, onSubmit, lens) => { }; }; -export default useLensFormModalUI; \ No newline at end of file +export default useLensFormUI; \ No newline at end of file diff --git a/web-app/src/Components/Pages/LensesPage/Components/LensViewModal/LensViewModal.jsx b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensViewModal/LensViewModal.jsx similarity index 97% rename from web-app/src/Components/Pages/LensesPage/Components/LensViewModal/LensViewModal.jsx rename to web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensViewModal/LensViewModal.jsx index 022f138..2a45358 100644 --- a/web-app/src/Components/Pages/LensesPage/Components/LensViewModal/LensViewModal.jsx +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensViewModal/LensViewModal.jsx @@ -1,6 +1,6 @@ import {Button, Col, Modal, Row, Typography} from "antd"; import PropTypes from "prop-types"; -import {LensPropType} from "../../../../../Types/lensPropType.js"; +import {LensPropType} from "../../../../../../../Types/lensPropType.js"; const {Text, Title} = Typography; diff --git a/web-app/src/Components/Pages/LensesPage/LensesPage.jsx b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/LensesTab.jsx similarity index 98% rename from web-app/src/Components/Pages/LensesPage/LensesPage.jsx rename to web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/LensesTab.jsx index e24305e..35b80ce 100644 --- a/web-app/src/Components/Pages/LensesPage/LensesPage.jsx +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/LensesTab.jsx @@ -22,10 +22,10 @@ import { TableOutlined, BuildOutlined } from "@ant-design/icons"; -import LensCard from "../../Dummies/LensListCard.jsx"; +import LensCard from "../../../../Dummies/LensListCard.jsx"; import LensFormModal from "./Components/LensFormModal/LensFormModal.jsx"; -import SelectViewMode from "../../Widgets/SelectViewMode.jsx"; -import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx"; +import SelectViewMode from "../../../../Widgets/SelectViewMode.jsx"; +import LoadingIndicator from "../../../../Widgets/LoadingIndicator.jsx"; import useLenses from "./useLenses.js"; import useLensesUI from "./useLensesUI.js"; @@ -33,7 +33,7 @@ const {Option} = Select; const {useBreakpoint} = Grid; const {Title} = Typography; -const LensesPage = () => { +const LensesTab = () => { const lensesData = useLenses(); const lensesUI = useLensesUI(lensesData.lenses); @@ -332,4 +332,4 @@ const LensesPage = () => { ); }; -export default LensesPage; \ No newline at end of file +export default LensesTab; \ No newline at end of file diff --git a/web-app/src/Components/Pages/LensesPage/useLenses.js b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/useLenses.js similarity index 95% rename from web-app/src/Components/Pages/LensesPage/useLenses.js rename to web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/useLenses.js index bba24f6..a6097cd 100644 --- a/web-app/src/Components/Pages/LensesPage/useLenses.js +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/useLenses.js @@ -4,9 +4,9 @@ import { useDeleteLensMutation, useGetLensesQuery, useUpdateLensMutation -} from "../../../Api/lensesApi.js"; +} from "../../../../../Api/lensesApi.js"; import {notification} from "antd"; -import {closeModal} from "../../../Redux/Slices/lensesSlice.js"; +import {closeModal} from "../../../../../Redux/Slices/lensesSlice.js"; const useLenses = () => { diff --git a/web-app/src/Components/Pages/LensesPage/useLensesUI.js b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/useLensesUI.js similarity index 96% rename from web-app/src/Components/Pages/LensesPage/useLensesUI.js rename to web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/useLensesUI.js index 9c2ae1e..f9531c1 100644 --- a/web-app/src/Components/Pages/LensesPage/useLensesUI.js +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/useLensesUI.js @@ -1,5 +1,5 @@ import {useEffect, useMemo} from "react"; -import {getCachedInfo} from "../../../Utils/cachedInfoUtils.js"; +import {getCachedInfo} from "../../../../../Utils/cachedInfoUtils.js"; import { closeModal, openModal, @@ -7,7 +7,7 @@ import { setSearchParams, setSearchText, setShowAdvancedSearch, setViewMode -} from "../../../Redux/Slices/lensesSlice.js"; +} from "../../../../../Redux/Slices/lensesSlice.js"; import {useDispatch, useSelector} from "react-redux"; diff --git a/web-app/src/Components/Pages/SetsPage/Components/SetFormModal/SetFormModal.jsx b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/Components/SetFormModal/SetFormModal.jsx similarity index 94% rename from web-app/src/Components/Pages/SetsPage/Components/SetFormModal/SetFormModal.jsx rename to web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/Components/SetFormModal/SetFormModal.jsx index 85a6eb0..eadbdbb 100644 --- a/web-app/src/Components/Pages/SetsPage/Components/SetFormModal/SetFormModal.jsx +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/Components/SetFormModal/SetFormModal.jsx @@ -1,15 +1,15 @@ import {Modal, Button, Form, Input, Table, InputNumber, Select, Space, Result} from "antd"; import {PlusOutlined, DeleteOutlined} from "@ant-design/icons"; import PropTypes from "prop-types"; -import {SetPropType} from "../../../../../Types/setPropType.js"; -import useSetFormModal from "./useSetFormModal.js"; -import useSetFormModalUI from "./useSetFormModalUI.js"; +import {SetPropType} from "../../../../../../../Types/setPropType.js"; +import useSetForm from "./useSetForm.js"; +import useSetFormUI from "./useSetFormUI.js"; const {Option} = Select; const SetFormModal = ({visible, onCancel, setData, onSubmit}) => { - const setFormModalData = useSetFormModal(setData); - const setFormModalUI = useSetFormModalUI(visible, onCancel, setData, onSubmit, setFormModalData.setContents, setFormModalData.lensTypes); + const setFormModalData = useSetForm(setData); + const setFormModalUI = useSetFormUI(visible, onCancel, setData, onSubmit, setFormModalData.setContents, setFormModalData.lensTypes); const columns = [ { diff --git a/web-app/src/Components/Pages/SetsPage/Components/SetFormModal/useSetFormModal.js b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/Components/SetFormModal/useSetForm.js similarity index 72% rename from web-app/src/Components/Pages/SetsPage/Components/SetFormModal/useSetFormModal.js rename to web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/Components/SetFormModal/useSetForm.js index 5f490df..025a3a7 100644 --- a/web-app/src/Components/Pages/SetsPage/Components/SetFormModal/useSetFormModal.js +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/Components/SetFormModal/useSetForm.js @@ -1,8 +1,8 @@ -import {useGetLensTypesQuery} from "../../../../../Api/lensTypesApi.js"; -import {useGetSetContentQuery} from "../../../../../Api/setContentApi.js"; +import {useGetLensTypesQuery} from "../../../../../../../Api/lensTypesApi.js"; +import {useGetSetContentQuery} from "../../../../../../../Api/setContentApi.js"; -const useSetFormModal = (setData) => { +const useSetForm = (setData) => { const {data: lensTypes = [], isLoading: isLoadingLensTypes, isError: isErrorLensTypes} = useGetLensTypesQuery(undefined); @@ -24,4 +24,4 @@ const useSetFormModal = (setData) => { }; }; -export default useSetFormModal; \ No newline at end of file +export default useSetForm; \ No newline at end of file diff --git a/web-app/src/Components/Pages/SetsPage/Components/SetFormModal/useSetFormModalUI.js b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/Components/SetFormModal/useSetFormUI.js similarity index 96% rename from web-app/src/Components/Pages/SetsPage/Components/SetFormModal/useSetFormModalUI.js rename to web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/Components/SetFormModal/useSetFormUI.js index b79320d..d23a72f 100644 --- a/web-app/src/Components/Pages/SetsPage/Components/SetFormModal/useSetFormModalUI.js +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/Components/SetFormModal/useSetFormUI.js @@ -2,7 +2,7 @@ import {Form, notification} from "antd"; import {useEffect, useState} from "react"; -const useSetFormModalUI = (visible, onCancel, setData, onSubmit, content, lensTypes) => { +const useSetFormUI = (visible, onCancel, setData, onSubmit, content, lensTypes) => { const [form] = Form.useForm(); const [currentContent, setCurrentContent] = useState([]); @@ -112,4 +112,4 @@ const useSetFormModalUI = (visible, onCancel, setData, onSubmit, content, lensTy }; }; -export default useSetFormModalUI; \ No newline at end of file +export default useSetFormUI; \ No newline at end of file diff --git a/web-app/src/Components/Pages/SetsPage/SetsPage.jsx b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/SetsTab.jsx similarity index 93% rename from web-app/src/Components/Pages/SetsPage/SetsPage.jsx rename to web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/SetsTab.jsx index bd1129a..523211c 100644 --- a/web-app/src/Components/Pages/SetsPage/SetsPage.jsx +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/SetsTab.jsx @@ -1,15 +1,15 @@ import {FloatButton, Input, List, Result, Row, Typography} from "antd"; import {PlusOutlined, SwitcherOutlined} from "@ant-design/icons"; -import SetListCard from "../../Dummies/SetListCard.jsx"; +import SetListCard from "../../../../Dummies/SetListCard.jsx"; import SetFormModal from "./Components/SetFormModal/SetFormModal.jsx"; -import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx"; +import LoadingIndicator from "../../../../Widgets/LoadingIndicator.jsx"; import useSets from "./useSets.js"; import useSetsUI from "./useSetsUI.js"; const {Title} = Typography; -const SetsPage = () => { +const SetsTab = () => { const setsData = useSets(); const setsUI = useSetsUI(setsData.sets); @@ -79,4 +79,4 @@ const SetsPage = () => { ); }; -export default SetsPage; \ No newline at end of file +export default SetsTab; \ No newline at end of file diff --git a/web-app/src/Components/Pages/SetsPage/useSets.js b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/useSets.js similarity index 96% rename from web-app/src/Components/Pages/SetsPage/useSets.js rename to web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/useSets.js index d987d6b..2bdd3e1 100644 --- a/web-app/src/Components/Pages/SetsPage/useSets.js +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/useSets.js @@ -5,9 +5,9 @@ import { useDeleteSetMutation, useGetSetsQuery, useUpdateSetMutation -} from "../../../Api/setsApi.js"; -import {closeModal} from "../../../Redux/Slices/setsSlice.js"; -import {useAddSetContentMutation, useUpdateSetContentMutation} from "../../../Api/setContentApi.js"; +} from "../../../../../Api/setsApi.js"; +import {closeModal} from "../../../../../Redux/Slices/setsSlice.js"; +import {useAddSetContentMutation, useUpdateSetContentMutation} from "../../../../../Api/setContentApi.js"; const useSets = () => { diff --git a/web-app/src/Components/Pages/SetsPage/useSetsUI.js b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/useSetsUI.js similarity index 97% rename from web-app/src/Components/Pages/SetsPage/useSetsUI.js rename to web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/useSetsUI.js index 1ceab76..8171e60 100644 --- a/web-app/src/Components/Pages/SetsPage/useSetsUI.js +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/useSetsUI.js @@ -7,7 +7,7 @@ import { setCurrentPage, setPageSize, setSearchText -} from "../../../Redux/Slices/setsSlice.js"; +} from "../../../../../Redux/Slices/setsSlice.js"; const useSetsUI = (sets) => { diff --git a/web-app/src/Components/Layouts/LensesLayout.jsx b/web-app/src/Components/Pages/LensesSetsPage/LensesSetsPage.jsx similarity index 64% rename from web-app/src/Components/Layouts/LensesLayout.jsx rename to web-app/src/Components/Pages/LensesSetsPage/LensesSetsPage.jsx index 409106f..3dabc51 100644 --- a/web-app/src/Components/Layouts/LensesLayout.jsx +++ b/web-app/src/Components/Pages/LensesSetsPage/LensesSetsPage.jsx @@ -1,27 +1,27 @@ import { Tabs } from "antd"; -import LensesPage from "../Pages/LensesPage/LensesPage.jsx"; +import LensesTab from "./Components/LensesTab/LensesTab.jsx"; import {FolderViewOutlined, SwitcherOutlined} from "@ant-design/icons"; -import SetsPage from "../Pages/SetsPage/SetsPage.jsx"; +import SetsTab from "./Components/SetsTab/SetsTab.jsx"; const items = [ { key: '1', label: 'Линзы', - children: , + children: , icon: }, { key: '2', label: 'Наборы линз', - children: , + children: , icon: } ] -const LensesLayout = () => { +const LensesSetsPage = () => { return ( { ); }; -export default LensesLayout; \ No newline at end of file +export default LensesSetsPage; \ No newline at end of file diff --git a/web-app/src/Components/Pages/LoginPage.jsx b/web-app/src/Components/Pages/LoginPage/LoginPage.jsx similarity index 97% rename from web-app/src/Components/Pages/LoginPage.jsx rename to web-app/src/Components/Pages/LoginPage/LoginPage.jsx index 6e1cfbc..06ce407 100644 --- a/web-app/src/Components/Pages/LoginPage.jsx +++ b/web-app/src/Components/Pages/LoginPage/LoginPage.jsx @@ -1,6 +1,6 @@ import {Form, Input, Button, Row, Col, Typography} from 'antd'; import {useEffect, useState} from 'react'; -import {useAuth} from "../../Hooks/AuthContext.jsx"; +import {useAuth} from "../../../Hooks/AuthContext.jsx"; import {useNavigate} from "react-router-dom"; const {Title} = Typography; diff --git a/web-app/src/Components/Pages/PatientsPage/Components/PatientFormModal/PatientFormModal.jsx b/web-app/src/Components/Pages/PatientsPage/Components/PatientFormModal/PatientFormModal.jsx index da93f52..634d9c1 100644 --- a/web-app/src/Components/Pages/PatientsPage/Components/PatientFormModal/PatientFormModal.jsx +++ b/web-app/src/Components/Pages/PatientsPage/Components/PatientFormModal/PatientFormModal.jsx @@ -4,12 +4,12 @@ import locale from "antd/es/date-picker/locale/ru_RU"; import {MaskedInput} from "antd-mask-input"; import dayjs from "dayjs"; import {PatientPropType} from "../../../../../Types/patientPropType.js"; -import usePatientFormModalUI from "./usePatientFormModalUI.js"; +import usePatientFormUI from "./usePatientFormUI.js"; const {TextArea} = Input; const PatientFormModal = ({visible, onCancel, onSubmit, patient}) => { - const patientFormModalUI = usePatientFormModalUI(visible, onCancel, onSubmit, patient); + const patientFormModalUI = usePatientFormUI(visible, onCancel, onSubmit, patient); return ( { +const usePatientFormUI = (visible, onCancel, onSubmit, patient) => { const [form] = Form.useForm(); useEffect(() => { @@ -65,4 +65,4 @@ const usePatientFormModalUI = (visible, onCancel, onSubmit, patient) => { } }; -export default usePatientFormModalUI; \ No newline at end of file +export default usePatientFormUI; \ No newline at end of file diff --git a/web-app/src/Components/Widgets/CalendarCell.jsx b/web-app/src/Components/Widgets/CalendarCell.jsx index ec01906..ad8355b 100644 --- a/web-app/src/Components/Widgets/CalendarCell.jsx +++ b/web-app/src/Components/Widgets/CalendarCell.jsx @@ -1,5 +1,5 @@ import {useEffect, useRef, useState} from "react"; -import {Badge, Col, Tag, Tooltip, Typography} from "antd"; +import {Badge, Col, Tag, Tooltip} from "antd"; import dayjs from "dayjs"; import PropTypes from "prop-types"; import {AppointmentPropType} from "../../Types/appointmentPropType.js"; @@ -38,6 +38,7 @@ const CalendarCell = ({appointments, scheduledAppointments, onCellClick, onItemC {appointments.map(app => ( @@ -61,6 +62,7 @@ const CalendarCell = ({appointments, scheduledAppointments, onCellClick, onItemC {scheduledAppointments.map(app => ( diff --git a/web-app/src/Redux/Slices/appointmentsSlice.js b/web-app/src/Redux/Slices/appointmentsSlice.js new file mode 100644 index 0000000..249324c --- /dev/null +++ b/web-app/src/Redux/Slices/appointmentsSlice.js @@ -0,0 +1,57 @@ +import {createSlice} from "@reduxjs/toolkit"; +import dayjs from "dayjs"; + + +const initialState = { + collapsed: true, + siderWidth: 250, + hovered: false, + selectedDate: dayjs().format('YYYY-MM-DD'), + modalVisible: false, + selectedAppointments: [], + selectedAppointment: null, +}; + +const appointmentsSlice = createSlice({ + name: 'appointmentsUI', + initialState, + reducers: { + toggleSider: (state) => { + state.collapsed = !state.collapsed; + }, + setSiderWidth: (state, action) => { + state.siderWidth = action.payload; + }, + setHovered: (state, action) => { + state.hovered = action.payload; + }, + setSelectedDate: (state, action) => { + state.selectedDate = action.payload; + }, + openModal: (state) => { + state.modalVisible = true; + }, + closeModal: (state) => { + state.modalVisible = false; + }, + setSelectedAppointments: (state, action) => { + state.selectedAppointments = action.payload; + }, + setSelectedAppointment: (state, action) => { + state.selectedAppointment = action.payload; + }, + } +}); + +export const { + toggleSider, + setSiderWidth, + setHovered, + setSelectedDate, + openModal, + closeModal, + setSelectedAppointments, + setSelectedAppointment, +} = appointmentsSlice.actions; + +export default appointmentsSlice.reducer; \ No newline at end of file diff --git a/web-app/src/Redux/store.js b/web-app/src/Redux/store.js index 257c197..abdf18d 100644 --- a/web-app/src/Redux/store.js +++ b/web-app/src/Redux/store.js @@ -9,6 +9,8 @@ import {setContentApi} from "../Api/setContentApi.js"; import {lensIssuesApi} from "../Api/lensIssuesApi.js"; import lensIssuesReducer from "./Slices/lensIssuesSlice.js"; import {lensTypesApi} from "../Api/lensTypesApi.js"; +import {appointmentsApi} from "../Api/appointmentsApi.js"; +import appointmentsReducer from "./Slices/appointmentsSlice.js"; export const store = configureStore({ reducer: { @@ -27,6 +29,9 @@ export const store = configureStore({ [lensIssuesApi.reducerPath]: lensIssuesApi.reducer, lensIssuesUI: lensIssuesReducer, + + [appointmentsApi.reducerPath]: appointmentsApi.reducer, + appointmentsUI: appointmentsReducer, }, middleware: (getDefaultMiddleware) => ( getDefaultMiddleware().concat( @@ -36,8 +41,9 @@ export const store = configureStore({ setContentApi.middleware, lensTypesApi.middleware, lensIssuesApi.middleware, + appointmentsApi.middleware, ) - ) + ), }); export default store; \ No newline at end of file diff --git a/web-app/src/old_api/appointments/getAllAppointments.js b/web-app/src/old_api/appointments/getAllAppointments.js deleted file mode 100644 index 4ae243f..0000000 --- a/web-app/src/old_api/appointments/getAllAppointments.js +++ /dev/null @@ -1,8 +0,0 @@ -import CONFIG from "../../Core/сonfig.js"; - -const getAllAppointments = async (api) => { - const response = await api.get(`${CONFIG.BASE_URL}/appointments/`); - return response.data; -}; - -export default getAllAppointments; \ No newline at end of file diff --git a/web-app/src/old_api/lens_issues/addLensIssue.js b/web-app/src/old_api/lens_issues/addLensIssue.js deleted file mode 100644 index f5d2524..0000000 --- a/web-app/src/old_api/lens_issues/addLensIssue.js +++ /dev/null @@ -1,8 +0,0 @@ -import CONFIG from "../../Core/сonfig.js"; - -const AddLensIssue = async (api, lens_issue) => { - const response = await api.post(`${CONFIG.BASE_URL}/lens_issues/`, lens_issue); - return response.data; -}; - -export default AddLensIssue; \ No newline at end of file diff --git a/web-app/src/old_api/lens_issues/getAllLensIssues.js b/web-app/src/old_api/lens_issues/getAllLensIssues.js deleted file mode 100644 index 7bf884d..0000000 --- a/web-app/src/old_api/lens_issues/getAllLensIssues.js +++ /dev/null @@ -1,8 +0,0 @@ -import CONFIG from "../../Core/сonfig.js"; - -const GetAllLensIssues = async (api) => { - const response = await api.get(`${CONFIG.BASE_URL}/lens_issues/`); - return response.data; -}; - -export default GetAllLensIssues; \ No newline at end of file diff --git a/web-app/src/old_api/lens_types/getAllLensTypes.js b/web-app/src/old_api/lens_types/getAllLensTypes.js deleted file mode 100644 index 8755872..0000000 --- a/web-app/src/old_api/lens_types/getAllLensTypes.js +++ /dev/null @@ -1,8 +0,0 @@ -import CONFIG from "../../Core/сonfig.js"; - -const getAllLensTypes = async (api) => { - const response = await api.get(`${CONFIG.BASE_URL}/lens_types/`); - return response.data; -}; - -export default getAllLensTypes; \ No newline at end of file diff --git a/web-app/src/old_api/lenses/getNotIssuedLenses.js b/web-app/src/old_api/lenses/getNotIssuedLenses.js deleted file mode 100644 index e8ab429..0000000 --- a/web-app/src/old_api/lenses/getNotIssuedLenses.js +++ /dev/null @@ -1,8 +0,0 @@ -import CONFIG from "../../Core/сonfig.js"; - -const getNotIssuedLenses = async (api) => { - const response = await api.get(`${CONFIG.BASE_URL}/lenses/not_issued/`); - return response.data; -}; - -export default getNotIssuedLenses; \ No newline at end of file diff --git a/web-app/src/old_api/patients/getAllPatients.js b/web-app/src/old_api/patients/getAllPatients.js deleted file mode 100644 index 44c8970..0000000 --- a/web-app/src/old_api/patients/getAllPatients.js +++ /dev/null @@ -1,8 +0,0 @@ -import CONFIG from "../../Core/сonfig.js"; - -const getAllPatients = async (api) => { - const response = await api.get(`${CONFIG.BASE_URL}/patients/`); - return response.data; -}; - -export default getAllPatients; \ No newline at end of file diff --git a/web-app/src/old_api/scheduled_appointments/getAllScheduledAppointments.js b/web-app/src/old_api/scheduled_appointments/getAllScheduledAppointments.js deleted file mode 100644 index 8fdbd58..0000000 --- a/web-app/src/old_api/scheduled_appointments/getAllScheduledAppointments.js +++ /dev/null @@ -1,8 +0,0 @@ -import CONFIG from "../../Core/сonfig.js"; - -const getAllScheduledAppointments = async (api) => { - const response = await api.get(`${CONFIG.BASE_URL}/scheduled_appointments/`); - return response.data; -}; - -export default getAllScheduledAppointments; \ No newline at end of file diff --git a/web-app/src/old_api/set_content/getSetContentBySetId.js b/web-app/src/old_api/set_content/getSetContentBySetId.js deleted file mode 100644 index 6fa7b2b..0000000 --- a/web-app/src/old_api/set_content/getSetContentBySetId.js +++ /dev/null @@ -1,8 +0,0 @@ -import CONFIG from "../../Core/сonfig.js"; - -const getSetContentBySetId = async (api, set_id) => { - const response = await api.get(`${CONFIG.BASE_URL}/set_content/${set_id}/`); - return response.data; -}; - -export default getSetContentBySetId; \ No newline at end of file