вынесс проп-типы в отдельный слой приложения и убрал повторения кода
This commit is contained in:
parent
2372083afe
commit
396aee3ab7
@ -17,7 +17,7 @@ class ScheduledAppointmentsRepository:
|
|||||||
.options(joinedload(ScheduledAppointment.type))
|
.options(joinedload(ScheduledAppointment.type))
|
||||||
.options(joinedload(ScheduledAppointment.patient))
|
.options(joinedload(ScheduledAppointment.patient))
|
||||||
.options(joinedload(ScheduledAppointment.doctor))
|
.options(joinedload(ScheduledAppointment.doctor))
|
||||||
.order_by(desc(ScheduledAppointment.appointment_datetime))
|
.order_by(desc(ScheduledAppointment.scheduled_datetime))
|
||||||
)
|
)
|
||||||
result = await self.db.execute(stmt)
|
result = await self.db.execute(stmt)
|
||||||
return result.scalars().all()
|
return result.scalars().all()
|
||||||
@ -29,7 +29,7 @@ class ScheduledAppointmentsRepository:
|
|||||||
.options(joinedload(ScheduledAppointment.patient))
|
.options(joinedload(ScheduledAppointment.patient))
|
||||||
.options(joinedload(ScheduledAppointment.doctor))
|
.options(joinedload(ScheduledAppointment.doctor))
|
||||||
.filter(ScheduledAppointment.doctor_id == doctor_id)
|
.filter(ScheduledAppointment.doctor_id == doctor_id)
|
||||||
.order_by(desc(ScheduledAppointment.appointment_datetime))
|
.order_by(desc(ScheduledAppointment.scheduled_datetime))
|
||||||
)
|
)
|
||||||
result = await self.db.execute(stmt)
|
result = await self.db.execute(stmt)
|
||||||
return result.scalars().all()
|
return result.scalars().all()
|
||||||
@ -41,7 +41,7 @@ class ScheduledAppointmentsRepository:
|
|||||||
.options(joinedload(ScheduledAppointment.patient))
|
.options(joinedload(ScheduledAppointment.patient))
|
||||||
.options(joinedload(ScheduledAppointment.doctor))
|
.options(joinedload(ScheduledAppointment.doctor))
|
||||||
.filter(ScheduledAppointment.patient_id == patient_id)
|
.filter(ScheduledAppointment.patient_id == patient_id)
|
||||||
.order_by(desc(ScheduledAppointment.appointment_datetime))
|
.order_by(desc(ScheduledAppointment.scheduled_datetime))
|
||||||
)
|
)
|
||||||
result = await self.db.execute(stmt)
|
result = await self.db.execute(stmt)
|
||||||
return result.scalars().all()
|
return result.scalars().all()
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import {BuildOutlined, TableOutlined} from "@ant-design/icons";
|
|||||||
import {Select, Tooltip} from "antd";
|
import {Select, Tooltip} from "antd";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import {cacheInfo} from "../utils/cachedInfoUtils.jsx";
|
import {cacheInfo} from "../utils/cachedInfoUtils.jsx";
|
||||||
|
import {ViewModPropType} from "../types/viewModPropType.jsx";
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
@ -35,11 +36,7 @@ SelectViewMode.propTypes = {
|
|||||||
setViewMode: PropTypes.func.isRequired,
|
setViewMode: PropTypes.func.isRequired,
|
||||||
localStorageKey: PropTypes.string.isRequired,
|
localStorageKey: PropTypes.string.isRequired,
|
||||||
toolTipText: PropTypes.string.isRequired,
|
toolTipText: PropTypes.string.isRequired,
|
||||||
viewModes: PropTypes.arrayOf(PropTypes.shape({
|
viewModes: PropTypes.arrayOf(ViewModPropType).isRequired,
|
||||||
value: PropTypes.string.isRequired,
|
|
||||||
label: PropTypes.string.isRequired,
|
|
||||||
icon: PropTypes.element,
|
|
||||||
})).isRequired,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SelectViewMode;
|
export default SelectViewMode;
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const AppointmentCellViewModal = ({appointment}) => {
|
||||||
|
|
||||||
|
};
|
||||||
109
web-app/src/components/appointments/CalendarCell.jsx
Normal file
109
web-app/src/components/appointments/CalendarCell.jsx
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import {useEffect, useRef, useState} from "react";
|
||||||
|
import {Badge, Col, Tag, Tooltip, Typography} from "antd";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import {AppointmentPropType} from "../../types/appointmentPropType.jsx";
|
||||||
|
import {ScheduledAppointmentPropType} from "../../types/scheduledAppointmentPropType.jsx";
|
||||||
|
|
||||||
|
|
||||||
|
const CalendarCell = ({appointments, scheduledAppointments, onCellClick, onItemClick}) => {
|
||||||
|
const containerRef = useRef(null);
|
||||||
|
const [isCompressed, setIsCompressed] = useState(false);
|
||||||
|
const COMPRESSION_THRESHOLD = 70;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!containerRef.current) return;
|
||||||
|
|
||||||
|
const observer = new ResizeObserver((entries) => {
|
||||||
|
const width = entries[0].contentRect.width;
|
||||||
|
setIsCompressed(width < COMPRESSION_THRESHOLD);
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(containerRef.current);
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={containerRef}
|
||||||
|
onClick={isCompressed ? onCellClick : undefined}
|
||||||
|
style={{
|
||||||
|
height: '100%',
|
||||||
|
cursor: isCompressed ? 'pointer' : 'default',
|
||||||
|
position: 'relative',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{!isCompressed && (
|
||||||
|
<ul style={{padding: 0, margin: 0}}>
|
||||||
|
{appointments.map(app => (
|
||||||
|
<Col
|
||||||
|
key={app.id}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
title={`Прошедший прием: ${dayjs(app.appointment_datetime).format('HH:mm')}`}
|
||||||
|
>
|
||||||
|
<Tag
|
||||||
|
color="green"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onItemClick(app);
|
||||||
|
}}
|
||||||
|
style={{margin: '2px 0', cursor: 'pointer'}}
|
||||||
|
>
|
||||||
|
<Badge
|
||||||
|
status="success"
|
||||||
|
text={dayjs(app.appointment_datetime).format('HH:mm')}
|
||||||
|
/>
|
||||||
|
</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
{scheduledAppointments.map(app => (
|
||||||
|
<Col
|
||||||
|
key={app.id}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
title={`Запланированный прием: ${dayjs(app.scheduled_datetime).format('HH:mm')}`}
|
||||||
|
>
|
||||||
|
<Tag
|
||||||
|
color="blue"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onItemClick(app);
|
||||||
|
}}
|
||||||
|
style={{margin: '2px 0', cursor: 'pointer'}}
|
||||||
|
>
|
||||||
|
<Badge
|
||||||
|
status="processing"
|
||||||
|
text={dayjs(app.scheduled_datetime).format('HH:mm')}
|
||||||
|
/>
|
||||||
|
</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
{isCompressed && (
|
||||||
|
<div style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 2,
|
||||||
|
right: 2,
|
||||||
|
fontSize: 10,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#1890ff'
|
||||||
|
}}>
|
||||||
|
{appointments.length + scheduledAppointments.length > 0 && `+${appointments.length + scheduledAppointments.length}`}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
CalendarCell.propTypes = {
|
||||||
|
appointments: PropTypes.arrayOf(AppointmentPropType).isRequired,
|
||||||
|
scheduledAppointments: PropTypes.arrayOf(ScheduledAppointmentPropType).isRequired,
|
||||||
|
onCellClick: PropTypes.func.isRequired,
|
||||||
|
onItemClick: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CalendarCell;
|
||||||
@ -36,27 +36,13 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => {
|
|||||||
}, [visible]);
|
}, [visible]);
|
||||||
|
|
||||||
const fetchPatients = async () => {
|
const fetchPatients = async () => {
|
||||||
try {
|
|
||||||
const data = await getAllPatients(api);
|
const data = await getAllPatients(api);
|
||||||
setPatients(data);
|
setPatients(data);
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки пациентов", description: "Проверьте подключение к сети.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchLenses = async () => {
|
const fetchLenses = async () => {
|
||||||
try {
|
|
||||||
const data = await getNotIssuedLenses(api);
|
const data = await getNotIssuedLenses(api);
|
||||||
setLenses(data);
|
setLenses(data);
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки линз", description: "Проверьте подключение к сети.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
@ -324,7 +310,9 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
LensIssueFormModal.propTypes = {
|
LensIssueFormModal.propTypes = {
|
||||||
visible: PropTypes.bool.isRequired, onCancel: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired,
|
visible: PropTypes.bool.isRequired,
|
||||||
|
onCancel: PropTypes.func.isRequired,
|
||||||
|
onSubmit: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LensIssueFormModal;
|
export default LensIssueFormModal;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import {Collapse, Modal} from "antd";
|
import {Collapse, Modal} from "antd";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
|
import {LensIssuePropType} from "../../types/lensIssuePropType.jsx";
|
||||||
|
|
||||||
|
|
||||||
const LensIssueViewModal = ({visible, onCancel, lensIssue}) => {
|
const LensIssueViewModal = ({visible, onCancel, lensIssue}) => {
|
||||||
@ -69,39 +70,9 @@ const LensIssueViewModal = ({visible, onCancel, lensIssue}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
LensIssueViewModal.propTypes = {
|
LensIssueViewModal.propTypes = {
|
||||||
visible: PropTypes.bool,
|
visible: PropTypes.bool.isRequired,
|
||||||
onCancel: PropTypes.func,
|
onCancel: PropTypes.func.isRequired,
|
||||||
lensIssue: PropTypes.shape({
|
lensIssue: LensIssuePropType.isRequired,
|
||||||
issue_date: PropTypes.string,
|
|
||||||
patient: PropTypes.shape({
|
|
||||||
first_name: PropTypes.string,
|
|
||||||
last_name: PropTypes.string,
|
|
||||||
patronymic: PropTypes.string,
|
|
||||||
birthday: PropTypes.string,
|
|
||||||
address: PropTypes.string,
|
|
||||||
email: PropTypes.string,
|
|
||||||
phone: PropTypes.string,
|
|
||||||
diagnosis: PropTypes.string,
|
|
||||||
correction: PropTypes.string,
|
|
||||||
}),
|
|
||||||
doctor: PropTypes.shape({
|
|
||||||
last_name: PropTypes.string,
|
|
||||||
first_name: PropTypes.string,
|
|
||||||
login: PropTypes.string,
|
|
||||||
}),
|
|
||||||
lens: PropTypes.shape({
|
|
||||||
id: PropTypes.number.isRequired,
|
|
||||||
tor: PropTypes.number.isRequired,
|
|
||||||
diameter: PropTypes.number.isRequired,
|
|
||||||
esa: PropTypes.number.isRequired,
|
|
||||||
fvc: PropTypes.number.isRequired,
|
|
||||||
preset_refraction: PropTypes.number.isRequired,
|
|
||||||
periphery_toricity: PropTypes.number.isRequired,
|
|
||||||
side: PropTypes.string.isRequired,
|
|
||||||
issued: PropTypes.bool.isRequired,
|
|
||||||
trial: PropTypes.number.isRequired,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LensIssueViewModal;
|
export default LensIssueViewModal;
|
||||||
@ -3,6 +3,7 @@ import {useEffect, useState} from "react";
|
|||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import getAllLensTypes from "../../api/lens_types/getAllLensTypes.jsx";
|
import getAllLensTypes from "../../api/lens_types/getAllLensTypes.jsx";
|
||||||
import {useAuth} from "../../AuthContext.jsx";
|
import {useAuth} from "../../AuthContext.jsx";
|
||||||
|
import {LensPropType} from "../../types/lensPropType.jsx";
|
||||||
|
|
||||||
|
|
||||||
const LensFormModal = ({visible, onCancel, onSubmit, lens}) => {
|
const LensFormModal = ({visible, onCancel, onSubmit, lens}) => {
|
||||||
@ -26,17 +27,8 @@ const LensFormModal = ({visible, onCancel, onSubmit, lens}) => {
|
|||||||
}, [visible, lens]);
|
}, [visible, lens]);
|
||||||
|
|
||||||
const fetchLensTypes = async () => {
|
const fetchLensTypes = async () => {
|
||||||
try {
|
|
||||||
const data = await getAllLensTypes(api);
|
const data = await getAllLensTypes(api);
|
||||||
setLensTypes(data);
|
setLensTypes(data);
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки типов линз",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
@ -199,18 +191,7 @@ LensFormModal.propTypes = {
|
|||||||
visible: PropTypes.bool.isRequired,
|
visible: PropTypes.bool.isRequired,
|
||||||
onCancel: PropTypes.func.isRequired,
|
onCancel: PropTypes.func.isRequired,
|
||||||
onSubmit: PropTypes.func.isRequired,
|
onSubmit: PropTypes.func.isRequired,
|
||||||
lens: PropTypes.shape({
|
lens: LensPropType.isRequired,
|
||||||
tor: PropTypes.number.isRequired,
|
|
||||||
trial: PropTypes.number.isRequired,
|
|
||||||
esa: PropTypes.number.isRequired,
|
|
||||||
fvc: PropTypes.number.isRequired,
|
|
||||||
preset_refraction: PropTypes.number.isRequired,
|
|
||||||
diameter: PropTypes.number.isRequired,
|
|
||||||
periphery_toricity: PropTypes.number.isRequired,
|
|
||||||
side: PropTypes.string.isRequired,
|
|
||||||
issued: PropTypes.bool.isRequired,
|
|
||||||
type_id: PropTypes.number.isRequired,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LensFormModal;
|
export default LensFormModal;
|
||||||
@ -3,6 +3,7 @@ import PropTypes from "prop-types";
|
|||||||
import {DeleteOutlined, EditOutlined, EyeOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, EditOutlined, EyeOutlined} from "@ant-design/icons";
|
||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
import LensViewModal from "./LensViewModal.jsx";
|
import LensViewModal from "./LensViewModal.jsx";
|
||||||
|
import {LensPropType} from "../../types/lensPropType.jsx";
|
||||||
|
|
||||||
const LensListCard = ({lens, handleEditLens, handleDeleteLens}) => {
|
const LensListCard = ({lens, handleEditLens, handleDeleteLens}) => {
|
||||||
const [showModalInfo, setShowModalInfo] = useState(false);
|
const [showModalInfo, setShowModalInfo] = useState(false);
|
||||||
@ -61,18 +62,7 @@ const LensListCard = ({lens, handleEditLens, handleDeleteLens}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
LensListCard.propTypes = {
|
LensListCard.propTypes = {
|
||||||
lens: PropTypes.shape({
|
lens: LensPropType.isRequired,
|
||||||
id: PropTypes.number.isRequired,
|
|
||||||
tor: PropTypes.number.isRequired,
|
|
||||||
trial: PropTypes.number,
|
|
||||||
esa: PropTypes.number,
|
|
||||||
fvc: PropTypes.number,
|
|
||||||
preset_refraction: PropTypes.number.isRequired,
|
|
||||||
diameter: PropTypes.number.isRequired,
|
|
||||||
periphery_toricity: PropTypes.number.isRequired,
|
|
||||||
side: PropTypes.string.isRequired,
|
|
||||||
issued: PropTypes.bool.isRequired,
|
|
||||||
}).isRequired,
|
|
||||||
handleEditLens: PropTypes.func.isRequired,
|
handleEditLens: PropTypes.func.isRequired,
|
||||||
handleDeleteLens: PropTypes.func.isRequired,
|
handleDeleteLens: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import {Button, Col, Modal, Row, Typography} from "antd";
|
import {Button, Col, Modal, Row, Typography} from "antd";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
|
import {LensPropType} from "../../types/lensPropType.jsx";
|
||||||
|
|
||||||
const {Text, Title} = Typography;
|
const {Text, Title} = Typography;
|
||||||
|
|
||||||
@ -72,17 +73,7 @@ const LensViewModal = ({visible, onCancel, lens}) => {
|
|||||||
LensViewModal.propTypes = {
|
LensViewModal.propTypes = {
|
||||||
visible: PropTypes.bool.isRequired,
|
visible: PropTypes.bool.isRequired,
|
||||||
onCancel: PropTypes.func.isRequired,
|
onCancel: PropTypes.func.isRequired,
|
||||||
lens: PropTypes.shape({
|
lens: LensPropType.isRequired,
|
||||||
tor: PropTypes.number.isRequired,
|
|
||||||
diameter: PropTypes.number.isRequired,
|
|
||||||
esa: PropTypes.number.isRequired,
|
|
||||||
fvc: PropTypes.number.isRequired,
|
|
||||||
preset_refraction: PropTypes.number.isRequired,
|
|
||||||
periphery_toricity: PropTypes.number.isRequired,
|
|
||||||
side: PropTypes.string.isRequired,
|
|
||||||
issued: PropTypes.bool.isRequired,
|
|
||||||
trial: PropTypes.number.isRequired,
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LensViewModal;
|
export default LensViewModal;
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import locale from "antd/es/date-picker/locale/ru_RU";
|
|||||||
import validator from "validator";
|
import validator from "validator";
|
||||||
import {MaskedInput} from "antd-mask-input";
|
import {MaskedInput} from "antd-mask-input";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import {PatientPropType} from "../../types/patientPropType.jsx";
|
||||||
|
|
||||||
const {TextArea} = Input;
|
const {TextArea} = Input;
|
||||||
|
|
||||||
@ -141,17 +142,7 @@ PatientFormModal.propTypes = {
|
|||||||
visible: PropTypes.bool.isRequired,
|
visible: PropTypes.bool.isRequired,
|
||||||
onCancel: PropTypes.func.isRequired,
|
onCancel: PropTypes.func.isRequired,
|
||||||
onSubmit: PropTypes.func.isRequired,
|
onSubmit: PropTypes.func.isRequired,
|
||||||
patient: PropTypes.shape({
|
patient: PatientPropType.isRequired,
|
||||||
first_name: PropTypes.string,
|
|
||||||
last_name: PropTypes.string,
|
|
||||||
patronymic: PropTypes.string,
|
|
||||||
birthday: PropTypes.string,
|
|
||||||
address: PropTypes.string,
|
|
||||||
email: PropTypes.string,
|
|
||||||
phone: PropTypes.string,
|
|
||||||
diagnosis: PropTypes.string,
|
|
||||||
correction: PropTypes.string,
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PatientFormModal;
|
export default PatientFormModal;
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import PropTypes from "prop-types";
|
|||||||
import {DeleteOutlined, EditOutlined, EyeOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, EditOutlined, EyeOutlined} from "@ant-design/icons";
|
||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
import PatientViewModal from "./PatientViewModal.jsx";
|
import PatientViewModal from "./PatientViewModal.jsx";
|
||||||
|
import {PatientPropType} from "../../types/patientPropType.jsx";
|
||||||
|
|
||||||
const PatientListCard = ({patient, handleEditPatient, handleDeletePatient}) => {
|
const PatientListCard = ({patient, handleEditPatient, handleDeletePatient}) => {
|
||||||
const [showModalInfo, setShowModalInfo] = useState(false);
|
const [showModalInfo, setShowModalInfo] = useState(false);
|
||||||
@ -73,18 +74,7 @@ const PatientListCard = ({patient, handleEditPatient, handleDeletePatient}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PatientListCard.propTypes = {
|
PatientListCard.propTypes = {
|
||||||
patient: PropTypes.shape({
|
patient: PatientPropType.isRequired,
|
||||||
id: PropTypes.number.isRequired,
|
|
||||||
last_name: PropTypes.string.isRequired,
|
|
||||||
first_name: PropTypes.string.isRequired,
|
|
||||||
patronymic: PropTypes.string,
|
|
||||||
birthday: PropTypes.string.isRequired,
|
|
||||||
address: PropTypes.string,
|
|
||||||
email: PropTypes.string,
|
|
||||||
phone: PropTypes.string,
|
|
||||||
diagnosis: PropTypes.string,
|
|
||||||
correction: PropTypes.string,
|
|
||||||
}).isRequired,
|
|
||||||
handleEditPatient: PropTypes.func.isRequired,
|
handleEditPatient: PropTypes.func.isRequired,
|
||||||
handleDeletePatient: PropTypes.func.isRequired,
|
handleDeletePatient: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import {Button, Col, Modal, Row, Typography, Divider} from "antd";
|
import {Button, Col, Modal, Row, Typography, Divider} from "antd";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
|
import {PatientPropType} from "../../types/patientPropType.jsx";
|
||||||
|
|
||||||
const { Text, Title } = Typography;
|
const { Text, Title } = Typography;
|
||||||
|
|
||||||
@ -72,17 +73,7 @@ const PatientViewModal = ({ visible, onCancel, patient }) => {
|
|||||||
PatientViewModal.propTypes = {
|
PatientViewModal.propTypes = {
|
||||||
visible: PropTypes.bool.isRequired,
|
visible: PropTypes.bool.isRequired,
|
||||||
onCancel: PropTypes.func.isRequired,
|
onCancel: PropTypes.func.isRequired,
|
||||||
patient: PropTypes.shape({
|
patient: PatientPropType.isRequired,
|
||||||
first_name: PropTypes.string,
|
|
||||||
last_name: PropTypes.string,
|
|
||||||
patronymic: PropTypes.string,
|
|
||||||
birthday: PropTypes.string,
|
|
||||||
address: PropTypes.string,
|
|
||||||
email: PropTypes.string,
|
|
||||||
phone: PropTypes.string,
|
|
||||||
diagnosis: PropTypes.string,
|
|
||||||
correction: PropTypes.string,
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PatientViewModal;
|
export default PatientViewModal;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import getAllLensTypes from "../../api/lens_types/getAllLensTypes.jsx";
|
|||||||
import {useAuth} from "../../AuthContext.jsx";
|
import {useAuth} from "../../AuthContext.jsx";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import getSetContentBySetId from "../../api/set_content/getSetContentBySetId.jsx";
|
import getSetContentBySetId from "../../api/set_content/getSetContentBySetId.jsx";
|
||||||
|
import {SetPropType} from "../../types/setPropType.jsx";
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
@ -32,31 +33,13 @@ const SetFormModal = ({visible, onCancel, setData, onSubmit}) => {
|
|||||||
const fetchSetContents = async () => {
|
const fetchSetContents = async () => {
|
||||||
if (!setData) return;
|
if (!setData) return;
|
||||||
|
|
||||||
try {
|
|
||||||
const data = await getSetContentBySetId(api, setData.id);
|
const data = await getSetContentBySetId(api, setData.id);
|
||||||
setContent(data);
|
setContent(data);
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки контента",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchLensTypes = async () => {
|
const fetchLensTypes = async () => {
|
||||||
try {
|
|
||||||
const data = await getAllLensTypes(api);
|
const data = await getAllLensTypes(api);
|
||||||
setLensTypes(data);
|
setLensTypes(data);
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки типов линз",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const addContentItem = () => {
|
const addContentItem = () => {
|
||||||
@ -272,10 +255,7 @@ SetFormModal.propTypes = {
|
|||||||
visible: PropTypes.bool.isRequired,
|
visible: PropTypes.bool.isRequired,
|
||||||
onCancel: PropTypes.func.isRequired,
|
onCancel: PropTypes.func.isRequired,
|
||||||
onSubmit: PropTypes.func.isRequired,
|
onSubmit: PropTypes.func.isRequired,
|
||||||
setData: PropTypes.shape({
|
setData: SetPropType.isRequired,
|
||||||
id: PropTypes.number,
|
|
||||||
title: PropTypes.string,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SetFormModal;
|
export default SetFormModal;
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import {Card, Modal, Popconfirm, Tooltip} from "antd";
|
import {Card, Modal, Popconfirm, Tooltip} from "antd";
|
||||||
import {DeleteOutlined, EditOutlined, PlusOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, EditOutlined, PlusOutlined} from "@ant-design/icons";
|
||||||
|
import {SetPropType} from "../../types/setPropType.jsx";
|
||||||
|
|
||||||
const SetListCard = ({set, handleEditSet, handleDeleteSet, handleAppendSet}) => {
|
const SetListCard = ({set, handleEditSet, handleDeleteSet, handleAppendSet}) => {
|
||||||
const deleteSet = () => {
|
const deleteSet = () => {
|
||||||
@ -59,10 +60,7 @@ const SetListCard = ({set, handleEditSet, handleDeleteSet, handleAppendSet}) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
SetListCard.propTypes = {
|
SetListCard.propTypes = {
|
||||||
set: PropTypes.shape({
|
set: SetPropType.isRequired,
|
||||||
id: PropTypes.number.isRequired,
|
|
||||||
title: PropTypes.string.isRequired,
|
|
||||||
}).isRequired,
|
|
||||||
handleEditSet: PropTypes.func.isRequired,
|
handleEditSet: PropTypes.func.isRequired,
|
||||||
handleAppendSet: PropTypes.func.isRequired,
|
handleAppendSet: PropTypes.func.isRequired,
|
||||||
handleDeleteSet: PropTypes.func.isRequired,
|
handleDeleteSet: PropTypes.func.isRequired,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import {Button, Grid, notification, Tabs, Typography} from "antd";
|
import {Button, Grid, Tabs, Typography} from "antd";
|
||||||
import {Splitter} from "antd";
|
import {Splitter} from "antd";
|
||||||
import {
|
import {
|
||||||
CalendarOutlined, TableOutlined, MenuFoldOutlined, MenuUnfoldOutlined,
|
CalendarOutlined, TableOutlined, MenuFoldOutlined, MenuUnfoldOutlined,
|
||||||
@ -62,17 +62,9 @@ const AppointmentsLayout = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fetchAppointments = async () => {
|
const fetchAppointments = async () => {
|
||||||
try {
|
|
||||||
const data = await getAllAppointments(api);
|
const data = await getAllAppointments(api);
|
||||||
setAppointments(data);
|
setAppointments(data);
|
||||||
|
|
||||||
cacheInfo("appointmentsData", data);
|
cacheInfo("appointmentsData", data);
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки данных", description: "Проверьте подключение к сети.", placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchScheduledAppointmentsWithCache = async () => {
|
const fetchScheduledAppointmentsWithCache = async () => {
|
||||||
@ -88,17 +80,9 @@ const AppointmentsLayout = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fetchScheduledAppointments = async () => {
|
const fetchScheduledAppointments = async () => {
|
||||||
try {
|
|
||||||
const data = await getAllScheduledAppointments(api);
|
const data = await getAllScheduledAppointments(api);
|
||||||
setScheduledAppointments(data);
|
setScheduledAppointments(data);
|
||||||
|
|
||||||
cacheInfo("scheduledAppointmentsData", data);
|
cacheInfo("scheduledAppointmentsData", data);
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки данных", description: "Проверьте подключение к сети.", placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const items = [{
|
const items = [{
|
||||||
|
|||||||
@ -92,39 +92,20 @@ const IssuesPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmitFormModal = async (issue_date, patient_id, lens_id) => {
|
const handleSubmitFormModal = async (issue_date, patient_id, lens_id) => {
|
||||||
try {
|
|
||||||
await addLensIssue(api, {issue_date, patient_id, lens_id});
|
|
||||||
setIsModalVisible(false);
|
setIsModalVisible(false);
|
||||||
|
await addLensIssue(api, {issue_date, patient_id, lens_id});
|
||||||
notification.success({
|
notification.success({
|
||||||
message: "Линза выдана",
|
message: "Линза выдана",
|
||||||
description: "Линза успешно выдана пациенту.",
|
description: "Линза успешно выдана пациенту.",
|
||||||
placement: "topRight",
|
placement: "topRight",
|
||||||
});
|
});
|
||||||
await fetchLensIssues();
|
await fetchLensIssues();
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка добавления",
|
|
||||||
description: "Не удалось выдать линзу пациенту.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchLensIssues = async () => {
|
const fetchLensIssues = async () => {
|
||||||
try {
|
|
||||||
const data = await getAllLensIssues(api);
|
const data = await getAllLensIssues(api);
|
||||||
setLensIssues(data);
|
setLensIssues(data);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки данных",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearch = (e) => {
|
const handleSearch = (e) => {
|
||||||
|
|||||||
@ -75,20 +75,10 @@ const PatientsPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fetchPatients = async () => {
|
const fetchPatients = async () => {
|
||||||
try {
|
|
||||||
const data = await getAllPatients(api);
|
const data = await getAllPatients(api);
|
||||||
setPatients(data);
|
setPatients(data);
|
||||||
|
|
||||||
cacheInfo("patientsData", data);
|
cacheInfo("patientsData", data);
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки данных",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -124,7 +114,6 @@ const PatientsPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDeletePatient = async (patient_id) => {
|
const handleDeletePatient = async (patient_id) => {
|
||||||
try {
|
|
||||||
await deletePatient(api, patient_id);
|
await deletePatient(api, patient_id);
|
||||||
await fetchPatients();
|
await fetchPatients();
|
||||||
notification.success({
|
notification.success({
|
||||||
@ -132,14 +121,6 @@ const PatientsPage = () => {
|
|||||||
description: "Пациент успешно удалён из базы.",
|
description: "Пациент успешно удалён из базы.",
|
||||||
placement: "topRight",
|
placement: "topRight",
|
||||||
});
|
});
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка удаления",
|
|
||||||
description: "Не удалось удалить пациента.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
@ -147,24 +128,14 @@ const PatientsPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleModalPatientSubmit = async (newPatient) => {
|
const handleModalPatientSubmit = async (newPatient) => {
|
||||||
try {
|
setIsModalVisible(false);
|
||||||
|
|
||||||
if (selectedPatient) {
|
if (selectedPatient) {
|
||||||
await editPatient(newPatient);
|
await editPatient(newPatient);
|
||||||
} else {
|
} else {
|
||||||
await addNewPatient(newPatient);
|
await addNewPatient(newPatient);
|
||||||
}
|
}
|
||||||
setIsModalVisible(false);
|
|
||||||
await fetchPatients();
|
await fetchPatients();
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка",
|
|
||||||
description: error.response?.status === 401
|
|
||||||
? "Ошибка авторизации: пользователь не найден или токен недействителен"
|
|
||||||
: "Не удалось сохранить данные пациента.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const editPatient = async (patient) => {
|
const editPatient = async (patient) => {
|
||||||
@ -330,6 +301,7 @@ const PatientsPage = () => {
|
|||||||
allowClear
|
allowClear
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
{viewMode === "tile" && (
|
{viewMode === "tile" && (
|
||||||
<Col xs={24} md={5} sm={6} xl={3} xxl={2}>
|
<Col xs={24} md={5} sm={6} xl={3} xxl={2}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
import {Calendar, Grid, ConfigProvider, Badge, Modal} from "antd";
|
import {Calendar, Grid, ConfigProvider, Badge, Modal, Tag, Tooltip} from "antd";
|
||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import 'dayjs/locale/ru';
|
import 'dayjs/locale/ru';
|
||||||
import locale from 'antd/es/locale/ru_RU';
|
import locale from 'antd/es/locale/ru_RU';
|
||||||
import updateLocale from 'dayjs/plugin/updateLocale';
|
import updateLocale from 'dayjs/plugin/updateLocale';
|
||||||
import PropTypes from "prop-types";
|
import PropTypes, {arrayOf} from "prop-types";
|
||||||
|
import CalendarCell from "../../components/appointments/CalendarCell.jsx";
|
||||||
|
import {AppointmentPropType} from "../../types/appointmentPropType.jsx";
|
||||||
|
import {ScheduledAppointmentPropType} from "../../types/scheduledAppointmentPropType.jsx";
|
||||||
|
|
||||||
const {useBreakpoint} = Grid;
|
const {useBreakpoint} = Grid;
|
||||||
|
|
||||||
@ -18,6 +21,7 @@ const AppointmentsCalendarPage = ({appointments, scheduledAppointments}) => {
|
|||||||
const [selectedDate, setSelectedDate] = useState(dayjs(new Date()));
|
const [selectedDate, setSelectedDate] = useState(dayjs(new Date()));
|
||||||
const [modalVisible, setModalVisible] = useState(false);
|
const [modalVisible, setModalVisible] = useState(false);
|
||||||
const [selectedAppointments, setSelectedAppointments] = useState([]);
|
const [selectedAppointments, setSelectedAppointments] = useState([]);
|
||||||
|
const [selectedAppointment, setSelectedAppointment] = useState(null);
|
||||||
|
|
||||||
const dateCellRender = (value) => {
|
const dateCellRender = (value) => {
|
||||||
const date = value.format('YYYY-MM-DD');
|
const date = value.format('YYYY-MM-DD');
|
||||||
@ -29,19 +33,14 @@ const AppointmentsCalendarPage = ({appointments, scheduledAppointments}) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul style={{listStyle: 'none', padding: 0}}>
|
<CalendarCell
|
||||||
{appointmentsForDate.map(app => (
|
appointments={appointmentsForDate}
|
||||||
<li key={app.id}>
|
scheduledAppointments={scheduledForDate}
|
||||||
<Badge status="success" text={`Прием ${dayjs(app.appointment_datetime).format('HH:mm')}`}/>
|
onCellClick={() => {
|
||||||
</li>
|
}}
|
||||||
))}
|
onItemClick={() => {
|
||||||
{scheduledForDate.map(app => (
|
}}
|
||||||
<li key={app.id}>
|
/>
|
||||||
<Badge status="processing"
|
|
||||||
text={`Запланировано ${dayjs(app.scheduled_datetime).format('HH:mm')}`}/>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,83 +66,15 @@ const AppointmentsCalendarPage = ({appointments, scheduledAppointments}) => {
|
|||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
cellRender={dateCellRender}
|
cellRender={dateCellRender}
|
||||||
/>
|
/>
|
||||||
<Modal
|
|
||||||
title={`Приемы на ${selectedDate.format('DD.MM.YYYY')}`}
|
|
||||||
open={modalVisible}
|
|
||||||
onCancel={() => setModalVisible(false)}
|
|
||||||
footer={null}
|
|
||||||
>
|
|
||||||
{selectedAppointments.map(app => (
|
|
||||||
<div key={app.id}>
|
|
||||||
<p>{app.appointment_datetime ? 'Прием' : 'Запланировано'}: {dayjs(app.appointment_datetime || app.scheduled_datetime).format('HH:mm')}</p>
|
|
||||||
<p>Пациент: {app.patient?.name || 'Не указан'}</p>
|
|
||||||
<p>Врач: {app.doctor?.name || 'Не указан'}</p>
|
|
||||||
<p>Тип: {app.type?.name || 'Не указан'}</p>
|
|
||||||
{app.results && <p>Результаты: {app.results}</p>}
|
|
||||||
<hr/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</Modal>
|
|
||||||
</div>
|
</div>
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
AppointmentsCalendarPage.propTypes = {
|
AppointmentsCalendarPage.propTypes = {
|
||||||
appointments: PropTypes.arrayOf(
|
appointments: PropTypes.arrayOf(AppointmentPropType).isRequired,
|
||||||
PropTypes.shape({
|
scheduledAppointments: PropTypes.arrayOf(ScheduledAppointmentPropType).isRequired,
|
||||||
id: PropTypes.number.isRequired,
|
|
||||||
results: PropTypes.string,
|
|
||||||
days_until_the_next_appointment: PropTypes.number,
|
|
||||||
appointment_datetime: PropTypes.string.isRequired,
|
|
||||||
patient: PropTypes.shape({
|
|
||||||
first_name: PropTypes.string,
|
|
||||||
last_name: PropTypes.string,
|
|
||||||
patronymic: PropTypes.string,
|
|
||||||
birthday: PropTypes.string,
|
|
||||||
address: PropTypes.string,
|
|
||||||
email: PropTypes.string,
|
|
||||||
phone: PropTypes.string,
|
|
||||||
diagnosis: PropTypes.string,
|
|
||||||
correction: PropTypes.string,
|
|
||||||
}),
|
|
||||||
doctor: PropTypes.shape({
|
|
||||||
last_name: PropTypes.string,
|
|
||||||
first_name: PropTypes.string,
|
|
||||||
login: PropTypes.string,
|
|
||||||
}),
|
|
||||||
type: PropTypes.shape({
|
|
||||||
title: PropTypes.string,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
),
|
|
||||||
scheduledAppointments: PropTypes.arrayOf(
|
|
||||||
PropTypes.shape(
|
|
||||||
{
|
|
||||||
id: PropTypes.number.isRequired,
|
|
||||||
scheduled_datetime: PropTypes.string.isRequired,
|
|
||||||
patient: PropTypes.shape({
|
|
||||||
first_name: PropTypes.string,
|
|
||||||
last_name: PropTypes.string,
|
|
||||||
patronymic: PropTypes.string,
|
|
||||||
birthday: PropTypes.string,
|
|
||||||
address: PropTypes.string,
|
|
||||||
email: PropTypes.string,
|
|
||||||
phone: PropTypes.string,
|
|
||||||
diagnosis: PropTypes.string,
|
|
||||||
correction: PropTypes.string,
|
|
||||||
}),
|
|
||||||
doctor: PropTypes.shape({
|
|
||||||
last_name: PropTypes.string,
|
|
||||||
first_name: PropTypes.string,
|
|
||||||
login: PropTypes.string,
|
|
||||||
}),
|
|
||||||
type: PropTypes.shape({
|
|
||||||
title: PropTypes.string,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AppointmentsCalendarPage;
|
export default AppointmentsCalendarPage;
|
||||||
@ -92,19 +92,9 @@ const LensesPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fetchLenses = async () => {
|
const fetchLenses = async () => {
|
||||||
try {
|
|
||||||
const data = await getAllLenses(api);
|
const data = await getAllLenses(api);
|
||||||
setLenses(data);
|
setLenses(data);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} catch (error) {
|
|
||||||
console.error("Ошибка загрузки линз:", error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки линз",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
})
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchViewModeFromCache = () => {
|
const fetchViewModeFromCache = () => {
|
||||||
@ -147,7 +137,6 @@ const LensesPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteLens = async (lensId) => {
|
const handleDeleteLens = async (lensId) => {
|
||||||
try {
|
|
||||||
await deleteLens(api, lensId);
|
await deleteLens(api, lensId);
|
||||||
await fetchLenses(api);
|
await fetchLenses(api);
|
||||||
notification.success({
|
notification.success({
|
||||||
@ -155,18 +144,10 @@ const LensesPage = () => {
|
|||||||
description: "Линза успешно удалена.",
|
description: "Линза успешно удалена.",
|
||||||
placement: "topRight",
|
placement: "topRight",
|
||||||
})
|
})
|
||||||
} catch (error) {
|
|
||||||
console.error("Ошибка удаления линзы:", error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка удаления линзы",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleModalSubmit = async (lensData) => {
|
const handleModalSubmit = async (lensData) => {
|
||||||
try {
|
setIsModalVisible(false);
|
||||||
if (selectedLens) {
|
if (selectedLens) {
|
||||||
await updateLens(api, selectedLens.id, lensData);
|
await updateLens(api, selectedLens.id, lensData);
|
||||||
notification.success({
|
notification.success({
|
||||||
@ -182,16 +163,7 @@ const LensesPage = () => {
|
|||||||
placement: "topRight",
|
placement: "topRight",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setIsModalVisible(false);
|
|
||||||
await fetchLenses();
|
await fetchLenses();
|
||||||
} catch (error) {
|
|
||||||
console.error("Ошибка сохранения линзы:", error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка сохранения линзы",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleAdvancedSearch = () => {
|
const toggleAdvancedSearch = () => {
|
||||||
|
|||||||
@ -53,23 +53,10 @@ const SetLensesPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fetchSets = async () => {
|
const fetchSets = async () => {
|
||||||
try {
|
|
||||||
const data = await getAllSets(api);
|
const data = await getAllSets(api);
|
||||||
setSets(data);
|
setSets(data);
|
||||||
|
|
||||||
cacheInfo("setsData", data);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка загрузки данных",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
cacheInfo("setsData", data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const filteredSets = sets.filter(set => set.title.toLowerCase().includes(searchText.toLowerCase()));
|
const filteredSets = sets.filter(set => set.title.toLowerCase().includes(searchText.toLowerCase()));
|
||||||
@ -82,10 +69,9 @@ const SetLensesPage = () => {
|
|||||||
const handleEditSet = (set) => {
|
const handleEditSet = (set) => {
|
||||||
setSelectedSet(set);
|
setSelectedSet(set);
|
||||||
setIsModalVisible(true);
|
setIsModalVisible(true);
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleDeleteSet = async (set_id) => {
|
const handleDeleteSet = async (set_id) => {
|
||||||
try {
|
|
||||||
await deleteSet(api, set_id);
|
await deleteSet(api, set_id);
|
||||||
notification.success({
|
notification.success({
|
||||||
message: "Набор удален",
|
message: "Набор удален",
|
||||||
@ -93,40 +79,24 @@ const SetLensesPage = () => {
|
|||||||
placement: "topRight",
|
placement: "topRight",
|
||||||
});
|
});
|
||||||
await fetchSets();
|
await fetchSets();
|
||||||
} catch (error) {
|
};
|
||||||
console.error("Ошибка удаления набора:", error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка удаления набора",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
setIsModalVisible(false);
|
setIsModalVisible(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAppendSet = async (set) => {
|
const handleAppendSet = async (set) => {
|
||||||
try {
|
|
||||||
await appendLensesFromSet(api, set.id);
|
await appendLensesFromSet(api, set.id);
|
||||||
notification.success({
|
notification.success({
|
||||||
message: "Линзы добавлены",
|
message: "Линзы добавлены",
|
||||||
description: "Линзы успешно добавлены.",
|
description: "Линзы успешно добавлены.",
|
||||||
placement: "topRight",
|
placement: "topRight",
|
||||||
});
|
});
|
||||||
} catch (error) {
|
|
||||||
console.error("Ошибка добавления линз:", error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка добавления линз",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleModalSetSubmit = async (set, content = []) => {
|
const handleModalSetSubmit = async (set, content = []) => {
|
||||||
try {
|
setIsModalVisible(false);
|
||||||
|
|
||||||
let refreshed_set;
|
let refreshed_set;
|
||||||
|
|
||||||
if (selectedSet) {
|
if (selectedSet) {
|
||||||
@ -141,43 +111,15 @@ const SetLensesPage = () => {
|
|||||||
await setContent(content, refreshed_set.id);
|
await setContent(content, refreshed_set.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsModalVisible(false);
|
|
||||||
await fetchSets();
|
await fetchSets();
|
||||||
} catch (error) {
|
|
||||||
console.error("Ошибка сохранения набора:", error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка сохранения набора",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const setContent = async (content, set_id) => {
|
const setContent = async (content, set_id) => {
|
||||||
try {
|
|
||||||
console.log(content);
|
|
||||||
await addSetContent(api, content, set_id);
|
await addSetContent(api, content, set_id);
|
||||||
} catch (error) {
|
|
||||||
console.error("Ошибка сохранения набора:", error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка сохранения набора",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateContent = async (content, set_id) => {
|
const updateContent = async (content, set_id) => {
|
||||||
try {
|
|
||||||
await updateSetContent(api, content, set_id);
|
await updateSetContent(api, content, set_id);
|
||||||
} catch (error) {
|
|
||||||
console.error("Ошибка сохранения набора:", error);
|
|
||||||
notification.error({
|
|
||||||
message: "Ошибка сохранения набора",
|
|
||||||
description: "Проверьте подключение к сети.",
|
|
||||||
placement: "topRight",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const editCurrentSet = async (set) => {
|
const editCurrentSet = async (set) => {
|
||||||
|
|||||||
17
web-app/src/types/appointmentPropType.jsx
Normal file
17
web-app/src/types/appointmentPropType.jsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
import {PatientPropType} from "./patientPropType.jsx";
|
||||||
|
import {UserPropType} from "./userPropType.jsx";
|
||||||
|
import {AppointmentTypePropType} from "./appointmentTypePropType.jsx";
|
||||||
|
|
||||||
|
export const AppointmentPropType = PropTypes.shape({
|
||||||
|
id: PropTypes.number,
|
||||||
|
results: PropTypes.string,
|
||||||
|
days_until_the_next_appointment: PropTypes.number,
|
||||||
|
appointment_datetime: PropTypes.string.isRequired,
|
||||||
|
patient_id: PropTypes.number.isRequired,
|
||||||
|
doctor_id: PropTypes.number.isRequired,
|
||||||
|
type_id: PropTypes.number.isRequired,
|
||||||
|
patient: PatientPropType,
|
||||||
|
doctor: UserPropType,
|
||||||
|
type: AppointmentTypePropType,
|
||||||
|
});
|
||||||
6
web-app/src/types/appointmentTypePropType.jsx
Normal file
6
web-app/src/types/appointmentTypePropType.jsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export const AppointmentTypePropType = PropTypes.shape({
|
||||||
|
id: PropTypes.number,
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
})
|
||||||
15
web-app/src/types/lensIssuePropType.jsx
Normal file
15
web-app/src/types/lensIssuePropType.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
import {PatientPropType} from "./patientPropType.jsx";
|
||||||
|
import {UserPropType} from "./userPropType.jsx";
|
||||||
|
import {LensPropType} from "./lensPropType.jsx";
|
||||||
|
|
||||||
|
export const LensIssuePropType = PropTypes.shape({
|
||||||
|
id: PropTypes.number,
|
||||||
|
issue_date: PropTypes.string.isRequired,
|
||||||
|
patient_id: PropTypes.number.isRequired,
|
||||||
|
doctor_id: PropTypes.number,
|
||||||
|
lens_id: PropTypes.number.isRequired,
|
||||||
|
patient: PatientPropType,
|
||||||
|
doctor: UserPropType,
|
||||||
|
lens: LensPropType,
|
||||||
|
});
|
||||||
15
web-app/src/types/lensPropType.jsx
Normal file
15
web-app/src/types/lensPropType.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export const LensPropType = PropTypes.shape({
|
||||||
|
id: PropTypes.number,
|
||||||
|
tor: PropTypes.number.isRequired,
|
||||||
|
trial: PropTypes.number.isRequired,
|
||||||
|
esa: PropTypes.number.isRequired,
|
||||||
|
fvc: PropTypes.number.isRequired,
|
||||||
|
preset_refraction: PropTypes.number.isRequired,
|
||||||
|
diameter: PropTypes.number.isRequired,
|
||||||
|
periphery_toricity: PropTypes.number.isRequired,
|
||||||
|
side: PropTypes.string.isRequired,
|
||||||
|
issued: PropTypes.bool.isRequired,
|
||||||
|
type_id: PropTypes.number.isRequired,
|
||||||
|
});
|
||||||
6
web-app/src/types/lensTypePropType.jsx
Normal file
6
web-app/src/types/lensTypePropType.jsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export const LensTypePropType = PropTypes.shape({
|
||||||
|
id: PropTypes.number,
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
});
|
||||||
14
web-app/src/types/patientPropType.jsx
Normal file
14
web-app/src/types/patientPropType.jsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export const PatientPropType = PropTypes.shape({
|
||||||
|
id: PropTypes.number,
|
||||||
|
first_name: PropTypes.string.isRequired,
|
||||||
|
last_name: PropTypes.string.isRequired,
|
||||||
|
patronymic: PropTypes.string,
|
||||||
|
birthday: PropTypes.string.isRequired,
|
||||||
|
address: PropTypes.string,
|
||||||
|
email: PropTypes.string,
|
||||||
|
phone: PropTypes.string,
|
||||||
|
diagnosis: PropTypes.string,
|
||||||
|
correction: PropTypes.string,
|
||||||
|
});
|
||||||
15
web-app/src/types/scheduledAppointmentPropType.jsx
Normal file
15
web-app/src/types/scheduledAppointmentPropType.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
import {PatientPropType} from "./patientPropType.jsx";
|
||||||
|
import {UserPropType} from "./userPropType.jsx";
|
||||||
|
import {AppointmentTypePropType} from "./appointmentTypePropType.jsx";
|
||||||
|
|
||||||
|
export const ScheduledAppointmentPropType = PropTypes.shape({
|
||||||
|
id: PropTypes.number,
|
||||||
|
scheduled_datetime: PropTypes.string.isRequired,
|
||||||
|
patient_id: PropTypes.number.isRequired,
|
||||||
|
doctor_id: PropTypes.number.isRequired,
|
||||||
|
type_id: PropTypes.number.isRequired,
|
||||||
|
patient: PatientPropType,
|
||||||
|
doctor: UserPropType,
|
||||||
|
type: AppointmentTypePropType,
|
||||||
|
})
|
||||||
15
web-app/src/types/setContentPropType.jsx
Normal file
15
web-app/src/types/setContentPropType.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export const SetContentPropType = PropTypes.shape({
|
||||||
|
id: PropTypes.number,
|
||||||
|
tor: PropTypes.number.isRequired,
|
||||||
|
trial: PropTypes.number.isRequired,
|
||||||
|
esa: PropTypes.number.isRequired,
|
||||||
|
fvc: PropTypes.number.isRequired,
|
||||||
|
preset_refraction: PropTypes.number.isRequired,
|
||||||
|
diameter: PropTypes.number.isRequired,
|
||||||
|
side: PropTypes.string.isRequired,
|
||||||
|
count: PropTypes.number.isRequired,
|
||||||
|
type_id: PropTypes.number.isRequired,
|
||||||
|
set_id: PropTypes.number,
|
||||||
|
});
|
||||||
6
web-app/src/types/setPropType.jsx
Normal file
6
web-app/src/types/setPropType.jsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export const SetPropType = PropTypes.shape({
|
||||||
|
id: PropTypes.number,
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
});
|
||||||
10
web-app/src/types/userPropType.jsx
Normal file
10
web-app/src/types/userPropType.jsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export const UserPropType = PropTypes.shape({
|
||||||
|
id: PropTypes.number,
|
||||||
|
first_name: PropTypes.string.isRequired,
|
||||||
|
last_name: PropTypes.string.isRequired,
|
||||||
|
patronymic: PropTypes.string,
|
||||||
|
login: PropTypes.string.isRequired,
|
||||||
|
role_id: PropTypes.number.isRequired,
|
||||||
|
});
|
||||||
7
web-app/src/types/viewModPropType.jsx
Normal file
7
web-app/src/types/viewModPropType.jsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export const ViewModPropType = PropTypes.shape({
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
label: PropTypes.string.isRequired,
|
||||||
|
icon: PropTypes.element,
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user