diff --git a/api/app/application/appointments_repository.py b/api/app/application/appointments_repository.py index 14b4681..0853ad7 100644 --- a/api/app/application/appointments_repository.py +++ b/api/app/application/appointments_repository.py @@ -1,5 +1,5 @@ from typing import Sequence, Optional -from sqlalchemy import select, desc +from sqlalchemy import select, desc, func from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import joinedload from datetime import date @@ -27,7 +27,7 @@ class AppointmentsRepository: return result.scalars().all() async def get_by_doctor_id(self, doctor_id: int, start_date: date | None = None, end_date: date | None = None) -> \ - Sequence[Appointment]: + Sequence[Appointment]: stmt = ( select(Appointment) .options(joinedload(Appointment.type)) @@ -43,8 +43,22 @@ class AppointmentsRepository: result = await self.db.execute(stmt) return result.scalars().all() + async def get_upcoming_by_doctor_id(self, doctor_id: int) -> Sequence[Appointment]: + stmt = ( + select(Appointment) + .options(joinedload(Appointment.type)) + .options(joinedload(Appointment.patient)) + .options(joinedload(Appointment.doctor)) + .filter_by(doctor_id=doctor_id) + .filter(Appointment.appointment_datetime >= func.now()) + .order_by(Appointment.appointment_datetime) + .limit(5) + ) + result = await self.db.execute(stmt) + return result.scalars().all() + async def get_by_patient_id(self, patient_id: int, start_date: date | None = None, end_date: date | None = None) -> \ - Sequence[Appointment]: + Sequence[Appointment]: stmt = ( select(Appointment) .options(joinedload(Appointment.type)) diff --git a/api/app/application/scheduled_appointments_repository.py b/api/app/application/scheduled_appointments_repository.py index da72af0..dfa25dd 100644 --- a/api/app/application/scheduled_appointments_repository.py +++ b/api/app/application/scheduled_appointments_repository.py @@ -1,5 +1,5 @@ from typing import Sequence -from sqlalchemy import select, desc +from sqlalchemy import select, desc, func from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import joinedload from datetime import date @@ -29,7 +29,7 @@ class ScheduledAppointmentsRepository: return result.scalars().all() async def get_by_doctor_id(self, doctor_id: int, start_date: date | None = None, end_date: date | None = None) -> \ - Sequence[ScheduledAppointment]: + Sequence[ScheduledAppointment]: stmt = ( select(ScheduledAppointment) .options(joinedload(ScheduledAppointment.type)) @@ -45,8 +45,22 @@ class ScheduledAppointmentsRepository: result = await self.db.execute(stmt) return result.scalars().all() + async def get_upcoming_by_doctor_id(self, doctor_id: int) -> Sequence[ScheduledAppointment]: + stmt = ( + select(ScheduledAppointment) + .options(joinedload(ScheduledAppointment.type)) + .options(joinedload(ScheduledAppointment.patient)) + .options(joinedload(ScheduledAppointment.doctor)) + .filter_by(doctor_id=doctor_id, is_canceled=False) + .filter(ScheduledAppointment.scheduled_datetime >= func.now()) + .order_by(ScheduledAppointment.scheduled_datetime) + .limit(5) + ) + result = await self.db.execute(stmt) + return result.scalars().all() + async def get_by_patient_id(self, patient_id: int, start_date: date | None = None, end_date: date | None = None) -> \ - Sequence[ScheduledAppointment]: + Sequence[ScheduledAppointment]: stmt = ( select(ScheduledAppointment) .options(joinedload(ScheduledAppointment.type)) diff --git a/api/app/controllers/appointments_router.py b/api/app/controllers/appointments_router.py index 0b2fdfd..cb41f66 100644 --- a/api/app/controllers/appointments_router.py +++ b/api/app/controllers/appointments_router.py @@ -43,6 +43,21 @@ async def get_all_appointments_by_doctor_id( return await appointments_service.get_appointments_by_doctor_id(doctor_id, start_date=start_date, end_date=end_date) +@router.get( + "/doctor/{doctor_id}/upcoming/", + response_model=list[AppointmentEntity], + summary="Get upcoming appointments for doctor", + description="Returns the next 5 upcoming appointments for doctor", +) +async def get_upcoming_appointments_by_doctor_id( + doctor_id: int, + db: AsyncSession = Depends(get_db), + user=Depends(get_current_user), +): + appointments_service = AppointmentsService(db) + return await appointments_service.get_upcoming_appointments_by_doctor_id(doctor_id) + + @router.get( "/patient/{patient_id}/", response_model=list[AppointmentEntity], diff --git a/api/app/controllers/scheduled_appointments_router.py b/api/app/controllers/scheduled_appointments_router.py index cfd4515..8e1c83e 100644 --- a/api/app/controllers/scheduled_appointments_router.py +++ b/api/app/controllers/scheduled_appointments_router.py @@ -45,6 +45,21 @@ async def get_all_scheduled_appointments_by_doctor_id( end_date=end_date) +@router.get( + "/doctor/{doctor_id}/upcoming/", + response_model=list[ScheduledAppointmentEntity], + summary="Get upcoming scheduled appointments for doctor", + description="Returns the next 5 upcoming scheduled appointments for doctor", +) +async def get_upcoming_scheduled_appointments_by_doctor_id( + doctor_id: int, + db: AsyncSession = Depends(get_db), + user=Depends(get_current_user), +): + appointments_service = ScheduledAppointmentsService(db) + return await appointments_service.get_upcoming_scheduled_appointments_by_doctor_id(doctor_id) + + @router.get( "/patient/{patient_id}/", response_model=ScheduledAppointmentEntity, diff --git a/api/app/infrastructure/appointments_service.py b/api/app/infrastructure/appointments_service.py index cf6a14d..bafd822 100644 --- a/api/app/infrastructure/appointments_service.py +++ b/api/app/infrastructure/appointments_service.py @@ -39,6 +39,16 @@ class AppointmentsService: end_date=end_date) return [self.model_to_entity(appointment) for appointment in appointments] + async def get_upcoming_appointments_by_doctor_id(self, doctor_id: int) -> Optional[list[AppointmentEntity]]: + doctor = await self.users_repository.get_by_id(doctor_id) + if not doctor: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail='Доктор с таким ID не найден', + ) + appointments = await self.appointments_repository.get_upcoming_by_doctor_id(doctor_id) + return [self.model_to_entity(appointment) for appointment in appointments] + async def get_appointments_by_patient_id(self, patient_id: int, start_date: date | None = None, end_date: date | None = None) -> Optional[list[AppointmentEntity]]: patient = await self.patients_repository.get_by_id(patient_id) diff --git a/api/app/infrastructure/scheduled_appointments_service.py b/api/app/infrastructure/scheduled_appointments_service.py index ea6fe71..7213b8e 100644 --- a/api/app/infrastructure/scheduled_appointments_service.py +++ b/api/app/infrastructure/scheduled_appointments_service.py @@ -39,6 +39,17 @@ class ScheduledAppointmentsService: end_date=end_date) return [self.model_to_entity(scheduled_appointment) for scheduled_appointment in scheduled_appointments] + async def get_upcoming_scheduled_appointments_by_doctor_id(self, doctor_id: int) -> Optional[ + list[ScheduledAppointmentEntity]]: + doctor = await self.users_repository.get_by_id(doctor_id) + if not doctor: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail='Доктор с таким ID не найден', + ) + scheduled_appointments = await self.scheduled_appointment_repository.get_upcoming_by_doctor_id(doctor_id) + return [self.model_to_entity(scheduled_appointment) for scheduled_appointment in scheduled_appointments] + async def get_scheduled_appointments_by_patient_id(self, patient_id: int, start_date: date | None = None, end_date: date | None = None) -> Optional[ list[ScheduledAppointmentEntity]]: diff --git a/web-app/src/Api/appointmentsApi.js b/web-app/src/Api/appointmentsApi.js index ae92b58..4e6631d 100644 --- a/web-app/src/Api/appointmentsApi.js +++ b/web-app/src/Api/appointmentsApi.js @@ -1,5 +1,5 @@ -import { createApi } from "@reduxjs/toolkit/query/react"; -import { baseQueryWithAuth } from "./baseQuery.js"; +import {createApi} from "@reduxjs/toolkit/query/react"; +import {baseQueryWithAuth} from "./baseQuery.js"; export const appointmentsApi = createApi({ reducerPath: 'appointmentsApi', @@ -7,13 +7,17 @@ export const appointmentsApi = createApi({ tagTypes: ['Appointment'], endpoints: (builder) => ({ getAppointments: builder.query({ - query: ({ doctor_id, start_date, end_date }) => ({ + query: ({doctor_id, start_date, end_date}) => ({ url: `/appointments/doctor/${doctor_id}/`, - params: { start_date, end_date }, + params: {start_date, end_date}, }), providesTags: ['Appointment'], refetchOnMountOrArgChange: 5, }), + getUpcomingAppointments: builder.query({ + query: (doctor_id) => `/appointments/doctor/${doctor_id}/upcoming/`, + providesTags: ['Appointment'], + }), getByPatientId: builder.query({ query: (id) => `/appointments/patient/${id}/`, providesTags: ['Appointment'], @@ -28,7 +32,7 @@ export const appointmentsApi = createApi({ invalidatesTags: ['Appointment'], }), updateAppointment: builder.mutation({ - query: ({ id, data }) => ({ + query: ({id, data}) => ({ url: `/appointments/${id}/`, method: 'PUT', body: data, @@ -40,6 +44,7 @@ export const appointmentsApi = createApi({ export const { useGetAppointmentsQuery, + useGetUpcomingAppointmentsQuery, useGetByPatientIdQuery, useCreateAppointmentMutation, useUpdateAppointmentMutation, diff --git a/web-app/src/Api/scheduledAppointmentsApi.js b/web-app/src/Api/scheduledAppointmentsApi.js index 96dc4d7..6398744 100644 --- a/web-app/src/Api/scheduledAppointmentsApi.js +++ b/web-app/src/Api/scheduledAppointmentsApi.js @@ -13,6 +13,10 @@ export const scheduledAppointmentsApi = createApi({ }), providesTags: ['ScheduledAppointment'], }), + getUpcomingScheduledAppointments: builder.query({ + query: (doctor_id) => `/scheduled_appointments/doctor/${doctor_id}/upcoming/`, + providesTags: ['ScheduledAppointment'], + }), createScheduledAppointment: builder.mutation({ query: (data) => ({ url: '/scheduled_appointments/', @@ -41,6 +45,7 @@ export const scheduledAppointmentsApi = createApi({ export const { useGetScheduledAppointmentsQuery, + useGetUpcomingScheduledAppointmentsQuery, useCreateScheduledAppointmentMutation, useUpdateScheduledAppointmentMutation, useCancelScheduledAppointmentMutation, diff --git a/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx b/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx index cbc5f05..adc1e10 100644 --- a/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx +++ b/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx @@ -1,5 +1,5 @@ -import {Badge, Button, FloatButton, List, Result, Row, Space, Tag, Typography} from "antd"; -import {Splitter} from "antd"; +import { Badge, Button, FloatButton, List, Result, Row, Space, Tag, Typography } from "antd"; +import { Splitter } from "antd"; import { CalendarOutlined, MenuFoldOutlined, @@ -13,14 +13,15 @@ import dayjs from 'dayjs'; import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx"; import AppointmentFormModal from "../../Dummies/AppointmentFormModal/AppointmentFormModal.jsx"; import AppointmentViewModal from "../../Dummies/AppointmentViewModal/AppointmentViewModal.jsx"; -import ScheduledAppointmentFormModal - from "../../Dummies/ScheduledAppintmentFormModal/ScheduledAppointmentFormModal.jsx"; -import ScheduledAppointmentsViewModal - from "../../Widgets/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx"; +import ScheduledAppointmentFormModal from "../../Dummies/ScheduledAppintmentFormModal/ScheduledAppointmentFormModal.jsx"; +import ScheduledAppointmentsViewModal from "../../Widgets/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx"; import AppointmentsListModal from "./Components/AppointmentsListModal/AppointmentsListModal.jsx"; const AppointmentsPage = () => { const { + patients, // Добавляем + appointments, // Добавляем + scheduledAppointments, // Добавляем isLoading, isError, collapsed, @@ -46,7 +47,6 @@ const AppointmentsPage = () => { openCreateAppointmentModal, } = useAppointments(); - if (isError) return ( { return ( <> - Приемы + Приемы {isLoading ? ( - + ) : ( <> - + - + - Запланированный прием - - } - /> + text={Запланированный прием} /> - + - Прошедший прием - - } - /> + text={Прошедший прием} /> @@ -100,9 +90,10 @@ const AppointmentsPage = () => { - {showSplitterPanel && ( { dataSource={upcomingEvents.sort((a, b) => dayjs(a.appointment_datetime || a.scheduled_datetime).diff( dayjs(b.appointment_datetime || b.scheduled_datetime) - ) - )} + ))} renderItem={(item) => ( handleEventClick(item)} @@ -137,9 +127,9 @@ const AppointmentsPage = () => { {item.appointment_datetime ? ( - + ) : ( - + )} {dayjs(item.appointment_datetime || item.scheduled_datetime).format('DD.MM.YYYY HH:mm')} @@ -173,7 +163,7 @@ const AppointmentsPage = () => {