diff --git a/api/app/domain/entities/scheduled_appointment.py b/api/app/domain/entities/scheduled_appointment.py
index 79faf99..25f4ded 100644
--- a/api/app/domain/entities/scheduled_appointment.py
+++ b/api/app/domain/entities/scheduled_appointment.py
@@ -11,7 +11,7 @@ from app.domain.entities.user import UserEntity
class ScheduledAppointmentEntity(BaseModel):
id: Optional[int] = None
scheduled_datetime: datetime.datetime
- is_canceled: bool
+ is_canceled: Optional[bool] = False
patient_id: int
doctor_id: Optional[int] = None
diff --git a/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx b/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx
index 9e1a587..d1fefe3 100644
--- a/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx
+++ b/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx
@@ -131,7 +131,6 @@ const AppointmentsPage = () => {
diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/useAppointmentCalendarUI.js b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/useAppointmentCalendarUI.js
index 972529c..d74b550 100644
--- a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/useAppointmentCalendarUI.js
+++ b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/useAppointmentCalendarUI.js
@@ -1,20 +1,13 @@
-// useAppointmentCalendarUI.js
import {useDispatch, useSelector} from "react-redux";
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
-import {Form, Grid, notification} from "antd";
+import {Grid} from "antd";
import {
- closeModal,
openModal, setSelectedAppointment,
setSelectedAppointments,
- setSelectedDate, setSelectedScheduledAppointment,
+ setSelectedScheduledAppointment,
} from "../../../../../Redux/Slices/appointmentsSlice.js";
-import {useCreateAppointmentMutation, useUpdateAppointmentMutation} from "../../../../../Api/appointmentsApi.js";
-import {
- useCreateScheduledAppointmentMutation,
- useUpdateScheduledAppointmentMutation
-} from "../../../../../Api/scheduledAppointmentsApi.js";
dayjs.extend(utc);
dayjs.extend(timezone);
@@ -24,12 +17,6 @@ const {useBreakpoint} = Grid;
const useAppointmentCalendarUI = (appointments, scheduledAppointments) => {
const dispatch = useDispatch();
- const {
- modalVisible,
- selectedAppointments,
- selectedAppointment,
- selectedScheduledAppointment,
- } = useSelector(state => state.appointmentsUI);
const selectedDate = dayjs.tz(useSelector(state => state.appointmentsUI.selectedDate), 'Europe/Moscow');
const screens = useBreakpoint();
@@ -39,7 +26,7 @@ const useAppointmentCalendarUI = (appointments, scheduledAppointments) => {
const onSelect = (date) => {
const selectedDateStr = date.format('YYYY-MM-DD');
- dispatch(setSelectedDate(selectedDateStr));
+ // dispatch(setSelectedDate(selectedDateStr));
const appointmentsForDate = appointments.filter(app =>
dayjs(app.appointment_datetime).format('YYYY-MM-DD') === selectedDateStr
@@ -62,10 +49,9 @@ const useAppointmentCalendarUI = (appointments, scheduledAppointments) => {
};
const getAppointmentsByListAndDate = (list, value, isScheduled = false) => {
- const date = value.tz('Europe/Moscow').format('YYYY-MM-DD');
+ const date = value.format('YYYY-MM-DD');
return list.filter(app =>
dayjs(isScheduled ? app.scheduled_datetime : app.appointment_datetime)
- .tz('Europe/Moscow')
.format('YYYY-MM-DD') === date
);
};
diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/AppointmentFormModal.jsx b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/AppointmentFormModal.jsx
index b7d1de5..7317afd 100644
--- a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/AppointmentFormModal.jsx
+++ b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/AppointmentFormModal.jsx
@@ -28,6 +28,7 @@ const AppointmentFormModal = ({onCancel}) => {
onCancel,
appointmentFormModalData.createAppointment,
appointmentFormModalData.patients,
+ appointmentFormModalData.cancelAppointment,
);
const editor = useRef(null);
diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/useAppointmentFormModal.js b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/useAppointmentFormModal.js
index ab197b2..6cf7647 100644
--- a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/useAppointmentFormModal.js
+++ b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/useAppointmentFormModal.js
@@ -1,6 +1,7 @@
import {useGetPatientsQuery} from "../../../../../Api/patientsApi.js";
import {useGetAppointmentTypesQuery} from "../../../../../Api/appointmentTypesApi.js";
import {useCreateAppointmentMutation, useUpdateAppointmentMutation} from "../../../../../Api/appointmentsApi.js";
+import {useCancelScheduledAppointmentMutation} from "../../../../../Api/scheduledAppointmentsApi.js";
const useAppointmentFormModal = () => {
const {
@@ -19,11 +20,13 @@ const useAppointmentFormModal = () => {
});
const [createAppointment, {isLoading: isCreating, isError: isErrorCreating}] = useCreateAppointmentMutation();
+ const [cancelAppointment] = useCancelScheduledAppointmentMutation();
return {
patients,
appointmentTypes,
createAppointment,
+ cancelAppointment,
isLoading: isLoadingPatients || isLoadingAppointmentTypes || isCreating,
isError: isErrorPatients || isErrorAppointmentTypes || isErrorCreating,
};
diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/useAppointmentFormModalUI.js b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/useAppointmentFormModalUI.js
index c1a860a..8b8a74f 100644
--- a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/useAppointmentFormModalUI.js
+++ b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentFormModal/useAppointmentFormModalUI.js
@@ -1,6 +1,6 @@
import {Form, notification} from "antd";
import {useDispatch, useSelector} from "react-redux";
-import {closeModal} from "../../../../../Redux/Slices/appointmentsSlice.js";
+import {closeModal, setSelectedScheduledAppointment} from "../../../../../Redux/Slices/appointmentsSlice.js";
import {useEffect, useMemo, useState} from "react";
import dayjs from "dayjs";
import {useGetAppointmentsQuery} from "../../../../../Api/appointmentsApi.js";
@@ -8,9 +8,9 @@ import {Grid} from "antd";
const {useBreakpoint} = Grid;
-const useAppointmentFormModalUI = (onCancel, createAppointment, patients) => {
+const useAppointmentFormModalUI = (onCancel, createAppointment, patients, cancelAppointment) => {
const dispatch = useDispatch();
- const {modalVisible} = useSelector(state => state.appointmentsUI);
+ const {modalVisible, scheduledData} = useSelector(state => state.appointmentsUI);
const [form] = Form.useForm();
const screens = useBreakpoint();
@@ -53,11 +53,24 @@ const useAppointmentFormModalUI = (onCancel, createAppointment, patients) => {
setSearchPatientString("");
setFormValues({});
- form.setFieldsValue({
- appointment_datetime: dayjs(new Date()),
- })
+ if (scheduledData) {
+ const patient = patients.find(p => p.id === scheduledData.patient_id);
+ if (patient) {
+ setSelectedPatient(patient);
+ setCurrentStep(1); // Skip to appointment details step
+ form.setFieldsValue({
+ patient_id: scheduledData.patient_id,
+ type_id: scheduledData.type_id,
+ appointment_datetime: dayjs(scheduledData.appointment_datetime),
+ });
+ }
+ } else {
+ form.setFieldsValue({
+ appointment_datetime: dayjs(new Date()),
+ });
+ }
}
- }, [modalVisible, form]);
+ }, [modalVisible, form, scheduledData, patients]);
const handleResultsChange = (newContent) => {
setResults(newContent);
@@ -144,8 +157,13 @@ const useAppointmentFormModalUI = (onCancel, createAppointment, patients) => {
results: results,
};
-
await createAppointment(data).unwrap();
+
+ if (scheduledData) {
+ await cancelScheduledAppointment(scheduledData.id);
+ dispatch(setSelectedScheduledAppointment(null));
+ }
+
notification.success({
message: 'Прием создан',
description: 'Прием успешно создан.',
@@ -166,6 +184,18 @@ const useAppointmentFormModalUI = (onCancel, createAppointment, patients) => {
}
};
+ const cancelScheduledAppointment = async (selectedScheduledAppointmentId) => {
+ try {
+ await cancelAppointment(selectedScheduledAppointmentId);
+ } catch (error) {
+ notification.error({
+ message: 'Ошибка',
+ description: error.data?.message || 'Не удалось отменить прием.',
+ placement: 'topRight',
+ })
+ }
+ };
+
const handleCancel = () => {
form.resetFields();
setSelectedPatient(null);
diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/ScheduledAppintmentFormModal/useScheduledAppointmentFormModalUI.js b/web-app/src/Components/Pages/AppointmentsPage/Components/ScheduledAppintmentFormModal/useScheduledAppointmentFormModalUI.js
index e7534e9..aaa0807 100644
--- a/web-app/src/Components/Pages/AppointmentsPage/Components/ScheduledAppintmentFormModal/useScheduledAppointmentFormModalUI.js
+++ b/web-app/src/Components/Pages/AppointmentsPage/Components/ScheduledAppintmentFormModal/useScheduledAppointmentFormModalUI.js
@@ -25,14 +25,16 @@ const useScheduledAppointmentFormModalUI = (patients, createScheduledAppointment
type_id: selectedAppointmentType
};
- console.log(data)
-
await createScheduledAppointment(data).unwrap();
notification.success({
message: 'Прием создан',
placement: 'topRight',
description: 'Прием успешно запланирован.',
- })
+ });
+
+ setSelectedPatient(null);
+ setSelectedDateTime(dayjs(new Date()).add(1, 'day'));
+ setSelectedAppointmentType(null);
dispatch(closeScheduledModal());
} catch (error) {
diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx b/web-app/src/Components/Pages/AppointmentsPage/Components/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx
index c60b404..2441c4f 100644
--- a/web-app/src/Components/Pages/AppointmentsPage/Components/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx
+++ b/web-app/src/Components/Pages/AppointmentsPage/Components/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx
@@ -2,8 +2,11 @@ import {Button, Modal, Popconfirm, Row, Typography} from "antd";
import dayjs from "dayjs";
import useScheduledAppointmentsViewModal from "./useScheduledAppointmentsViewModal.js";
import useScheduledAppointmentsViewModalUI from "./useScheduledAppointmentsViewModalUI.js";
+import { useDispatch } from "react-redux";
+import {openModalWithScheduledData} from "../../../../../Redux/Slices/appointmentsSlice.js";
const ScheduledAppointmentsViewModal = () => {
+ const dispatch = useDispatch();
const scheduledAppointmentsViewModalData = useScheduledAppointmentsViewModal();
const scheduledAppointmentsViewModalUI = useScheduledAppointmentsViewModalUI(scheduledAppointmentsViewModalData.cancelAppointment);
@@ -11,6 +14,15 @@ const ScheduledAppointmentsViewModal = () => {
return null;
}
+ const handleConvertToAppointment = () => {
+ dispatch(openModalWithScheduledData({
+ id: scheduledAppointmentsViewModalUI.selectedScheduledAppointment.id,
+ patient_id: scheduledAppointmentsViewModalUI.selectedScheduledAppointment.patient?.id,
+ type_id: scheduledAppointmentsViewModalUI.selectedScheduledAppointment.type?.id,
+ appointment_datetime: scheduledAppointmentsViewModalUI.selectedScheduledAppointment.scheduled_datetime,
+ }));
+ };
+
return (
{
onClick={scheduledAppointmentsViewModalUI.onCancel}>
Закрыть
+
{
-
);
};
diff --git a/web-app/src/Redux/Slices/appointmentsSlice.js b/web-app/src/Redux/Slices/appointmentsSlice.js
index 6a772b4..b555a98 100644
--- a/web-app/src/Redux/Slices/appointmentsSlice.js
+++ b/web-app/src/Redux/Slices/appointmentsSlice.js
@@ -1,72 +1,69 @@
-import { createSlice } from "@reduxjs/toolkit";
+import { createSlice } from '@reduxjs/toolkit';
const initialState = {
- collapsed: true,
- siderWidth: 250,
- hovered: false,
modalVisible: false,
- scheduledModalVisible: false,
+ collapsed: true,
+ siderWidth: 300,
+ hovered: false,
selectedAppointment: null,
- scheduledAppointments: [],
selectedScheduledAppointment: null,
+ scheduledModalVisible: false,
+ scheduledData: null,
+ selectedAppointments: [], // Новое поле для хранения массива выбранных приемов
};
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) => {
+ openModal(state) {
state.modalVisible = true;
},
- closeModal: (state) => {
+ closeModal(state) {
state.modalVisible = false;
},
- openScheduledModal: (state) => {
- state.scheduledModalVisible = true;
+ toggleSider(state) {
+ state.collapsed = !state.collapsed;
},
- closeScheduledModal: (state) => {
- state.scheduledModalVisible = false;
+ setSiderWidth(state, action) {
+ state.siderWidth = action.payload;
},
- setSelectedAppointments: (state, action) => {
- state.selectedAppointments = action.payload;
+ setHovered(state, action) {
+ state.hovered = action.payload;
},
- setSelectedAppointment: (state, action) => {
+ setSelectedAppointment(state, action) {
state.selectedAppointment = action.payload;
},
- setScheduledAppointments: (state, action) => {
- state.scheduledAppointments = action.payload;
- },
- setSelectedScheduledAppointment: (state, action) => {
+ setSelectedScheduledAppointment(state, action) {
state.selectedScheduledAppointment = action.payload;
},
- }
+ openScheduledModal(state) {
+ state.scheduledModalVisible = true;
+ },
+ closeScheduledModal(state) {
+ state.scheduledModalVisible = false;
+ },
+ openModalWithScheduledData(state, action) {
+ state.modalVisible = true;
+ state.scheduledData = action.payload;
+ },
+ setSelectedAppointments(state, action) {
+ state.selectedAppointments = action.payload;
+ },
+ },
});
export const {
- toggleSider,
- setSiderWidth,
- setHovered,
- setSelectedDate,
openModal,
closeModal,
- setSelectedAppointments,
+ toggleSider,
+ setHovered,
setSelectedAppointment,
setSelectedScheduledAppointment,
- setScheduledAppointments,
openScheduledModal,
closeScheduledModal,
+ openModalWithScheduledData,
+ setSelectedAppointments,
} = appointmentsSlice.actions;
export default appointmentsSlice.reducer;
\ No newline at end of file