diff --git a/web-app/src/AppRouter.jsx b/web-app/src/AppRouter.jsx index c9ab41f..f299e28 100644 --- a/web-app/src/AppRouter.jsx +++ b/web-app/src/AppRouter.jsx @@ -6,7 +6,7 @@ import PatientsPage from "./pages/PatientsPage.jsx"; import HomePage from "./pages/HomePage.jsx"; import LensesLayout from "./layouts/LensesLayout.jsx"; import IssuesPage from "./pages/IssuesPage.jsx"; -import AppointmentsPage from "./pages/AppointmentsPage.jsx"; +import AppointmentsLayout from "./layouts/AppointmentsLayout.jsx"; const AppRouter = () => ( @@ -18,7 +18,7 @@ const AppRouter = () => ( }/> }/> }/> - }/> + }/> }/> diff --git a/web-app/src/api/appointments/GetAllAppointments.jsx b/web-app/src/api/appointments/GetAllAppointments.jsx new file mode 100644 index 0000000..8b720f2 --- /dev/null +++ b/web-app/src/api/appointments/GetAllAppointments.jsx @@ -0,0 +1,21 @@ +import axios from "axios"; +import CONFIG from "../../core/Config.jsx"; + + +const getAllAppointments = async (token) => { + try { + const response = await axios.get(`${CONFIG.BASE_URL}/appointments/`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + return response.data; + } catch (error) { + if (error.status === 403 || error.status === 401) { + throw new Error("Ошибка авторизации: пользователь неайден или токен недействителен"); + } + throw new Error(error.message); + } +}; + +export default getAllAppointments; \ No newline at end of file diff --git a/web-app/src/components/sets/SetListCard.jsx b/web-app/src/components/sets/SetListCard.jsx index 20f84fb..3fa9316 100644 --- a/web-app/src/components/sets/SetListCard.jsx +++ b/web-app/src/components/sets/SetListCard.jsx @@ -3,8 +3,6 @@ import {Card, Modal, Popconfirm, Tooltip} from "antd"; import {DeleteOutlined, EditOutlined, PlusOutlined} from "@ant-design/icons"; const SetListCard = ({set, handleEditSet, handleDeleteSet, handleAppendSet}) => { - - const deleteSet = () => { handleDeleteSet(set.id); }; diff --git a/web-app/src/layouts/AppointmentsLayout.jsx b/web-app/src/layouts/AppointmentsLayout.jsx new file mode 100644 index 0000000..5355f76 --- /dev/null +++ b/web-app/src/layouts/AppointmentsLayout.jsx @@ -0,0 +1,34 @@ +import {useAuth} from "../AuthContext.jsx"; +import {useEffect, useState} from "react"; +import getAllAppointments from "../api/appointments/GetAllAppointments.jsx"; +import {notification, Tabs} from "antd"; +import AppointmentsCalendarPage from "../pages/appointments_layout/AppointmentsCalendarPage.jsx"; +import {CalendarOutlined, TableOutlined} from "@ant-design/icons"; +import AppointmentsTablePage from "../pages/appointments_layout/AppointmentsTablePage.jsx"; + + +const AppointmentsLayout = () => { + const items = [ + { + key: '1', + label: 'Календарь приемов', + children: , + icon: , + }, + { + key: '2', + label: 'Таблица приемов', + children: , + icon: , + } + ] + + return ( + + ); +}; + +export default AppointmentsLayout; \ No newline at end of file diff --git a/web-app/src/layouts/LensesLayout.jsx b/web-app/src/layouts/LensesLayout.jsx index 7e0774d..f51a060 100644 --- a/web-app/src/layouts/LensesLayout.jsx +++ b/web-app/src/layouts/LensesLayout.jsx @@ -1,9 +1,9 @@ import { Tabs } from "antd"; -import LensesPage from "../pages/LensesPage.jsx"; +import LensesPage from "../pages/lenses_layout/LensesPage.jsx"; import {FolderViewOutlined, SwitcherOutlined} from "@ant-design/icons"; -import SetLensesPage from "../pages/SetLensesPage.jsx"; +import SetLensesPage from "../pages/lenses_layout/SetLensesPage.jsx"; const items = [ diff --git a/web-app/src/pages/AppointmentsPage.jsx b/web-app/src/pages/AppointmentsPage.jsx deleted file mode 100644 index 65ddf0c..0000000 --- a/web-app/src/pages/AppointmentsPage.jsx +++ /dev/null @@ -1,11 +0,0 @@ - - - -const AppointmentsPage = () => { - return ( - <> - - ) -}; - -export default AppointmentsPage; \ No newline at end of file diff --git a/web-app/src/pages/PatientsPage.jsx b/web-app/src/pages/PatientsPage.jsx index 6d22535..f23735a 100644 --- a/web-app/src/pages/PatientsPage.jsx +++ b/web-app/src/pages/PatientsPage.jsx @@ -75,8 +75,6 @@ const PatientsPage = () => { }; const fetchPatients = async () => { - if (!user || !user.token) return; - try { const data = await getAllPatients(user.token); setPatients(data); diff --git a/web-app/src/pages/appointments_layout/AppointmentsCalendarPage.jsx b/web-app/src/pages/appointments_layout/AppointmentsCalendarPage.jsx new file mode 100644 index 0000000..29e4cdf --- /dev/null +++ b/web-app/src/pages/appointments_layout/AppointmentsCalendarPage.jsx @@ -0,0 +1,25 @@ +import {Calendar, Grid} from "antd"; +import {useState} from "react"; +import dayjs from "dayjs"; + +const {useBreakpoint} = Grid; + +const AppointmentsCalendarPage = () => { + const screens = useBreakpoint(); + + const [selectedDate, setSelectedDate] = useState(dayjs( + new Date() + )); + + return ( +
+ +
+ ); +}; + +export default AppointmentsCalendarPage; \ No newline at end of file diff --git a/web-app/src/pages/appointments_layout/AppointmentsTablePage.jsx b/web-app/src/pages/appointments_layout/AppointmentsTablePage.jsx new file mode 100644 index 0000000..f0ea018 --- /dev/null +++ b/web-app/src/pages/appointments_layout/AppointmentsTablePage.jsx @@ -0,0 +1,72 @@ +import {useAuth} from "../../AuthContext.jsx"; +import {useEffect, useState} from "react"; +import getAllAppointments from "../../api/appointments/GetAllAppointments.jsx"; +import {notification} from "antd"; + + +const AppointmentsTablePage = () => { + const {user} = useAuth(); + + const [appointments, setAppointments] = useState([]); + + const [current, setCurrent] = useState(1); + const [pageSize, setPageSize] = useState(10); + + const [isModalVisible, setIsModalVisible] = useState(false); + const [selectedAppointment, setSelectedAppointment] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetchAppointmentsWithCache(); + document.title = "Приемы"; + }, []); + + useEffect(() => { + if (!isModalVisible && !selectedAppointment) { + const intervalId = setInterval(fetchAppointments, 5000); + return () => clearInterval(intervalId); + } + }, [user, isModalVisible, selectedAppointment]); + + const fetchAppointmentsWithCache = async () => { + const cachedData = localStorage.getItem("appointmentsData"); + const cacheTimestamp = localStorage.getItem("appointmentsTimestamp"); + const currentTime = Date.now(); + if (cachedData && currentTime - cacheTimestamp < 60000) { + setAppointments(JSON.parse(cachedData)); + setLoading(false); + return; + } + + await fetchAppointments(); + }; + + const fetchAppointments = async () => { + try { + const data = await getAllAppointments(user.token); + setAppointments(data); + + localStorage.setItem("appointmentsData", JSON.stringify(data)); + localStorage.setItem("appointmentsTimestamp", Date.now().toString()); + } catch (error) { + console.log(error); + notification.error({ + message: "Ошибка загрузки данных", + description: "Проверьте подключение к сети.", + placement: "topRight", + }) + } + + if (loading) { + setLoading(false); + } + }; + + return ( +
+ +
+ ); +}; + +export default AppointmentsTablePage; \ No newline at end of file diff --git a/web-app/src/pages/LensesPage.jsx b/web-app/src/pages/lenses_layout/LensesPage.jsx similarity index 97% rename from web-app/src/pages/LensesPage.jsx rename to web-app/src/pages/lenses_layout/LensesPage.jsx index c91c266..8f9d235 100644 --- a/web-app/src/pages/LensesPage.jsx +++ b/web-app/src/pages/lenses_layout/LensesPage.jsx @@ -26,14 +26,14 @@ import { TableOutlined, BuildOutlined } from "@ant-design/icons"; -import LensCard from "../components/lenses/LensListCard.jsx"; -import getAllLenses from "../api/lenses/GetAllLenses.jsx"; -import addLens from "../api/lenses/AddLens.jsx"; -import updateLens from "../api/lenses/UpdateLens.jsx"; -import deleteLens from "../api/lenses/DeleteLens.jsx"; -import {useAuth} from "../AuthContext.jsx"; -import LensFormModal from "../components/lenses/LensFormModal.jsx"; -import SelectViewMode from "../components/SelectViewMode.jsx"; +import LensCard from "../../components/lenses/LensListCard.jsx"; +import getAllLenses from "../../api/lenses/GetAllLenses.jsx"; +import addLens from "../../api/lenses/AddLens.jsx"; +import updateLens from "../../api/lenses/UpdateLens.jsx"; +import deleteLens from "../../api/lenses/DeleteLens.jsx"; +import {useAuth} from "../../AuthContext.jsx"; +import LensFormModal from "../../components/lenses/LensFormModal.jsx"; +import SelectViewMode from "../../components/SelectViewMode.jsx"; const {Option} = Select; const {useBreakpoint} = Grid; diff --git a/web-app/src/pages/SetLensesPage.jsx b/web-app/src/pages/lenses_layout/SetLensesPage.jsx similarity index 93% rename from web-app/src/pages/SetLensesPage.jsx rename to web-app/src/pages/lenses_layout/SetLensesPage.jsx index c72d0ef..7b9f59d 100644 --- a/web-app/src/pages/SetLensesPage.jsx +++ b/web-app/src/pages/lenses_layout/SetLensesPage.jsx @@ -1,16 +1,16 @@ -import {useAuth} from "../AuthContext.jsx"; +import {useAuth} from "../../AuthContext.jsx"; import {useEffect, useState} from "react"; import {FloatButton, Input, List, notification, Row, Spin, Typography} from "antd"; -import getAllSets from "../api/sets/GetAllSets.jsx"; +import getAllSets from "../../api/sets/GetAllSets.jsx"; import {LoadingOutlined, PlusOutlined, SwitcherOutlined} from "@ant-design/icons"; -import SetListCard from "../components/sets/SetListCard.jsx"; -import SetFormModal from "../components/sets/SetFormModal.jsx"; -import updateSet from "../api/sets/UpdateSet.jsx"; -import addSet from "../api/sets/AddSet.jsx"; -import deleteSet from "../api/sets/DeleteSet.jsx"; -import addSetContent from "../api/set_content/AddSetContent.jsx"; -import updateSetContent from "../api/set_content/UpdateSetContent.jsx"; -import appendLensesFromSet from "../api/sets/AppendLensesFromSet.jsx"; +import SetListCard from "../../components/sets/SetListCard.jsx"; +import SetFormModal from "../../components/sets/SetFormModal.jsx"; +import updateSet from "../../api/sets/UpdateSet.jsx"; +import addSet from "../../api/sets/AddSet.jsx"; +import deleteSet from "../../api/sets/DeleteSet.jsx"; +import addSetContent from "../../api/set_content/AddSetContent.jsx"; +import updateSetContent from "../../api/set_content/UpdateSetContent.jsx"; +import appendLensesFromSet from "../../api/sets/AppendLensesFromSet.jsx"; const {Title} = Typography;