создал пустую страницу для преимов, изменил обработку ошибок в методах API, исправил закрывающиеся модальные окна при просмотре информации о пациенте и линзе

This commit is contained in:
Андрей Дувакин 2025-03-11 19:10:25 +05:00
parent faaf087d08
commit 99fbca72fe
27 changed files with 67 additions and 37 deletions

View File

@ -6,6 +6,7 @@ import PatientsPage from "./pages/PatientsPage.jsx";
import HomePage from "./pages/HomePage.jsx"; import HomePage from "./pages/HomePage.jsx";
import LensesLayout from "./layouts/LensesLayout.jsx"; import LensesLayout from "./layouts/LensesLayout.jsx";
import IssuesPage from "./pages/IssuesPage.jsx"; import IssuesPage from "./pages/IssuesPage.jsx";
import AppointmentsPage from "./pages/AppointmentsPage.jsx";
const AppRouter = () => ( const AppRouter = () => (
@ -17,6 +18,7 @@ const AppRouter = () => (
<Route path={"/patients"} element={<PatientsPage/>}/> <Route path={"/patients"} element={<PatientsPage/>}/>
<Route path={"/lenses"} element={<LensesLayout/>}/> <Route path={"/lenses"} element={<LensesLayout/>}/>
<Route path={"/issues"} element={<IssuesPage/>}/> <Route path={"/issues"} element={<IssuesPage/>}/>
<Route path={"/appointments"} element={<AppointmentsPage/>}/>
<Route path={"/"} element={<HomePage/>}/> <Route path={"/"} element={<HomePage/>}/>
</Route> </Route>
</Route> </Route>

View File

@ -8,7 +8,7 @@ const loginUser = async (loginData) => {
}); });
return response.data.access_token; return response.data.access_token;
} catch (error) { } catch (error) {
if (error.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Неверное имя пользователя или пароль") throw new Error("Неверное имя пользователя или пароль")
} }

View File

@ -11,7 +11,7 @@ const AddLensIssue = async (token, lens_issue) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь неайден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь неайден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const GetAllLensIssues = async (token) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const getAllLensTypes = async (token) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const addLens = async (token, lens) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const deleteLens = async (token, lens_id) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -10,7 +10,7 @@ const getAllLenses = async (token) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw Error("Ошибка авторизации: пользователь неяден или токен недействителен"); throw Error("Ошибка авторизации: пользователь неяден или токен недействителен");
} }
throw Error(error.message); throw Error(error.message);

View File

@ -10,7 +10,7 @@ const getNotIssuedLenses = async (token) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw Error("Ошибка авторизации: пользователь неяден или токен недействителен"); throw Error("Ошибка авторизации: пользователь неяден или токен недействителен");
} }
throw Error(error.message); throw Error(error.message);

View File

@ -11,7 +11,7 @@ const updateLens = async (token, lensId, lensData) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const addPatient = async (token, patient) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const deletePatient = async (token, patient_id) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const getAllPatients = async (token) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const updatePatient = async (token, patientId, patientData) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const addSetContent = async (token, set_content, set_id) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const getSetContentBySetId = async (token, set_id) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const updateSetContent = async (token, set_content, set_id) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const addSet = async (token, set) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,11 +11,10 @@ const appendLensesFromSet = async (token, set_id) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} else {
throw new Error(error.message);
} }
throw new Error(error.message);
} }
}; };

View File

@ -10,7 +10,7 @@ const deleteSet = async (token, set_id) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -10,7 +10,7 @@ const getAllSets = async (token) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -11,7 +11,7 @@ const updateSet = async (token, set_id, set) => {
}); });
return response.data; return response.data;
} catch (error) { } catch (error) {
if (error.response?.status === 403) { if (error.status === 403 || error.status === 401) {
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен"); throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
} }
throw new Error(error.message); throw new Error(error.message);

View File

@ -1,5 +1,5 @@
import {useState} from "react"; import {useState} from "react";
import {Layout, Menu} from "antd"; import {Grid, Layout, Menu} from "antd";
import {Outlet, useLocation, useNavigate} from "react-router-dom"; import {Outlet, useLocation, useNavigate} from "react-router-dom";
import { import {
HomeOutlined, HomeOutlined,
@ -16,8 +16,11 @@ import {useAuth} from "../AuthContext.jsx";
const {Content, Footer, Sider} = Layout; const {Content, Footer, Sider} = Layout;
const getItem = (label, key, icon, children) => ({key, icon, children, label}); const getItem = (label, key, icon, children) => ({key, icon, children, label});
const {useBreakpoint} = Grid;
const MainLayout = () => { const MainLayout = () => {
const screens = useBreakpoint();
const [collapsed, setCollapsed] = useState(true); const [collapsed, setCollapsed] = useState(true);
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
@ -47,7 +50,12 @@ const MainLayout = () => {
return ( return (
<Layout style={{minHeight: "100vh"}}> <Layout style={{minHeight: "100vh"}}>
<Sider collapsible collapsed={collapsed} onCollapse={setCollapsed} style={{height: "100vh", position: "fixed", left: 0}}> <Sider
collapsible={!screens.xs}
collapsed={collapsed}
onCollapse={setCollapsed}
style={{height: "100vh", position: "fixed", left: 0}}
>
<div style={{display: "flex", justifyContent: "center", padding: 16}}> <div style={{display: "flex", justifyContent: "center", padding: 16}}>
<img <img
src="/logo_rounded.png" src="/logo_rounded.png"
@ -64,8 +72,18 @@ const MainLayout = () => {
/> />
</Sider> </Sider>
<Layout style={{marginLeft: collapsed ? 80 : 200, transition: "margin-left 0.2s"}}> <Layout
<Content style={{margin: "0 16px", padding: 24, minHeight: "100vh", overflow: "auto", background: "#fff", borderRadius: 8, marginTop: "15px"}}> style={{marginLeft: collapsed ? 80 : 200, transition: "margin-left 0.2s"}}
>
<Content style={{
margin: "0 16px",
padding: 24,
minHeight: "100vh",
overflow: "auto",
background: "#fff",
borderRadius: 8,
marginTop: "15px"
}}>
<Outlet/> <Outlet/>
</Content> </Content>
<Footer style={{textAlign: "center"}}>Линза+ © {new Date().getFullYear()}</Footer> <Footer style={{textAlign: "center"}}>Линза+ © {new Date().getFullYear()}</Footer>

View File

@ -0,0 +1,11 @@
const AppointmentsPage = () => {
return (
<>
</>
)
};
export default AppointmentsPage;

View File

@ -283,7 +283,7 @@ const IssuesPage = () => {
<Row gutter={[16, 16]} style={{marginBottom: 20}}> <Row gutter={[16, 16]} style={{marginBottom: 20}}>
<Col xs={24} md={24} sm={24} xl={12}> <Col xs={24} md={24} sm={24} xl={12}>
<Input <Input
placeholder="Поиск по пациенту или дате" placeholder="Поиск по пациенту или врачу"
onChange={handleSearch} onChange={handleSearch}
style={{width: "100%"}} style={{width: "100%"}}
allowClear allowClear
@ -301,6 +301,7 @@ const IssuesPage = () => {
title="Фильтр по дате выдачи линзы" title="Фильтр по дате выдачи линзы"
> >
<DatePicker.RangePicker <DatePicker.RangePicker
allowClear={false}
style={{width: "100%"}} style={{width: "100%"}}
placeholder={["Дата начала", "Дата окончания"]} placeholder={["Дата начала", "Дата окончания"]}
format="DD.MM.YYYY" format="DD.MM.YYYY"

View File

@ -72,11 +72,11 @@ const LensesPage = () => {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (!isModalVisible) { if (!isModalVisible && !selectedLens) {
const intervalId = setInterval(fetchLenses, 5000); const intervalId = setInterval(fetchLenses, 5000);
return () => clearInterval(intervalId); return () => clearInterval(intervalId);
} }
}, [user, isModalVisible]); }, [user, isModalVisible, selectedLens]);
const fetchLensWithCache = async () => { const fetchLensWithCache = async () => {
const cachedData = localStorage.getItem("lensData"); const cachedData = localStorage.getItem("lensData");
@ -107,7 +107,6 @@ const LensesPage = () => {
} }
}; };
const fetchViewModeFromCache = () => { const fetchViewModeFromCache = () => {
const cachedViewMode = localStorage.getItem("viewModeLenses"); const cachedViewMode = localStorage.getItem("viewModeLenses");
if (cachedViewMode) { if (cachedViewMode) {
@ -351,7 +350,7 @@ const LensesPage = () => {
<div style={{padding: 20}}> <div style={{padding: 20}}>
<Title level={1}><FolderViewOutlined/> Линзы</Title> <Title level={1}><FolderViewOutlined/> Линзы</Title>
<Row gutter={[16, 16]} style={{marginBottom: 20}}> <Row gutter={[16, 16]} style={{marginBottom: 20}}>
<Col xs={24} md={14} sm={10} xl={16}> <Col xs={24} md={24} sm={24} xl={15}>
<Input <Input
placeholder="Поиск линзы" placeholder="Поиск линзы"
value={searchText} value={searchText}
@ -360,7 +359,7 @@ const LensesPage = () => {
allowClear allowClear
/> />
</Col> </Col>
<Col xs={24} md={7} sm={10} xl={4}> <Col xs={24} md={12} sm={24} xl={5}>
<Button <Button
onClick={toggleAdvancedSearch} icon={showAdvancedSearch ? <UpOutlined/> : <DownOutlined/>} onClick={toggleAdvancedSearch} icon={showAdvancedSearch ? <UpOutlined/> : <DownOutlined/>}
block block
@ -368,7 +367,7 @@ const LensesPage = () => {
Расширенный поиск Расширенный поиск
</Button> </Button>
</Col> </Col>
<Col xs={24} md={4} sm={4} xl={4}> <Col xs={24} md={12} sm={24} xl={4}>
<SelectViewMode <SelectViewMode
viewMode={viewMode} viewMode={viewMode}
setViewMode={setViewMode} setViewMode={setViewMode}

View File

@ -55,11 +55,11 @@ const PatientsPage = () => {
}, []); }, []);
useEffect(() => { useEffect(() => {
if (!isModalVisible) { if (!isModalVisible && !selectedPatient) {
const intervalId = setInterval(fetchPatients, 5000); const intervalId = setInterval(fetchPatients, 5000);
return () => clearInterval(intervalId); return () => clearInterval(intervalId);
} }
}, [user, isModalVisible]); }, [user, isModalVisible, selectedPatient]);
const fetchPatientsWithCache = async () => { const fetchPatientsWithCache = async () => {
const cachedData = localStorage.getItem("patientsData"); const cachedData = localStorage.getItem("patientsData");
@ -359,7 +359,7 @@ const PatientsPage = () => {
} xl={ } xl={
viewMode === "tile" ? 3 : 5 viewMode === "tile" ? 3 : 5
} xxl={ } xxl={
viewMode === "tile" ? 3 : 4 viewMode === "tile" ? 3 : 5
}> }>
<SelectViewMode <SelectViewMode
viewMode={viewMode} viewMode={viewMode}