diff --git a/web-app/src/Components/Dummies/AppointmentFormModal/AppointmentFormModal.jsx b/web-app/src/Components/Dummies/AppointmentFormModal/AppointmentFormModal.jsx index c375eee..acc5474 100644 --- a/web-app/src/Components/Dummies/AppointmentFormModal/AppointmentFormModal.jsx +++ b/web-app/src/Components/Dummies/AppointmentFormModal/AppointmentFormModal.jsx @@ -331,7 +331,7 @@ const AppointmentFormModal = () => { @@ -339,7 +339,7 @@ const AppointmentFormModal = () => { type="primary" onClick={appointmentFormModalUI.handleClickNextButton} disabled={appointmentFormModalUI.disableNextButton} - loading={appointmentFormModalData.isCreating || appointmentFormModalUI.isUploadingFile} + loading={appointmentFormModalData.isProcessed || appointmentFormModalUI.isUploadingFile} > {appointmentFormModalUI.nextButtonText} diff --git a/web-app/src/Components/Dummies/AppointmentFormModal/useAppointmentFormModal.js b/web-app/src/Components/Dummies/AppointmentFormModal/useAppointmentFormModal.js index 62a081d..8e758c9 100644 --- a/web-app/src/Components/Dummies/AppointmentFormModal/useAppointmentFormModal.js +++ b/web-app/src/Components/Dummies/AppointmentFormModal/useAppointmentFormModal.js @@ -1,10 +1,10 @@ -import { useGetPatientsQuery } from "../../../Api/patientsApi.js"; -import { useGetAppointmentTypesQuery } from "../../../Api/appointmentTypesApi.js"; +import {useGetPatientsQuery} from "../../../Api/patientsApi.js"; +import {useGetAppointmentTypesQuery} from "../../../Api/appointmentTypesApi.js"; import { useCreateAppointmentMutation, useGetByPatientIdQuery, } from "../../../Api/appointmentsApi.js"; -import { useCancelScheduledAppointmentMutation } from "../../../Api/scheduledAppointmentsApi.js"; +import {useCancelScheduledAppointmentMutation} from "../../../Api/scheduledAppointmentsApi.js"; const useAppointmentFormModal = () => { const { @@ -18,8 +18,11 @@ const useAppointmentFormModal = () => { isError: isErrorAppointmentTypes, } = useGetAppointmentTypesQuery(undefined); - const [createAppointment, { isLoading: isCreating, isError: isErrorCreating }] = useCreateAppointmentMutation(); - const [cancelAppointment] = useCancelScheduledAppointmentMutation(); + const [createAppointment, {isLoading: isCreating, isError: isErrorCreating}] = useCreateAppointmentMutation(); + const [cancelAppointment, { + isLoading: isCanceling, + isError: isErrorCanceling + }] = useCancelScheduledAppointmentMutation(); return { patients, @@ -27,9 +30,9 @@ const useAppointmentFormModal = () => { createAppointment, cancelAppointment, useGetByPatientIdQuery, - isLoading: isLoadingPatients || isLoadingAppointmentTypes || isCreating, - isError: isErrorPatients || isErrorAppointmentTypes || isErrorCreating, - isCreating, + isLoading: isLoadingPatients || isLoadingAppointmentTypes || isCreating || isCanceling, + isError: isErrorPatients || isErrorAppointmentTypes || isErrorCreating || isErrorCanceling, + isProcessed: isCreating || isCanceling, }; }; diff --git a/web-app/src/Components/Dummies/PatientFormModal/PatientFormModal.jsx b/web-app/src/Components/Dummies/PatientFormModal/PatientFormModal.jsx index 6c70a19..c313c42 100644 --- a/web-app/src/Components/Dummies/PatientFormModal/PatientFormModal.jsx +++ b/web-app/src/Components/Dummies/PatientFormModal/PatientFormModal.jsx @@ -17,6 +17,7 @@ const PatientFormModal = () => { open={patientFormModalUI.isModalVisible} onCancel={patientFormModalUI.handleCancel} onOk={patientFormModalUI.handleOk} + confirmLoading={patientFormModalData.isOperationLoading} okText={"Сохранить"} cancelText={"Отмена"} maskClosable={false} diff --git a/web-app/src/Components/Dummies/PatientFormModal/usePatientFormModal.js b/web-app/src/Components/Dummies/PatientFormModal/usePatientFormModal.js index fb2c8a9..e3ff1fc 100644 --- a/web-app/src/Components/Dummies/PatientFormModal/usePatientFormModal.js +++ b/web-app/src/Components/Dummies/PatientFormModal/usePatientFormModal.js @@ -7,8 +7,8 @@ import {useAddPatientMutation, useUpdatePatientMutation} from "../../../Api/pati const usePatientFormModal = () => { const dispatch = useDispatch(); - const [addPatient] = useAddPatientMutation(); - const [updatePatient] = useUpdatePatientMutation(); + const [addPatient, { isLoading: isAdding }] = useAddPatientMutation(); + const [updatePatient, { isLoading: isUpdating }] = useUpdatePatientMutation(); const { selectedPatient, @@ -44,6 +44,7 @@ const usePatientFormModal = () => { return { handleModalSubmit, + isOperationLoading: isAdding || isUpdating }; }; diff --git a/web-app/src/Components/Dummies/ScheduledAppintmentFormModal/ScheduledAppointmentFormModal.jsx b/web-app/src/Components/Dummies/ScheduledAppintmentFormModal/ScheduledAppointmentFormModal.jsx index 41354ec..8022c9a 100644 --- a/web-app/src/Components/Dummies/ScheduledAppintmentFormModal/ScheduledAppointmentFormModal.jsx +++ b/web-app/src/Components/Dummies/ScheduledAppintmentFormModal/ScheduledAppointmentFormModal.jsx @@ -96,6 +96,7 @@ const ScheduledAppointmentFormModal = () => { disabled={scheduledAppointmentFormModalUI.selectedPatient === null || scheduledAppointmentFormModalUI.selectedDateTime === null || scheduledAppointmentFormModalUI.selectedAppointmentType === null} onClick={scheduledAppointmentFormModalUI.handleCreateScheduledAppointment} style={scheduledAppointmentFormModalUI.buttonStyle} + loading={scheduledAppointmentFormModalData.isProcessing} > Запланировать diff --git a/web-app/src/Components/Dummies/ScheduledAppintmentFormModal/useScheduledAppointmentFormModal.js b/web-app/src/Components/Dummies/ScheduledAppintmentFormModal/useScheduledAppointmentFormModal.js index 2e5280c..cec2d02 100644 --- a/web-app/src/Components/Dummies/ScheduledAppintmentFormModal/useScheduledAppointmentFormModal.js +++ b/web-app/src/Components/Dummies/ScheduledAppintmentFormModal/useScheduledAppointmentFormModal.js @@ -28,6 +28,7 @@ const useScheduledAppointmentFormModal = () => { createScheduledAppointment, isLoading: isLoadingPatients || isLoadingAppointmentTypes || isCreating, isError: isErrorPatients || isErrorAppointmentTypes || isErrorCreating, + isProcessing: isCreating }; }; diff --git a/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensFormModal/LensFormModal.jsx b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensFormModal/LensFormModal.jsx index c289d6f..61c7f54 100644 --- a/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensFormModal/LensFormModal.jsx +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/Components/LensFormModal/LensFormModal.jsx @@ -5,7 +5,7 @@ import useLensForm from "./useLensForm.js"; import useLensFormUI from "./useLensFormUI.js"; -const LensFormModal = ({visible, onCancel, onSubmit, lens}) => { +const LensFormModal = ({visible, onCancel, onSubmit, lens, isProcessing}) => { const lensFormData = useLensForm(); const lensFormUI = useLensFormUI(lensFormData.lensTypes, visible, onCancel, onSubmit, lens); @@ -15,6 +15,7 @@ const LensFormModal = ({visible, onCancel, onSubmit, lens}) => { open={visible} onCancel={lensFormUI.handleCancel} onOk={lensFormUI.handleOk} + confirmLoading={isProcessing} okText={"Сохранить"} cancelText={"Отмена"} maskClosable={false} @@ -156,6 +157,7 @@ LensFormModal.propTypes = { onCancel: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired, lens: LensPropType, + isProcessing: PropTypes.bool, } export default LensFormModal; \ No newline at end of file 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 86b2b3e..6c14217 100644 --- a/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/LensesTab.jsx +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/LensesTab.jsx @@ -124,7 +124,12 @@ const LensesTab = () => { okText="Да, удалить" cancelText="Отмена" > - + ), @@ -327,6 +332,7 @@ const LensesTab = () => { onCancel={lensesUI.handleCloseModal} onSubmit={lensesData.handleModalSubmit} lens={lensesUI.selectedLens} + isProcessing={lensesData.isProcessing} /> ); diff --git a/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/useLenses.js b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/useLenses.js index f87f931..3308a78 100644 --- a/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/useLenses.js +++ b/web-app/src/Components/Pages/LensesSetsPage/Components/LensesTab/useLenses.js @@ -20,9 +20,9 @@ const useLenses = () => { pollingInterval: 20000, }); - const [addLens] = useAddLensMutation(); - const [updateLens] = useUpdateLensMutation(); - const [deleteLens] = useDeleteLensMutation(); + const [addLens, {isLoading: isAdding}] = useAddLensMutation(); + const [updateLens, {isLoading: isUpdating}] = useUpdateLensMutation(); + const [deleteLens, {isLoading: isDeleting}] = useDeleteLensMutation(); const handleDeleteLens = async (lensId) => { try { @@ -73,6 +73,7 @@ const useLenses = () => { lenses, isLoading, isError, + isProcessing: isAdding || isUpdating || isDeleting, handleDeleteLens, handleModalSubmit, } diff --git a/web-app/src/Components/Pages/LoginPage/LoginPage.jsx b/web-app/src/Components/Pages/LoginPage/LoginPage.jsx index 861a323..343a05c 100644 --- a/web-app/src/Components/Pages/LoginPage/LoginPage.jsx +++ b/web-app/src/Components/Pages/LoginPage/LoginPage.jsx @@ -1,31 +1,40 @@ -import {Form, Input, Button, Row, Col, Typography} from "antd"; -import {useSelector} from "react-redux"; +import {Form, Input, Button, Row, Col, Typography, Image, Space} from "antd"; import useLoginPage from "./useLoginPage.js"; import useLoginPageUI from "./useLoginPageUI.js"; const {Title} = Typography; const LoginPage = () => { - const {error} = useSelector((state) => state.auth); - const {onFinish, isLoading} = useLoginPage(); - const {containerStyle, formContainerStyle, titleStyle, errorStyle, labels} = useLoginPageUI(); + const { + containerStyle, + formContainerStyle, + titleStyle, + logoBlockStyle, + logoStyle, + appNameStyle, + labels + } = useLoginPageUI(); return ( + + Visus API Logo + + Visus+ + +
{labels.title} - {error && ( -
- {labels.errorPrefix} - {error} -
- )} -
{ const response = await loginUser(loginData).unwrap(); const token = response.access_token || response.token; if (!token) { - throw new Error("Токен не получен от сервера"); + throw new Error("Сервер не вернул токен авторизации"); } localStorage.setItem("access_token", token); dispatch(setUser({ token })); await dispatch(checkAuth()).unwrap(); } catch (error) { - const errorMessage = error?.data?.detail || "Не удалось войти"; + const errorMessage = error?.data?.detail || "Не удалось войти. Проверьте логин и пароль."; console.error(error); dispatch(setError(errorMessage)); notification.error({ diff --git a/web-app/src/Components/Pages/LoginPage/useLoginPageUI.js b/web-app/src/Components/Pages/LoginPage/useLoginPageUI.js index 765e87b..91af0ef 100644 --- a/web-app/src/Components/Pages/LoginPage/useLoginPageUI.js +++ b/web-app/src/Components/Pages/LoginPage/useLoginPageUI.js @@ -1,13 +1,13 @@ -import {useEffect, useRef} from "react"; -import {useNavigate} from "react-router-dom"; -import {useSelector} from "react-redux"; -import {Grid} from "antd"; +import { useEffect, useRef } from "react"; +import { useNavigate } from "react-router-dom"; +import { useSelector } from "react-redux"; +import { Grid } from "antd"; -const {useBreakpoint} = Grid; +const { useBreakpoint } = Grid; const useLoginPageUI = () => { const navigate = useNavigate(); - const {user, userData, isLoading} = useSelector((state) => state.auth); + const { user, userData, isLoading } = useSelector((state) => state.auth); const screens = useBreakpoint(); const hasRedirected = useRef(false); @@ -19,15 +19,32 @@ const useLoginPageUI = () => { padding: screens.xs ? 10 : 20, border: "1px solid #ddd", borderRadius: 8, + textAlign: "center", }; const titleStyle = { textAlign: "center", + marginBottom: 20, }; - const errorStyle = { - color: "red", - marginBottom: 15, + const logoStyle = { + width: 80, + marginBottom: 10, + borderRadius: 20, + border: "1px solid #ddd", + }; + + const appNameStyle = { + textAlign: "center", + color: "#1890ff", + marginBottom: 40, + }; + + const logoBlockStyle = { + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "center", }; const labels = { @@ -37,7 +54,6 @@ const useLoginPageUI = () => { submitButton: "Войти", loginRequired: "Пожалуйста, введите логин", passwordRequired: "Пожалуйста, введите пароль", - errorPrefix: "Ошибка при входе: ", }; useEffect(() => { @@ -52,8 +68,10 @@ const useLoginPageUI = () => { containerStyle, formContainerStyle, titleStyle, - errorStyle, + logoStyle, + appNameStyle, labels, + logoBlockStyle, }; };