diff --git a/web-app/src/Components/Dummies/AppointmentFormModal/AppointmentFormModal.jsx b/web-app/src/Components/Dummies/AppointmentFormModal/AppointmentFormModal.jsx
index 00c7970..67f952a 100644
--- a/web-app/src/Components/Dummies/AppointmentFormModal/AppointmentFormModal.jsx
+++ b/web-app/src/Components/Dummies/AppointmentFormModal/AppointmentFormModal.jsx
@@ -18,7 +18,7 @@ import {
} from "antd";
import useAppointmentFormModal from "./useAppointmentFormModal.js";
import useAppointmentFormModalUI from "./useAppointmentFormModalUI.js";
-import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx";
+import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
import {useMemo} from "react";
const AppointmentFormModal = () => {
diff --git a/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx b/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx
index 6a0f884..22abf85 100644
--- a/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx
+++ b/web-app/src/Components/Pages/AppointmentsPage/AppointmentsPage.jsx
@@ -11,7 +11,7 @@ import AppointmentsCalendarTab from "./Components/AppointmentCalendarTab/Appoint
import useAppointmentsUI from "./useAppointmentsUI.js";
import useAppointments from "./useAppointments.js";
import dayjs from 'dayjs';
-import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx";
+import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
import AppointmentFormModal from "../../Dummies/AppointmentFormModal/AppointmentFormModal.jsx";
import {useDispatch} from "react-redux";
import {
diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx
index f675b35..f423a4d 100644
--- a/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx
+++ b/web-app/src/Components/Pages/AppointmentsPage/Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx
@@ -1,6 +1,6 @@
import { Calendar } from "antd";
import "dayjs/locale/ru";
-import CalendarCell from "../../../../Widgets/CalendarCell.jsx";
+import CalendarCell from "../CalendarCell/CalendarCell.jsx";
import useAppointments from "../../useAppointments.js";
import useAppointmentCalendarUI from "./useAppointmentCalendarUI.js";
import AppointmentsListModal from "../AppointmentsListModal/AppointmentsListModal.jsx";
diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/CalendarCell/CalendarCell.jsx b/web-app/src/Components/Pages/AppointmentsPage/Components/CalendarCell/CalendarCell.jsx
new file mode 100644
index 0000000..c42b6e8
--- /dev/null
+++ b/web-app/src/Components/Pages/AppointmentsPage/Components/CalendarCell/CalendarCell.jsx
@@ -0,0 +1,73 @@
+import { Badge, Col, Tag, Tooltip } from "antd";
+import PropTypes from "prop-types";
+import { AppointmentPropType } from "../../../../../Types/appointmentPropType.js";
+import { ScheduledAppointmentPropType } from "../../../../../Types/scheduledAppointmentPropType.js";
+import useCalendarCellUI from "./useCalendarCellUI.js";
+
+const CalendarCell = ({ allAppointments, onCellClick, onItemClick }) => {
+ const {
+ containerRef,
+ isCompressed,
+ containerStyle,
+ listStyle,
+ columnStyle,
+ tagStyle,
+ badgeTextStyle,
+ compressedCountStyle,
+ getTooltipTitle,
+ getBadgeText,
+ getTagColor,
+ getBadgeStatus,
+ } = useCalendarCellUI();
+
+ return (
+
+ {!isCompressed && (
+
+ {allAppointments.map((app) => (
+
+
+ {
+ e.stopPropagation();
+ onItemClick(app);
+ }}
+ style={tagStyle}
+ >
+
+ {getBadgeText(app)}
+
+ }
+ />
+
+
+
+ ))}
+
+ )}
+ {isCompressed && (
+
+ {allAppointments.length > 0 && `+${allAppointments.length}`}
+
+ )}
+
+ );
+};
+
+CalendarCell.propTypes = {
+ allAppointments: PropTypes.arrayOf(
+ PropTypes.oneOfType([AppointmentPropType, ScheduledAppointmentPropType])
+ ).isRequired,
+ onCellClick: PropTypes.func.isRequired,
+ onItemClick: PropTypes.func.isRequired,
+};
+
+export default CalendarCell;
\ No newline at end of file
diff --git a/web-app/src/Components/Pages/AppointmentsPage/Components/CalendarCell/useCalendarCellUI.js b/web-app/src/Components/Pages/AppointmentsPage/Components/CalendarCell/useCalendarCellUI.js
new file mode 100644
index 0000000..7557da1
--- /dev/null
+++ b/web-app/src/Components/Pages/AppointmentsPage/Components/CalendarCell/useCalendarCellUI.js
@@ -0,0 +1,114 @@
+import { useEffect, useRef, useState } from "react";
+import dayjs from "dayjs";
+
+const useCalendarCellUI = () => {
+ 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();
+ }, []);
+
+ // Styles
+ const containerStyle = {
+ height: "100%",
+ cursor: isCompressed ? "pointer" : "default",
+ position: "relative",
+ };
+
+ const listStyle = {
+ padding: 0,
+ margin: 0,
+ };
+
+ const columnStyle = {
+ overflowX: "hidden",
+ };
+
+ const tagStyle = {
+ margin: "2px 2px 0 0",
+ cursor: "pointer",
+ width: "95%",
+ minHeight: 30,
+ display: "flex",
+ alignItems: "center",
+ overflow: "hidden",
+ };
+
+ const badgeTextStyle = {
+ whiteSpace: "nowrap",
+ overflow: "hidden",
+ textOverflow: "ellipsis",
+ display: "inline-block",
+ width: "100%",
+ };
+
+ const compressedCountStyle = {
+ position: "absolute",
+ top: 2,
+ right: 2,
+ fontSize: 10,
+ fontWeight: "bold",
+ color: "#1890ff",
+ };
+
+ // Static configuration
+ const labels = {
+ pastAppointment: "Прошедший прием",
+ scheduledAppointment: "Запланированный прием",
+ notSpecified: "Не указан",
+ };
+
+ // Formatting functions
+ const getAppointmentTime = (datetime) => {
+ return datetime ? dayjs(datetime).format("HH:mm") : labels.notSpecified;
+ };
+
+ const getTooltipTitle = (app) => {
+ const type = app.appointment_datetime ? labels.pastAppointment : labels.scheduledAppointment;
+ return `${type}: ${getAppointmentTime(app.appointment_datetime || app.scheduled_datetime)}`;
+ };
+
+ const getBadgeText = (app) => {
+ const time = getAppointmentTime(app.appointment_datetime || app.scheduled_datetime);
+ const patientName = app.patient
+ ? `${app.patient.last_name || ""} ${app.patient.first_name || ""}`.trim()
+ : labels.notSpecified;
+ return `${time} ${patientName}`;
+ };
+
+ const getTagColor = (isPast) => {
+ return isPast ? "green" : "blue";
+ };
+
+ const getBadgeStatus = (isPast) => {
+ return isPast ? "success" : "processing";
+ };
+
+ return {
+ containerRef,
+ isCompressed,
+ containerStyle,
+ listStyle,
+ columnStyle,
+ tagStyle,
+ badgeTextStyle,
+ compressedCountStyle,
+ labels,
+ getTooltipTitle,
+ getBadgeText,
+ getTagColor,
+ getBadgeStatus,
+ };
+};
+
+export default useCalendarCellUI;
\ No newline at end of file
diff --git a/web-app/src/Components/Pages/HomePage/HomePage.jsx b/web-app/src/Components/Pages/HomePage/HomePage.jsx
index e1047c1..84818d3 100644
--- a/web-app/src/Components/Pages/HomePage/HomePage.jsx
+++ b/web-app/src/Components/Pages/HomePage/HomePage.jsx
@@ -8,7 +8,7 @@ import {
import useHomePage from "./useHomePage.js";
import useHomePageUI from "./useHomePageUI.js";
import dayjs from "dayjs";
-import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx";
+import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
import {Bar} from "react-chartjs-2";
import {
Chart as ChartJS,
diff --git a/web-app/src/Components/Pages/IssuesPage/IssuesPage.jsx b/web-app/src/Components/Pages/IssuesPage/IssuesPage.jsx
index 4699408..139a929 100644
--- a/web-app/src/Components/Pages/IssuesPage/IssuesPage.jsx
+++ b/web-app/src/Components/Pages/IssuesPage/IssuesPage.jsx
@@ -16,8 +16,8 @@ import {DatabaseOutlined, PlusOutlined, UnorderedListOutlined} from "@ant-design
import LensIssueViewModal from "./Components/LensIssueViewModal/LensIssueViewModal.jsx";
import dayjs from "dayjs";
import LensIssueFormModal from "./Components/LensIssueFormModal/LensIssueFormModal.jsx";
-import SelectViewMode from "../../Widgets/SelectViewMode.jsx";
-import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx";
+import SelectViewMode from "../../Widgets/SelectViewMode/SelectViewMode.jsx";
+import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
import useIssues from "./useIssues.js";
import useIssuesUI from "./useIssuesUI.js";
diff --git a/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/LensesTab.jsx b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/LensesTab.jsx
index 35b80ce..86b2b3e 100644
--- a/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/LensesTab.jsx
+++ b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/LensesTab.jsx
@@ -24,8 +24,8 @@ import {
} from "@ant-design/icons";
import LensCard from "../../../../Dummies/LensListCard.jsx";
import LensFormModal from "./Components/LensFormModal/LensFormModal.jsx";
-import SelectViewMode from "../../../../Widgets/SelectViewMode.jsx";
-import LoadingIndicator from "../../../../Widgets/LoadingIndicator.jsx";
+import SelectViewMode from "../../../../Widgets/SelectViewMode/SelectViewMode.jsx";
+import LoadingIndicator from "../../../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
import useLenses from "./useLenses.js";
import useLensesUI from "./useLensesUI.js";
diff --git a/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/SetsTab.jsx b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/SetsTab.jsx
index 523211c..2d99915 100644
--- a/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/SetsTab.jsx
+++ b/web-app/src/Components/Pages/LensesSetsPage/Components/SetsTab/SetsTab.jsx
@@ -2,7 +2,7 @@ import {FloatButton, Input, List, Result, Row, Typography} from "antd";
import {PlusOutlined, SwitcherOutlined} from "@ant-design/icons";
import SetListCard from "../../../../Dummies/SetListCard.jsx";
import SetFormModal from "./Components/SetFormModal/SetFormModal.jsx";
-import LoadingIndicator from "../../../../Widgets/LoadingIndicator.jsx";
+import LoadingIndicator from "../../../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
import useSets from "./useSets.js";
import useSetsUI from "./useSetsUI.js";
diff --git a/web-app/src/Components/Pages/PatientsPage/PatientsPage.jsx b/web-app/src/Components/Pages/PatientsPage/PatientsPage.jsx
index f26922f..153de88 100644
--- a/web-app/src/Components/Pages/PatientsPage/PatientsPage.jsx
+++ b/web-app/src/Components/Pages/PatientsPage/PatientsPage.jsx
@@ -19,9 +19,9 @@ import {
TeamOutlined
} from "@ant-design/icons";
import PatientListCard from "../../Dummies/PatientListCard.jsx";
-import PatientFormModal from "./Components/PatientFormModal/PatientFormModal.jsx";
-import SelectViewMode from "../../Widgets/SelectViewMode.jsx";
-import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx";
+import PatientFormModal from "../../Dummies/PatientFormModal/PatientFormModal.jsx";
+import SelectViewMode from "../../Widgets/SelectViewMode/SelectViewMode.jsx";
+import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
import usePatients from "./usePatients.js";
import usePatientsUI from "./usePatientsUI.js";
@@ -186,11 +186,7 @@ const PatientsPage = () => {
tooltip="Добавить пациента"
/>
-
+
);
};
diff --git a/web-app/src/Components/Pages/PatientsPage/usePatients.js b/web-app/src/Components/Pages/PatientsPage/usePatients.js
index 78fe3e2..515f45f 100644
--- a/web-app/src/Components/Pages/PatientsPage/usePatients.js
+++ b/web-app/src/Components/Pages/PatientsPage/usePatients.js
@@ -1,24 +1,14 @@
-import { useDispatch, useSelector } from "react-redux";
-import { notification } from "antd";
+import {notification} from "antd";
import {
- useAddPatientMutation,
useDeletePatientMutation,
useGetPatientsQuery,
- useUpdatePatientMutation
} from "../../../Api/patientsApi.js";
-import {closeModal} from "../../../Redux/Slices/patientsSlice.js";
const usePatients = () => {
- const dispatch = useDispatch();
- const {
- selectedPatient,
- } = useSelector(state => state.patientsUI);
-
- const { data: patients = [], isLoading, isError } = useGetPatientsQuery(undefined, {
+ const {data: patients = [], isLoading, isError} = useGetPatientsQuery(undefined, {
pollingInterval: 20000,
});
- const [addPatient] = useAddPatientMutation();
- const [updatePatient] = useUpdatePatientMutation();
+
const [deletePatient] = useDeletePatientMutation();
const handleDeletePatient = async (patientId) => {
@@ -38,40 +28,11 @@ const usePatients = () => {
}
};
- const handleModalSubmit = async (patientData) => {
- dispatch(closeModal());
-
- try {
- if (selectedPatient) {
- await updatePatient({ id: selectedPatient.id, ...patientData }).unwrap();
- notification.success({
- message: "Пациент обновлён",
- description: `Данные пациента ${patientData.first_name} ${patientData.last_name} успешно обновлены.`,
- placement: "topRight",
- });
- } else {
- await addPatient(patientData).unwrap();
- notification.success({
- message: "Пациент добавлен",
- description: `Пациент ${patientData.first_name} ${patientData.last_name} успешно добавлен.`,
- placement: "topRight",
- });
- }
- } catch (error) {
- notification.error({
- message: "Ошибка",
- description: error.data?.message || "Произошла ошибка при сохранении",
- placement: "topRight",
- });
- }
- };
-
return {
patients,
isLoading,
isError,
handleDeletePatient,
- handleModalSubmit,
};
};
diff --git a/web-app/src/Components/Pages/ProfilePage/ProfilePage.jsx b/web-app/src/Components/Pages/ProfilePage/ProfilePage.jsx
index ef19099..d7f5e01 100644
--- a/web-app/src/Components/Pages/ProfilePage/ProfilePage.jsx
+++ b/web-app/src/Components/Pages/ProfilePage/ProfilePage.jsx
@@ -1,6 +1,6 @@
import { Button, Card, Col, Form, Input, Modal, Row, Space, Typography, Result } from "antd";
import { EditOutlined } from "@ant-design/icons";
-import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx";
+import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
import useProfilePage from "./useProfilePage.js";
import useProfilePageUI from "./useProfilePageUI.js";
import { useSelector } from "react-redux";
diff --git a/web-app/src/Components/Widgets/AppointmentViewModal/AppointmentViewModal.jsx b/web-app/src/Components/Widgets/AppointmentViewModal/AppointmentViewModal.jsx
index 99f1130..e54fb91 100644
--- a/web-app/src/Components/Widgets/AppointmentViewModal/AppointmentViewModal.jsx
+++ b/web-app/src/Components/Widgets/AppointmentViewModal/AppointmentViewModal.jsx
@@ -1,68 +1,78 @@
import {Button, Modal, Row, Typography} from "antd";
import useAppointmentViewUI from "./useAppointmentViewUI.js";
-import dayjs from "dayjs";
-
const AppointmentViewModal = () => {
- const appointmentViewModalUI = useAppointmentViewUI();
+ const {
+ modalWidth,
+ blockStyle,
+ footerRowStyle,
+ footerButtonStyle,
+ labels,
+ selectedAppointment,
+ visible,
+ getDateString,
+ getAppointmentTime,
+ getPatientName,
+ getPatientField,
+ getResults,
+ onCancel,
+ } = useAppointmentViewUI();
- if (!appointmentViewModalUI.selectedAppointment) {
+ if (!selectedAppointment) {
return null;
}
return (
- <>
-
-
-
Информация о приеме
-
- Пациент:{" "}
- {appointmentViewModalUI.selectedAppointment.patient ? `${appointmentViewModalUI.selectedAppointment.patient.last_name} ${appointmentViewModalUI.selectedAppointment.patient.first_name}` : "Не указан"}
-
-
- Дата рождения:{" "}
- {appointmentViewModalUI.selectedAppointment.patient ? appointmentViewModalUI.getDateString(appointmentViewModalUI.selectedAppointment.patient.birthday) : "Не указан"}
-
-
- Email: {appointmentViewModalUI.selectedAppointment.patient?.email || "Не указан"}
-
-
- Телефон: {appointmentViewModalUI.selectedAppointment.patient?.phone || "Не указан"}
-
-
- Тип приема: {appointmentViewModalUI.selectedAppointment.type?.title || "Не указан"}
-
-
- Время приема:{" "}
- {appointmentViewModalUI.selectedAppointment.appointment_datetime
- ? dayjs(appointmentViewModalUI.selectedAppointment.appointment_datetime).format("DD.MM.YYYY HH:mm")
- : "Не указано"}
-
-
- Дней до следующего приема:{" "}
- {appointmentViewModalUI.selectedAppointment.days_until_the_next_appointment || "Не указано"}
-
-
- Результаты приема:
-
-
-
-
-
-
-
- >
+
+
+
Информация о приеме
+
+ {labels.patient} {getPatientName(selectedAppointment.patient)}
+
+
+ {labels.birthday}{" "}
+ {getDateString(selectedAppointment.patient?.birthday)}
+
+
+ {labels.email}{" "}
+ {getPatientField(selectedAppointment.patient?.email)}
+
+
+ {labels.phone}{" "}
+ {getPatientField(selectedAppointment.patient?.phone)}
+
+
+ {labels.type}{" "}
+ {getPatientField(selectedAppointment.type?.title)}
+
+
+ {labels.appointmentTime}{" "}
+ {getAppointmentTime(selectedAppointment.appointment_datetime)}
+
+
+ {labels.daysUntilNext}{" "}
+ {getPatientField(selectedAppointment.days_until_the_next_appointment)}
+
+
+ {labels.results}
+
+
+
+
+
+
+
);
};
-
export default AppointmentViewModal;
\ No newline at end of file
diff --git a/web-app/src/Components/Widgets/AppointmentViewModal/useAppointmentViewUI.js b/web-app/src/Components/Widgets/AppointmentViewModal/useAppointmentViewUI.js
index c461e22..bb9d05f 100644
--- a/web-app/src/Components/Widgets/AppointmentViewModal/useAppointmentViewUI.js
+++ b/web-app/src/Components/Widgets/AppointmentViewModal/useAppointmentViewUI.js
@@ -1,36 +1,74 @@
-import {useDispatch, useSelector} from "react-redux";
-import {
- setSelectedAppointment
-} from "../../../Redux/Slices/appointmentsSlice.js";
+import { useDispatch, useSelector } from "react-redux";
+import { setSelectedAppointment } from "../../../Redux/Slices/appointmentsSlice.js";
+import dayjs from "dayjs";
const useAppointmentViewUI = () => {
const dispatch = useDispatch();
- const {
- selectedAppointment,
- } = useSelector(state => state.appointmentsUI);
+ const { selectedAppointment } = useSelector((state) => state.appointmentsUI);
const modalWidth = 700;
- const blockStyle = {marginBottom: 16};
- const footerRowStyle = {marginTop: 16};
- const footerButtonStyle = {marginRight: 8};
+ const blockStyle = { marginBottom: 16 };
+ const footerRowStyle = { marginTop: 16 };
+ const footerButtonStyle = { marginRight: 8 };
+
+ const labels = {
+ title: "Просмотр приема",
+ patient: "Пациент:",
+ birthday: "Дата рождения:",
+ email: "Email:",
+ phone: "Телефон:",
+ type: "Тип приема:",
+ appointmentTime: "Время приема:",
+ daysUntilNext: "Дней до следующего приема:",
+ results: "Результаты приема:",
+ closeButton: "Закрыть",
+ notSpecified: "Не указан",
+ resultsNotSpecified: "Не указаны",
+ };
+
const visible = !!selectedAppointment;
+ const getDateString = (date) => {
+ return date ? new Date(date).toLocaleDateString("ru-RU") : labels.notSpecified;
+ };
+
+ const getAppointmentTime = (datetime) => {
+ return datetime
+ ? dayjs(datetime).format("DD.MM.YYYY HH:mm")
+ : labels.notSpecified;
+ };
+
+ const getPatientName = (patient) => {
+ return patient
+ ? `${patient.last_name} ${patient.first_name}`
+ : labels.notSpecified;
+ };
+
+ const getPatientField = (field) => {
+ return field || labels.notSpecified;
+ };
+
+ const getResults = (results) => {
+ return results || labels.resultsNotSpecified;
+ };
+
const onCancel = () => {
dispatch(setSelectedAppointment(null));
};
- const getDateString = (date) => {
- return new Date(date).toLocaleDateString('ru-RU');
- };
-
return {
modalWidth,
blockStyle,
footerRowStyle,
footerButtonStyle,
+ labels,
selectedAppointment,
visible,
getDateString,
+ getAppointmentTime,
+ getPatientName,
+ getPatientField,
+ getResults,
onCancel,
};
};
diff --git a/web-app/src/Components/Widgets/CalendarCell.jsx b/web-app/src/Components/Widgets/CalendarCell.jsx
deleted file mode 100644
index 8bc3497..0000000
--- a/web-app/src/Components/Widgets/CalendarCell.jsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import {useEffect, useRef, useState} from "react";
-import {Badge, Col, Tag, Tooltip} from "antd";
-import dayjs from "dayjs";
-import PropTypes from "prop-types";
-import {AppointmentPropType} from "../../Types/appointmentPropType.js";
-import {ScheduledAppointmentPropType} from "../../Types/scheduledAppointmentPropType.js";
-
-const CalendarCell = ({allAppointments, 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 (
-
- {!isCompressed && (
-
- {allAppointments.map((app) => (
-
-
- {
- e.stopPropagation();
- onItemClick(app);
- }}
- style={{
- margin: "2px 2px 0 0",
- cursor: "pointer",
- width: "95%",
- minHeight: 30,
- display: "flex",
- alignItems: "center",
- overflow: "hidden",
- }}
- >
-
- {dayjs(app.appointment_datetime || app.scheduled_datetime).format("HH:mm") +
- ` ${app.patient?.last_name || ""} ${app.patient?.first_name || ""}`}
-
- }
- />
-
-
-
- ))}
-
- )}
- {isCompressed && (
-
- {allAppointments.length > 0 && `+${allAppointments.length}`}
-
- )}
-
- );
-};
-
-CalendarCell.propTypes = {
- allAppointments: PropTypes.arrayOf(
- PropTypes.oneOfType([AppointmentPropType, ScheduledAppointmentPropType])
- ).isRequired,
- onCellClick: PropTypes.func.isRequired,
- onItemClick: PropTypes.func.isRequired,
-};
-
-export default CalendarCell;
\ No newline at end of file
diff --git a/web-app/src/Components/Widgets/LoadingIndicator.jsx b/web-app/src/Components/Widgets/LoadingIndicator.jsx
deleted file mode 100644
index ff51c1b..0000000
--- a/web-app/src/Components/Widgets/LoadingIndicator.jsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import {Spin} from "antd";
-import {LoadingOutlined} from "@ant-design/icons";
-
-
-const LoadingIndicator = () => {
- return (
-
- }/>
-
- )
-};
-
-export default LoadingIndicator;
\ No newline at end of file
diff --git a/web-app/src/Components/Widgets/LoadingIndicator/LoadingIndicator.jsx b/web-app/src/Components/Widgets/LoadingIndicator/LoadingIndicator.jsx
new file mode 100644
index 0000000..0e850a3
--- /dev/null
+++ b/web-app/src/Components/Widgets/LoadingIndicator/LoadingIndicator.jsx
@@ -0,0 +1,15 @@
+import {Spin} from "antd";
+import {LoadingOutlined} from "@ant-design/icons";
+import useLoadingIndicatorUI from "./useLoadingIndicator.js";
+
+const LoadingIndicator = () => {
+ const {containerStyle, iconStyle} = useLoadingIndicatorUI();
+
+ return (
+
+ }/>
+
+ );
+};
+
+export default LoadingIndicator;
\ No newline at end of file
diff --git a/web-app/src/Components/Widgets/LoadingIndicator/useLoadingIndicator.js b/web-app/src/Components/Widgets/LoadingIndicator/useLoadingIndicator.js
new file mode 100644
index 0000000..8ff8713
--- /dev/null
+++ b/web-app/src/Components/Widgets/LoadingIndicator/useLoadingIndicator.js
@@ -0,0 +1,20 @@
+const useLoadingIndicatorUI = () => {
+ const containerStyle = {
+ display: "flex",
+ justifyContent: "center",
+ alignItems: "center",
+ height: "100vh",
+ };
+
+ const iconStyle = {
+ fontSize: 64,
+ color: "#1890ff",
+ };
+
+ return {
+ containerStyle,
+ iconStyle,
+ };
+};
+
+export default useLoadingIndicatorUI;
\ No newline at end of file
diff --git a/web-app/src/Components/Widgets/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx b/web-app/src/Components/Widgets/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx
index 6fa6f74..837437a 100644
--- a/web-app/src/Components/Widgets/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx
+++ b/web-app/src/Components/Widgets/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx
@@ -1,79 +1,79 @@
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);
+ const {
+ selectedScheduledAppointment,
+ modalWidth,
+ blockStyle,
+ footerRowStyle,
+ footerButtonStyle,
+ labels,
+ visible,
+ getDateString,
+ getAppointmentTime,
+ getPatientName,
+ getPatientField,
+ onCancel,
+ cancelScheduledAppointment,
+ handleConvertToAppointment,
+ } = useScheduledAppointmentsViewModalUI(scheduledAppointmentsViewModalData.cancelAppointment);
- if (!scheduledAppointmentsViewModalUI.selectedScheduledAppointment) {
+ if (!selectedScheduledAppointment) {
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 (
-
+
Информация о приеме
- Пациент:{" "}
- {scheduledAppointmentsViewModalUI.selectedScheduledAppointment.patient ? `${scheduledAppointmentsViewModalUI.selectedScheduledAppointment.patient.last_name} ${scheduledAppointmentsViewModalUI.selectedScheduledAppointment.patient.first_name}` : "Не указан"}
+ {labels.patient} {getPatientName(selectedScheduledAppointment.patient)}
- Дата рождения:{" "}
- {scheduledAppointmentsViewModalUI.selectedScheduledAppointment.patient ? scheduledAppointmentsViewModalUI.getDateString(scheduledAppointmentsViewModalUI.selectedScheduledAppointment.patient.birthday) : "Не указан"}
+ {labels.birthday}{" "}
+ {getDateString(selectedScheduledAppointment.patient?.birthday)}
- Email: {scheduledAppointmentsViewModalUI.selectedScheduledAppointment.patient?.email || "Не указан"}
+ {labels.email}{" "}
+ {getPatientField(selectedScheduledAppointment.patient?.email)}
- Телефон: {scheduledAppointmentsViewModalUI.selectedScheduledAppointment.patient?.phone || "Не указан"}
+ {labels.phone}{" "}
+ {getPatientField(selectedScheduledAppointment.patient?.phone)}
- Тип
- приема: {scheduledAppointmentsViewModalUI.selectedScheduledAppointment.type?.title || "Не указан"}
+ {labels.type}{" "}
+ {getPatientField(selectedScheduledAppointment.type?.title)}
- Время приема:{" "}
- {scheduledAppointmentsViewModalUI.selectedScheduledAppointment.scheduled_datetime
- ? dayjs(scheduledAppointmentsViewModalUI.selectedScheduledAppointment.scheduled_datetime).format("DD.MM.YYYY HH:mm")
- : "Не указано"}
+ {labels.appointmentTime}{" "}
+ {getAppointmentTime(selectedScheduledAppointment.scheduled_datetime)}
-
-