сделал конвертацию запланированного приема в обычный прием

This commit is contained in:
Андрей Дувакин 2025-06-01 20:43:06 +05:00
parent d101036445
commit 55369ac1a4
9 changed files with 102 additions and 70 deletions

View File

@ -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

View File

@ -131,7 +131,6 @@ const AppointmentsPage = () => {
</FloatButton.Group>
<AppointmentFormModal
visible={appointmentsPageUI.modalVisible}
onCancel={handleCancelModal}
/>

View File

@ -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
);
};

View File

@ -28,6 +28,7 @@ const AppointmentFormModal = ({onCancel}) => {
onCancel,
appointmentFormModalData.createAppointment,
appointmentFormModalData.patients,
appointmentFormModalData.cancelAppointment,
);
const editor = useRef(null);

View File

@ -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,
};

View File

@ -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);

View File

@ -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) {

View File

@ -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 (
<Modal
title="Просмотр запланированного приема"
@ -51,6 +63,9 @@ const ScheduledAppointmentsViewModal = () => {
onClick={scheduledAppointmentsViewModalUI.onCancel}>
Закрыть
</Button>
<Button type="primary" onClick={handleConvertToAppointment}>
Конвертировать в прием
</Button>
<Popconfirm
title="Вы уверены, что хотите отменить прием?"
onConfirm={scheduledAppointmentsViewModalUI.cancelScheduledAppointment}
@ -62,7 +77,6 @@ const ScheduledAppointmentsViewModal = () => {
</Button>
</Popconfirm>
</Row>
</Modal>
);
};

View File

@ -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;