начал делать создание приема
This commit is contained in:
parent
88ee83047d
commit
89a947cd28
@ -1,31 +1,37 @@
|
|||||||
import {Button, FloatButton, Result, Tabs, Typography} from "antd";
|
import { Button, FloatButton, Result, Tabs, Typography } from "antd";
|
||||||
import {Splitter} from "antd";
|
import { Splitter } from "antd";
|
||||||
import {CalendarOutlined, TableOutlined, MenuFoldOutlined, MenuUnfoldOutlined, PlusOutlined} from "@ant-design/icons";
|
import { CalendarOutlined, TableOutlined, MenuFoldOutlined, MenuUnfoldOutlined, PlusOutlined } from "@ant-design/icons";
|
||||||
import AppointmentsCalendarTab from "./Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx";
|
import AppointmentsCalendarTab from "./Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx";
|
||||||
import AppointmentsTableTab from "./Components/AppointmentTableTab/AppointmentsTableTab.jsx";
|
import AppointmentsTableTab from "./Components/AppointmentTableTab/AppointmentsTableTab.jsx";
|
||||||
import useAppointmentsUI from "./useAppointmentsUI.js";
|
import useAppointmentsUI from "./useAppointmentsUI.js";
|
||||||
import useAppointments from "./useAppointments.js";
|
import useAppointments from "./useAppointments.js";
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx";
|
import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx";
|
||||||
import AppointmentFormModal
|
import AppointmentFormModal from "./Components/AppointmentCalendarTab/Components/AppointmentFormModal/AppointmentFormModal.jsx";
|
||||||
from "./Components/AppointmentCalendarTab/Components/AppointmentFormModal/AppointmentFormModal.jsx";
|
import { useDispatch } from "react-redux";
|
||||||
|
import { closeModal, openModal } from "../../../Redux/Slices/appointmentsSlice.js";
|
||||||
|
|
||||||
const AppointmentsPage = () => {
|
const AppointmentsPage = () => {
|
||||||
const appointmentsData = useAppointments();
|
const appointmentsData = useAppointments();
|
||||||
const appointmentsPageUI = useAppointmentsUI(appointmentsData.appointments, appointmentsData.scheduledAppointments);
|
const appointmentsPageUI = useAppointmentsUI(appointmentsData.appointments, appointmentsData.scheduledAppointments);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const handleCancelModal = () => {
|
||||||
|
dispatch(closeModal());
|
||||||
|
};
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
key: "1",
|
key: "1",
|
||||||
label: "Календарь приемов",
|
label: "Календарь приемов",
|
||||||
children: <AppointmentsCalendarTab/>,
|
children: <AppointmentsCalendarTab />,
|
||||||
icon: <CalendarOutlined/>,
|
icon: <CalendarOutlined />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "2",
|
key: "2",
|
||||||
label: "Таблица приемов",
|
label: "Таблица приемов",
|
||||||
children: <AppointmentsTableTab/>,
|
children: <AppointmentsTableTab />,
|
||||||
icon: <TableOutlined/>,
|
icon: <TableOutlined />,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -40,7 +46,7 @@ const AppointmentsPage = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{appointmentsData.isLoading ? (
|
{appointmentsData.isLoading ? (
|
||||||
<LoadingIndicator/>
|
<LoadingIndicator />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Splitter
|
<Splitter
|
||||||
@ -56,7 +62,7 @@ const AppointmentsPage = () => {
|
|||||||
min="25%"
|
min="25%"
|
||||||
max="90%"
|
max="90%"
|
||||||
>
|
>
|
||||||
<Tabs defaultActiveKey="1" items={items}/>
|
<Tabs defaultActiveKey="1" items={items} />
|
||||||
</Splitter.Panel>
|
</Splitter.Panel>
|
||||||
|
|
||||||
{appointmentsPageUI.showSplitterPanel && (
|
{appointmentsPageUI.showSplitterPanel && (
|
||||||
@ -94,34 +100,33 @@ const AppointmentsPage = () => {
|
|||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={appointmentsPageUI.handleToggleSider}
|
onClick={appointmentsPageUI.handleToggleSider}
|
||||||
icon={appointmentsPageUI.collapsed ? <MenuUnfoldOutlined/> : <MenuFoldOutlined/>}
|
icon={appointmentsPageUI.collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||||||
style={appointmentsPageUI.siderButtonStyle}
|
style={appointmentsPageUI.siderButtonStyle}
|
||||||
>
|
>
|
||||||
{appointmentsPageUI.siderButtonText}
|
{appointmentsPageUI.siderButtonText}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<FloatButton.Group
|
<FloatButton.Group
|
||||||
trigger={"hover"}
|
trigger="hover"
|
||||||
type="primary"
|
type="primary"
|
||||||
icon={<PlusOutlined/>}
|
icon={<PlusOutlined />}
|
||||||
tooltip={"Создать"}
|
tooltip="Создать"
|
||||||
>
|
>
|
||||||
<FloatButton
|
<FloatButton
|
||||||
icon={<PlusOutlined/>}
|
icon={<PlusOutlined />}
|
||||||
onClick={appointmentsPageUI.openCreateAppointmentModal}
|
onClick={() => dispatch(openModal())}
|
||||||
tooltip={"Прием"}
|
tooltip="Прием"
|
||||||
/>
|
/>
|
||||||
<FloatButton
|
<FloatButton
|
||||||
icon={<CalendarOutlined/>}
|
icon={<CalendarOutlined />}
|
||||||
onClick={appointmentsPageUI.openCreateScheduledAppointmentModal}
|
onClick={appointmentsPageUI.openCreateScheduledAppointmentModal}
|
||||||
tooltip={"Запланированный прием"}
|
tooltip="Запланированный прием"
|
||||||
/>
|
/>
|
||||||
</FloatButton.Group>
|
</FloatButton.Group>
|
||||||
|
|
||||||
<AppointmentFormModal
|
<AppointmentFormModal
|
||||||
visible={appointmentsPageUI.modalVisible}
|
visible={appointmentsPageUI.modalVisible}
|
||||||
onCancel={appointmentsPageUI.handleCloseModal}
|
onCancel={handleCancelModal}
|
||||||
onSubmit={appointmentsData.handleSubmitModal}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,16 +1,26 @@
|
|||||||
import ReactQuill from 'react-quill';
|
import ReactQuill from 'react-quill';
|
||||||
import 'react-quill/dist/quill.snow.css';
|
import 'react-quill/dist/quill.snow.css';
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import {Button, DatePicker, Form, InputNumber, Modal, Result, Select} from "antd";
|
import utc from "dayjs/plugin/utc";
|
||||||
|
import timezone from "dayjs/plugin/timezone";
|
||||||
|
import { Button, DatePicker, Form, InputNumber, Modal, Result, Select } from "antd";
|
||||||
import useAppointmentFormModal from "./useAppointmentFormModal.js";
|
import useAppointmentFormModal from "./useAppointmentFormModal.js";
|
||||||
import useAppointmentFormModalUI from "./useAppointmentFormModalUI.js";
|
import useAppointmentFormModalUI from "./useAppointmentFormModalUI.js";
|
||||||
import LoadingIndicator from "../../../../../../Widgets/LoadingIndicator.jsx";
|
import LoadingIndicator from "../../../../../../Widgets/LoadingIndicator.jsx";
|
||||||
import {DefaultModalPropType} from "../../../../../../../Types/defaultModalPropType.js";
|
import { DefaultModalPropType } from "../../../../../../../Types/defaultModalPropType.js";
|
||||||
|
|
||||||
|
dayjs.extend(utc);
|
||||||
|
dayjs.extend(timezone);
|
||||||
|
dayjs.tz.setDefault('Europe/Moscow');
|
||||||
|
|
||||||
const AppointmentFormModal = ({visible, onCancel, onSubmit}) => {
|
const AppointmentFormModal = ({ visible, onCancel }) => {
|
||||||
const appointmentFormModalData = useAppointmentFormModal();
|
const appointmentFormModalData = useAppointmentFormModal();
|
||||||
const appointmentFormModalUI = useAppointmentFormModalUI(visible, onCancel, onSubmit);
|
const appointmentFormModalUI = useAppointmentFormModalUI(
|
||||||
|
visible,
|
||||||
|
onCancel,
|
||||||
|
appointmentFormModalData.createAppointment,
|
||||||
|
appointmentFormModalData.updateAppointment
|
||||||
|
);
|
||||||
|
|
||||||
if (appointmentFormModalData.isError) {
|
if (appointmentFormModalData.isError) {
|
||||||
return (
|
return (
|
||||||
@ -25,23 +35,23 @@ const AppointmentFormModal = ({visible, onCancel, onSubmit}) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{appointmentFormModalData.isLoading ? (
|
{appointmentFormModalData.isLoading ? (
|
||||||
<LoadingIndicator/>
|
<LoadingIndicator />
|
||||||
) : (
|
) : (
|
||||||
<Modal
|
<Modal
|
||||||
title={appointmentFormModalUI.selectedAppointment ? "Редактировать прием" : "Создать прием"}
|
title={appointmentFormModalUI.selectedAppointment ? "Редактировать прием" : "Создать прием"}
|
||||||
open={appointmentFormModalUI.modalVisible}
|
open={appointmentFormModalUI.modalVisible}
|
||||||
onCancel={appointmentFormModalUI.onCancel}
|
onCancel={appointmentFormModalUI.handleCancel}
|
||||||
footer={null}
|
footer={null}
|
||||||
>
|
>
|
||||||
<Form
|
<Form
|
||||||
form={appointmentFormModalUI.form}
|
form={appointmentFormModalUI.form}
|
||||||
onFinish={appointmentFormModalUI.onFinish}
|
onFinish={appointmentFormModalUI.handleOk}
|
||||||
initialValues={
|
initialValues={
|
||||||
appointmentFormModalUI.selectedAppointment
|
appointmentFormModalUI.selectedAppointment
|
||||||
? {
|
? {
|
||||||
patient_id: appointmentFormModalUI.selectedAppointment.patient_id,
|
patient_id: appointmentFormModalUI.selectedAppointment.patient_id,
|
||||||
type_id: appointmentFormModalUI.selectedAppointment.type_id,
|
type_id: appointmentFormModalUI.selectedAppointment.type_id,
|
||||||
appointmentTime: dayjs(appointmentFormModalUI.selectedAppointment.appointment_datetime).tz('Europe/Moscow'),
|
appointment_datetime: dayjs(appointmentFormModalUI.selectedAppointment.appointment_datetime).tz('Europe/Moscow'),
|
||||||
days_until_the_next_appointment: appointmentFormModalUI.selectedAppointment.days_until_the_next_appointment,
|
days_until_the_next_appointment: appointmentFormModalUI.selectedAppointment.days_until_the_next_appointment,
|
||||||
results: appointmentFormModalUI.selectedAppointment.results,
|
results: appointmentFormModalUI.selectedAppointment.results,
|
||||||
}
|
}
|
||||||
@ -52,13 +62,13 @@ const AppointmentFormModal = ({visible, onCancel, onSubmit}) => {
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
name="patient_id"
|
name="patient_id"
|
||||||
label="Пациент"
|
label="Пациент"
|
||||||
rules={[{required: true, message: 'Выберите пациента'}]}
|
rules={[{ required: true, message: 'Выберите пациента' }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
showSearch
|
showSearch
|
||||||
optionFilterProp="children"
|
optionFilterProp="children"
|
||||||
filterOption={(input, option) =>
|
filterOption={(input, option) =>
|
||||||
option.children.toLowerCase().includes(input.toLowerCase())
|
option.children.join(' ').toLowerCase().includes(input.toLowerCase())
|
||||||
}
|
}
|
||||||
placeholder="Выберите пациента"
|
placeholder="Выберите пациента"
|
||||||
>
|
>
|
||||||
@ -72,12 +82,12 @@ const AppointmentFormModal = ({visible, onCancel, onSubmit}) => {
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
name="type_id"
|
name="type_id"
|
||||||
label="Тип приема"
|
label="Тип приема"
|
||||||
rules={[{required: true, message: 'Выберите тип приема'}]}
|
rules={[{ required: true, message: 'Выберите тип приема' }]}
|
||||||
>
|
>
|
||||||
<Select placeholder="Выберите тип приема">
|
<Select placeholder="Выберите тип приема">
|
||||||
{appointmentFormModalData.appointmentTypes.map(type => (
|
{appointmentFormModalData.appointmentTypes.map(type => (
|
||||||
<Select.Option key={type.id} value={type.id}>
|
<Select.Option key={type.id} value={type.id}>
|
||||||
{type.name}
|
{type.title}
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
@ -85,23 +95,22 @@ const AppointmentFormModal = ({visible, onCancel, onSubmit}) => {
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
name="appointment_datetime"
|
name="appointment_datetime"
|
||||||
label="Время приема"
|
label="Время приема"
|
||||||
rules={[{required: true, message: 'Выберите время'}]}
|
rules={[{ required: true, message: 'Выберите время' }]}
|
||||||
>
|
>
|
||||||
<DatePicker defaultValue={dayjs().tz('Asia/Almaty')} showTime format="DD.MM.YYYY HH:mm"
|
<DatePicker showTime format="DD.MM.YYYY HH:mm" style={{ width: '100%' }} />
|
||||||
style={{width: '100%'}}/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="days_until_the_next_appointment"
|
name="days_until_the_next_appointment"
|
||||||
label="Дней до следующего приема"
|
label="Дней до следующего приема"
|
||||||
rules={[{type: 'number', min: 0, message: 'Введите неотрицательное число'}]}
|
rules={[{ type: 'number', min: 1, message: 'Введите неотрицательное число' }]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} style={{width: '100%'}}/>
|
<InputNumber min={1} defaultValue={1} style={{ width: '100%' }} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="results"
|
name="results"
|
||||||
label="Результаты приема"
|
label="Результаты приема"
|
||||||
>
|
>
|
||||||
<ReactQuill theme="snow"></ReactQuill>
|
<ReactQuill theme="snow" style={{ height: 150, marginBottom: 40 }} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Button type="primary" htmlType="submit">
|
<Button type="primary" htmlType="submit">
|
||||||
|
|||||||
@ -1,27 +1,33 @@
|
|||||||
import {useGetPatientsQuery} from "../../../../../../../Api/patientsApi.js";
|
import {useGetPatientsQuery} from "../../../../../../../Api/patientsApi.js";
|
||||||
import {useGetAppointmentTypesQuery} from "../../../../../../../Api/appointmentTypesApi.js";
|
import {useGetAppointmentTypesQuery} from "../../../../../../../Api/appointmentTypesApi.js";
|
||||||
|
import {useCreateAppointmentMutation, useUpdateAppointmentMutation} from "../../../../../../../Api/appointmentsApi.js";
|
||||||
|
|
||||||
const useAppointmentFormModal = () => {
|
const useAppointmentFormModal = () => {
|
||||||
const {
|
const {
|
||||||
data: patients = [],
|
data: patients = [],
|
||||||
isLoading: isLoadingPatients,
|
isLoading: isLoadingPatients,
|
||||||
isError: isErrorPatients
|
isError: isErrorPatients,
|
||||||
} = useGetPatientsQuery(undefined, {
|
} = useGetPatientsQuery(undefined, {
|
||||||
pollingInterval: 20000,
|
pollingInterval: 20000,
|
||||||
});
|
});
|
||||||
const {
|
const {
|
||||||
data: appointmentTypes = [],
|
data: appointmentTypes = [],
|
||||||
isLoading: isLoadingAppointmentTypes,
|
isLoading: isLoadingAppointmentTypes,
|
||||||
isError: isErrorAppointmentTypes
|
isError: isErrorAppointmentTypes,
|
||||||
} = useGetAppointmentTypesQuery(undefined, {
|
} = useGetAppointmentTypesQuery(undefined, {
|
||||||
pollingInterval: 20000,
|
pollingInterval: 20000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [createAppointment, {isLoading: isCreating, isError: isErrorCreating}] = useCreateAppointmentMutation();
|
||||||
|
const [updateAppointment, {isLoading: isUpdating, isError: isErrorUpdating}] = useUpdateAppointmentMutation();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
patients,
|
patients,
|
||||||
appointmentTypes,
|
appointmentTypes,
|
||||||
isLoading: isLoadingPatients || isLoadingAppointmentTypes,
|
createAppointment,
|
||||||
isError: isErrorPatients || isErrorAppointmentTypes,
|
updateAppointment,
|
||||||
|
isLoading: isLoadingPatients || isLoadingAppointmentTypes || isCreating || isUpdating,
|
||||||
|
isError: isErrorPatients || isErrorAppointmentTypes || isErrorCreating || isErrorUpdating,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,39 +1,97 @@
|
|||||||
import {Form, message, notification} from "antd";
|
import { Form, notification } from "antd";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import {closeModal} from "../../../../../../../Redux/Slices/appointmentsSlice.js";
|
import { closeModal } from "../../../../../../../Redux/Slices/appointmentsSlice.js";
|
||||||
import {useEffect} from "react";
|
import { useEffect } from "react";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import { useGetAppointmentsQuery } from "../../../../../../../Api/appointmentsApi.js";
|
||||||
|
|
||||||
const useAppointmentFormModalUI = (visible, onCancel, onSubmit) => {
|
const useAppointmentFormModalUI = (visible, onCancel, createAppointment, updateAppointment) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
const { modalVisible, selectedAppointment } = useSelector(state => state.appointmentsUI);
|
const { modalVisible, selectedAppointment } = useSelector(state => state.appointmentsUI);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
|
const { data: appointments = [] } = useGetAppointmentsQuery(undefined, {
|
||||||
|
pollingInterval: 20000,
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
if (selectedAppointment) {
|
if (selectedAppointment) {
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
...selectedAppointment,
|
patient_id: selectedAppointment.patient_id,
|
||||||
appointment_datetime: selectedAppointment.appointment_datetime ? dayjs(selectedAppointment.appointment_datetime, "YYYY-MM-DD HH:mm") : null,
|
type_id: selectedAppointment.type_id,
|
||||||
|
appointment_datetime: selectedAppointment.appointment_datetime
|
||||||
|
? dayjs(selectedAppointment.appointment_datetime).tz('Europe/Moscow')
|
||||||
|
: null,
|
||||||
|
days_until_the_next_appointment: selectedAppointment.days_until_the_next_appointment,
|
||||||
|
results: selectedAppointment.results,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, [visible, selectedAppointment, form]);
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
try {
|
try {
|
||||||
const values = await form.validateFields();
|
const values = await form.validateFields();
|
||||||
if (values.birthday) {
|
|
||||||
values.appointment_datetime = values.appointment_datetime.format("YYYY-MM-DD HH:mm");
|
// Проверка пересечения времени
|
||||||
|
const appointmentTime = values.appointment_datetime;
|
||||||
|
const hasConflict = appointments.some(app =>
|
||||||
|
app.id !== selectedAppointment?.id && // Исключаем текущий прием при редактировании
|
||||||
|
dayjs(app.appointment_datetime).tz('Europe/Moscow').isSame(appointmentTime, 'minute')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasConflict) {
|
||||||
|
notification.error({
|
||||||
|
message: 'Конфликт времени',
|
||||||
|
description: 'Выбранное время уже занято другим приемом.',
|
||||||
|
placement: 'topRight',
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
onSubmit(values);
|
|
||||||
|
const data = {
|
||||||
|
patient_id: values.patient_id,
|
||||||
|
type_id: values.type_id,
|
||||||
|
appointment_datetime: appointmentTime.toISOString(),
|
||||||
|
days_until_the_next_appointment: values.days_until_the_next_appointment,
|
||||||
|
results: values.results,
|
||||||
|
doctor_id: localStorage.getItem('doctor_id'),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!data.doctor_id) {
|
||||||
|
notification.error({
|
||||||
|
message: 'Ошибка',
|
||||||
|
description: 'ID доктора не найден. Пожалуйста, войдите в систему.',
|
||||||
|
placement: 'topRight',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedAppointment) {
|
||||||
|
await updateAppointment({ id: selectedAppointment.id, data }).unwrap();
|
||||||
|
notification.success({
|
||||||
|
message: 'Прием обновлен',
|
||||||
|
description: 'Прием успешно обновлен.',
|
||||||
|
placement: 'topRight',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await createAppointment(data).unwrap();
|
||||||
|
notification.success({
|
||||||
|
message: 'Прием создан',
|
||||||
|
description: 'Прием успешно создан.',
|
||||||
|
placement: 'topRight',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(closeModal());
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Validation Failed:", error);
|
|
||||||
notification.error({
|
notification.error({
|
||||||
message: "Ошибка валидации",
|
message: 'Ошибка',
|
||||||
description: "Проверьте правильность заполнения полей.",
|
description: error.data?.message || 'Не удалось сохранить прием.',
|
||||||
placement: "topRight",
|
placement: 'topRight',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
import {useCreateAppointmentMutation, useGetAppointmentsQuery} from "../../../Api/appointmentsApi.js";
|
import { useGetAppointmentsQuery } from "../../../Api/appointmentsApi.js";
|
||||||
import {useGetScheduledAppointmentsQuery} from "../../../Api/scheduledAppointmentsApi.js";
|
import { useGetScheduledAppointmentsQuery } from "../../../Api/scheduledAppointmentsApi.js";
|
||||||
import {useGetPatientsQuery} from "../../../Api/patientsApi.js";
|
import { useGetPatientsQuery } from "../../../Api/patientsApi.js";
|
||||||
import {notification} from "antd";
|
import { notification } from "antd";
|
||||||
import {closeModal} from "../../../Redux/Slices/appointmentsSlice.js";
|
import { useEffect } from "react";
|
||||||
import {useDispatch} from "react-redux";
|
|
||||||
|
|
||||||
const useAppointments = () => {
|
const useAppointments = () => {
|
||||||
const dispatch = useDispatch();
|
|
||||||
const [createAppointment] = useCreateAppointmentMutation();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: appointments = [],
|
data: appointments = [],
|
||||||
isLoading: isLoadingAppointments,
|
isLoading: isLoadingAppointments,
|
||||||
@ -28,45 +24,39 @@ const useAppointments = () => {
|
|||||||
const {
|
const {
|
||||||
data: patients = [],
|
data: patients = [],
|
||||||
isLoading: isLoadingPatients,
|
isLoading: isLoadingPatients,
|
||||||
isError: isErrorPatients
|
isError: isErrorPatients,
|
||||||
} = useGetPatientsQuery(undefined, {
|
} = useGetPatientsQuery(undefined, {
|
||||||
pollingInterval: 20000
|
pollingInterval: 20000,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSubmitModal = async (values) => {
|
useEffect(() => {
|
||||||
try {
|
if (isErrorAppointments) {
|
||||||
const appointmentTime = values.appointmentTime;
|
|
||||||
const data = {
|
|
||||||
patient_id: values.patient_id,
|
|
||||||
type_id: values.type_id,
|
|
||||||
appointment_datetime: appointmentTime.toISOString(),
|
|
||||||
days_until_the_next_appointment: values.days_until_the_next_appointment,
|
|
||||||
results: values.results,
|
|
||||||
doctor_id: localStorage.getItem('doctor_id'),
|
|
||||||
};
|
|
||||||
|
|
||||||
await createAppointment(data).unwrap();
|
|
||||||
|
|
||||||
notification.success({
|
|
||||||
message: 'Прием создан',
|
|
||||||
description: 'Прием успешно создан',
|
|
||||||
placement: 'topRight',
|
|
||||||
});
|
|
||||||
dispatch(closeModal());
|
|
||||||
} catch (error) {
|
|
||||||
notification.error({
|
notification.error({
|
||||||
message: 'Ошибка при создании приема',
|
message: 'Ошибка',
|
||||||
description: error.data?.message || 'Не удалось создать прием',
|
description: 'Ошибка загрузки приемов.',
|
||||||
placement: 'topRight',
|
placement: 'topRight',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
if (isErrorScheduledAppointments) {
|
||||||
|
notification.error({
|
||||||
|
message: 'Ошибка',
|
||||||
|
description: 'Ошибка загрузки запланированных приемов.',
|
||||||
|
placement: 'topRight',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (isErrorPatients) {
|
||||||
|
notification.error({
|
||||||
|
message: 'Ошибка',
|
||||||
|
description: 'Ошибка загрузки пациентов.',
|
||||||
|
placement: 'topRight',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [isErrorAppointments, isErrorScheduledAppointments, isErrorPatients]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
patients,
|
patients,
|
||||||
appointments,
|
appointments,
|
||||||
scheduledAppointments,
|
scheduledAppointments,
|
||||||
handleSubmitModal,
|
|
||||||
isLoading: isLoadingAppointments || isLoadingScheduledAppointments || isLoadingPatients,
|
isLoading: isLoadingAppointments || isLoadingScheduledAppointments || isLoadingPatients,
|
||||||
isError: isErrorAppointments || isErrorScheduledAppointments || isErrorPatients,
|
isError: isErrorAppointments || isErrorScheduledAppointments || isErrorPatients,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import {useDispatch, useSelector} from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import {Grid} from "antd";
|
import { Grid } from "antd";
|
||||||
import {openModal, setHovered, toggleSider} from "../../../Redux/Slices/appointmentsSlice.js";
|
import { setHovered, toggleSider } from "../../../Redux/Slices/appointmentsSlice.js";
|
||||||
import {useEffect, useMemo} from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const {useBreakpoint} = Grid;
|
const { useBreakpoint } = Grid;
|
||||||
|
|
||||||
const useAppointmentsUI = (appointments, scheduledAppointments) => {
|
const useAppointmentsUI = (appointments, scheduledAppointments) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -12,7 +12,6 @@ const useAppointmentsUI = (appointments, scheduledAppointments) => {
|
|||||||
collapsed,
|
collapsed,
|
||||||
siderWidth,
|
siderWidth,
|
||||||
hovered,
|
hovered,
|
||||||
modalVisible,
|
|
||||||
} = useSelector(state => state.appointmentsUI);
|
} = useSelector(state => state.appointmentsUI);
|
||||||
const screens = useBreakpoint();
|
const screens = useBreakpoint();
|
||||||
|
|
||||||
@ -20,10 +19,10 @@ const useAppointmentsUI = (appointments, scheduledAppointments) => {
|
|||||||
document.title = "Приемы";
|
document.title = "Приемы";
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const splitterStyle = {flex: 1};
|
const splitterStyle = { flex: 1 };
|
||||||
const splitterContentPanelStyle = {padding: 16};
|
const splitterContentPanelStyle = { padding: 16 };
|
||||||
const splitterSiderPanelStyle = {padding: "16px", borderLeft: "1px solid #ddd", overflowY: "auto"};
|
const splitterSiderPanelStyle = { padding: "16px", borderLeft: "1px solid #ddd", overflowY: "auto" };
|
||||||
const siderTitleStyle = {marginBottom: 36};
|
const siderTitleStyle = { marginBottom: 36 };
|
||||||
const siderButtonContainerStyle = {
|
const siderButtonContainerStyle = {
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
right: 0,
|
right: 0,
|
||||||
@ -46,9 +45,10 @@ const useAppointmentsUI = (appointments, scheduledAppointments) => {
|
|||||||
const handleHoverSider = () => dispatch(setHovered(true));
|
const handleHoverSider = () => dispatch(setHovered(true));
|
||||||
const handleLeaveSider = () => dispatch(setHovered(false));
|
const handleLeaveSider = () => dispatch(setHovered(false));
|
||||||
|
|
||||||
const openCreateAppointmentModal = () => dispatch(openModal());
|
const openCreateScheduledAppointmentModal = () => {
|
||||||
const handleCloseModal = () => dispatch(openModal(false));
|
// Логика для запланированных приемов будет добавлена позже
|
||||||
const handleModalSubmit = () => dispatch(openModal(false));
|
console.log('Открыть модальное окно для запланированного приема');
|
||||||
|
};
|
||||||
|
|
||||||
const siderButtonText = useMemo(() => hovered ? (collapsed ? "Показать предстоящие события" : "Скрыть предстоящие события") : "", [collapsed, hovered]);
|
const siderButtonText = useMemo(() => hovered ? (collapsed ? "Показать предстоящие события" : "Скрыть предстоящие события") : "", [collapsed, hovered]);
|
||||||
const showSplitterPanel = useMemo(() => !collapsed && !screens.xs, [collapsed, screens]);
|
const showSplitterPanel = useMemo(() => !collapsed && !screens.xs, [collapsed, screens]);
|
||||||
@ -71,13 +71,10 @@ const useAppointmentsUI = (appointments, scheduledAppointments) => {
|
|||||||
siderButtonContainerStyle,
|
siderButtonContainerStyle,
|
||||||
siderButtonStyle,
|
siderButtonStyle,
|
||||||
upcomingEvents,
|
upcomingEvents,
|
||||||
modalVisible,
|
|
||||||
handleToggleSider,
|
handleToggleSider,
|
||||||
handleHoverSider,
|
handleHoverSider,
|
||||||
handleLeaveSider,
|
handleLeaveSider,
|
||||||
openCreateAppointmentModal,
|
openCreateScheduledAppointmentModal,
|
||||||
handleCloseModal,
|
|
||||||
handleModalSubmit,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import {createSlice} from "@reduxjs/toolkit";
|
import { createSlice } from "@reduxjs/toolkit";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
siderWidth: 250,
|
siderWidth: 250,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user