начал переделывать поэтапное создание приема

This commit is contained in:
Андрей Дувакин 2025-06-01 13:30:29 +05:00
parent 89a947cd28
commit 20f754fbc6
2 changed files with 209 additions and 77 deletions

View File

@ -3,17 +3,31 @@ import 'react-quill/dist/quill.snow.css';
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
import { Button, DatePicker, Form, InputNumber, Modal, Result, Select } from "antd";
import {
Button,
Collapse,
DatePicker,
Form,
Input,
InputNumber,
Modal,
Result, Row,
Select,
Spin,
Steps,
Typography
} from "antd";
import useAppointmentFormModal from "./useAppointmentFormModal.js";
import useAppointmentFormModalUI from "./useAppointmentFormModalUI.js";
import LoadingIndicator from "../../../../../../Widgets/LoadingIndicator.jsx";
import { DefaultModalPropType } from "../../../../../../../Types/defaultModalPropType.js";
import {DefaultModalPropType} from "../../../../../../../Types/defaultModalPropType.js";
import {useMemo} from "react";
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.tz.setDefault('Europe/Moscow');
const AppointmentFormModal = ({ visible, onCancel }) => {
const AppointmentFormModal = ({visible, onCancel}) => {
const appointmentFormModalData = useAppointmentFormModal();
const appointmentFormModalUI = useAppointmentFormModalUI(
visible,
@ -32,10 +46,150 @@ const AppointmentFormModal = ({ visible, onCancel }) => {
);
}
const patientsItems = appointmentFormModalData.filteredPatients.map((patient) => ({
key: patient.id,
label: `${patient.last_name} ${patient.first_name} (${appointmentFormModalUI.getDateString(patient.birthday)})`,
children: <div>
<p><b>Пациент:</b> {patient.last_name} {patient.first_name}</p>
<p><b>Дата рождения:</b> {appointmentFormModalUI.getDateString(patient.birthday)}</p>
<p><b>Диагноз:</b> {patient.diagnosis}</p>
<p><b>Email:</b> {patient.email}</p>
<p><b>Телефон:</b> {patient.phone}</p>
<Button type="primary" onClick={() => appointmentFormModalUI.setSelectedPatient(patient)}>Выбрать</Button>
</div>,
}));
const SelectPatientStep = useMemo(() => {
return appointmentFormModalUI.selectedPatient ? (
<div style={appointmentFormModalUI.blockStepStyle}>
<Typography.Text strong>
{appointmentFormModalUI.selectedPatient.last_name} {appointmentFormModalUI.selectedPatient.first_name}
</Typography.Text>
<p><b>Дата
рождения:</b> {appointmentFormModalUI.getSelectedPatientBirthdayString()}
</p>
<p><b>Email:</b> {appointmentFormModalUI.selectedPatient.email}</p>
<p><b>Телефон:</b> {appointmentFormModalUI.selectedPatient.phone}</p>
<Button
type="primary"
onClick={appointmentFormModalUI.resetPatient}
danger
>
Выбрать другого пациента
</Button>
</div>
) : (
<>
<Input
placeholder="Поиск пациента"
value={appointmentFormModalUI.searchPatientString}
onChange={appointmentFormModalUI.handleSetSearchPatientString}
style={appointmentFormModalUI.searchInputStyle}
allowClear
/>
<div style={appointmentFormModalUI.chooseContainerStyle}>
<Collapse
items={patientsItems}
/>
</div>
</>
);
}, [appointmentFormModalUI, patientsItems]);
const AppointmentStep = useMemo(() => {
return (
<Form
form={appointmentFormModalUI.form}
onFinish={appointmentFormModalUI.handleOk}
initialValues={
appointmentFormModalUI.selectedAppointment
? {
patient_id: appointmentFormModalUI.selectedAppointment.patient_id,
type_id: appointmentFormModalUI.selectedAppointment.type_id,
appointment_datetime: dayjs(appointmentFormModalUI.selectedAppointment.appointment_datetime).tz('Europe/Moscow'),
days_until_the_next_appointment: appointmentFormModalUI.selectedAppointment.days_until_the_next_appointment,
results: appointmentFormModalUI.selectedAppointment.results,
}
: {}
}
layout="vertical"
>
<Form.Item
name="patient_id"
label="Пациент"
rules={[{required: true, message: 'Выберите пациента'}]}
>
<Select
showSearch
optionFilterProp="children"
filterOption={(input, option) =>
option.children.join(' ').toLowerCase().includes(input.toLowerCase())
}
placeholder="Выберите пациента"
>
{appointmentFormModalData.patients.map(patient => (
<Select.Option key={patient.id} value={patient.id}>
{patient.last_name} {patient.first_name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
name="type_id"
label="Тип приема"
rules={[{required: true, message: 'Выберите тип приема'}]}
>
<Select placeholder="Выберите тип приема">
{appointmentFormModalData.appointmentTypes.map(type => (
<Select.Option key={type.id} value={type.id}>
{type.title}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
name="appointment_datetime"
label="Время приема"
rules={[{required: true, message: 'Выберите время'}]}
>
<DatePicker showTime format="DD.MM.YYYY HH:mm" style={{width: '100%'}}/>
</Form.Item>
<Form.Item
name="days_until_the_next_appointment"
label="Дней до следующего приема"
rules={[{type: 'number', min: 1, message: 'Введите неотрицательное число'}]}
>
<InputNumber min={1} defaultValue={1} style={{width: '100%'}}/>
</Form.Item>
<Form.Item
name="results"
label="Результаты приема"
>
<ReactQuill theme="snow" style={{height: 150, marginBottom: 40}}/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
{appointmentFormModalUI.selectedAppointment ? 'Сохранить' : 'Создать'}
</Button>
</Form.Item>
</Form>
);
}, [appointmentFormModalData.appointmentTypes, appointmentFormModalData.patients, appointmentFormModalUI.form, appointmentFormModalUI.handleOk, appointmentFormModalUI.selectedAppointment]);
const steps = [{
title: 'Выбор пациента', content: SelectPatientStep,
}, {
title: 'Заполнение информации о приеме', content: AppointmentStep,
}, {
title: 'Подтверждение', content: ConfirmStep,
}];
return (
<>
{appointmentFormModalData.isLoading ? (
<LoadingIndicator />
<LoadingIndicator/>
) : (
<Modal
title={appointmentFormModalUI.selectedAppointment ? "Редактировать прием" : "Создать прием"}
@ -43,81 +197,46 @@ const AppointmentFormModal = ({ visible, onCancel }) => {
onCancel={appointmentFormModalUI.handleCancel}
footer={null}
>
<Form
form={appointmentFormModalUI.form}
onFinish={appointmentFormModalUI.handleOk}
initialValues={
appointmentFormModalUI.selectedAppointment
? {
patient_id: appointmentFormModalUI.selectedAppointment.patient_id,
type_id: appointmentFormModalUI.selectedAppointment.type_id,
appointment_datetime: dayjs(appointmentFormModalUI.selectedAppointment.appointment_datetime).tz('Europe/Moscow'),
days_until_the_next_appointment: appointmentFormModalUI.selectedAppointment.days_until_the_next_appointment,
results: appointmentFormModalUI.selectedAppointment.results,
}
: {}
}
layout="vertical"
{appointmentFormModalData.loading ? (
<div style={appointmentFormModalUI.loadingContainerStyle}>
<Spin size="large"/>
</div>
) : (
<div style={appointmentFormModalUI.stepsContentStyle}>
{steps[appointmentFormModalUI.currentStep].content}
</div>
)}
{!appointmentFormModalUI.screenXS && (
<Steps
current={appointmentFormModalUI.currentStep}
items={steps}
style={appointmentFormModalUI.stepsIndicatorStyle}
direction={appointmentFormModalUI.direction}
/>
)}
<Row
justify="end"
style={appointmentFormModalUI.footerRowStyle}
gutter={[8, 8]}
>
<Form.Item
name="patient_id"
label="Пациент"
rules={[{ required: true, message: 'Выберите пациента' }]}
<Button
style={appointmentFormModalUI.footerButtonStyle}
onClick={appointmentFormModalUI.handleClickBackButton}
disabled={appointmentFormModalUI.disableBackButton}
>
<Select
showSearch
optionFilterProp="children"
filterOption={(input, option) =>
option.children.join(' ').toLowerCase().includes(input.toLowerCase())
}
placeholder="Выберите пациента"
>
{appointmentFormModalData.patients.map(patient => (
<Select.Option key={patient.id} value={patient.id}>
{patient.last_name} {patient.first_name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
name="type_id"
label="Тип приема"
rules={[{ required: true, message: 'Выберите тип приема' }]}
Назад
</Button>
<Button
type="primary"
onClick={appointmentFormModalUI.handleClickNextButton}
disabled={appointmentFormModalUI.disableNextButton}
>
<Select placeholder="Выберите тип приема">
{appointmentFormModalData.appointmentTypes.map(type => (
<Select.Option key={type.id} value={type.id}>
{type.title}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
name="appointment_datetime"
label="Время приема"
rules={[{ required: true, message: 'Выберите время' }]}
>
<DatePicker showTime format="DD.MM.YYYY HH:mm" style={{ width: '100%' }} />
</Form.Item>
<Form.Item
name="days_until_the_next_appointment"
label="Дней до следующего приема"
rules={[{ type: 'number', min: 1, message: 'Введите неотрицательное число' }]}
>
<InputNumber min={1} defaultValue={1} style={{ width: '100%' }} />
</Form.Item>
<Form.Item
name="results"
label="Результаты приема"
>
<ReactQuill theme="snow" style={{ height: 150, marginBottom: 40 }} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
{appointmentFormModalUI.selectedAppointment ? 'Сохранить' : 'Создать'}
</Button>
</Form.Item>
</Form>
{appointmentFormModalUI.nextButtonText}
</Button>
</Row>
</Modal>
)}
</>

View File

@ -1,7 +1,7 @@
import { Form, notification } from "antd";
import { useDispatch, useSelector } from "react-redux";
import { closeModal } from "../../../../../../../Redux/Slices/appointmentsSlice.js";
import { useEffect } from "react";
import {useEffect, useState} from "react";
import dayjs from "dayjs";
import { useGetAppointmentsQuery } from "../../../../../../../Api/appointmentsApi.js";
@ -10,6 +10,15 @@ const useAppointmentFormModalUI = (visible, onCancel, createAppointment, updateA
const { modalVisible, selectedAppointment } = useSelector(state => state.appointmentsUI);
const [form] = Form.useForm();
const [selectedPatient, setSelectedPatient] = useState(null);
const [currentStep, setCurrentStep] = useState(0);
const resetPatient = () => setSelectedPatient(null);
const getDateString = (date) => {
return new Date(date).toLocaleDateString('ru-RU');
};
const { data: appointments = [] } = useGetAppointmentsQuery(undefined, {
pollingInterval: 20000,
});
@ -105,8 +114,12 @@ const useAppointmentFormModalUI = (visible, onCancel, createAppointment, updateA
form,
modalVisible,
selectedAppointment,
selectedPatient,
setSelectedPatient,
handleOk,
handleCancel,
resetPatient,
getDateString,
};
};