refactor: appointments UI
Перемещены и переименованы компоненты Appointments.
This commit is contained in:
parent
c3d77738a7
commit
04242d63f1
@ -33,10 +33,8 @@ const MainLayout = () => {
|
||||
}
|
||||
|
||||
menuItems.push(
|
||||
mainLayoutData.getItem("Мой профиль", "profile", <UserOutlined/>, [
|
||||
mainLayoutData.getItem("Перейти в профиль", "/profile", <UserOutlined/>),
|
||||
mainLayoutData.getItem("Выйти", "logout", <LogoutOutlined/>)
|
||||
])
|
||||
mainLayoutData.getItem("Перейти в профиль", "/profile", <UserOutlined/>),
|
||||
mainLayoutData.getItem("Выйти", "logout", <LogoutOutlined/>)
|
||||
);
|
||||
|
||||
if (mainLayoutData.isUserError) {
|
||||
@ -45,48 +43,101 @@ const MainLayout = () => {
|
||||
|
||||
return (
|
||||
<Layout style={{minHeight: "100vh"}}>
|
||||
<Sider
|
||||
collapsible={!mainLayoutData.screens.xs}
|
||||
collapsed={mainLayoutData.collapsed}
|
||||
onCollapse={mainLayoutData.setCollapsed}
|
||||
style={{height: "100vh", position: "fixed", left: 0, overflow: "auto"}}
|
||||
>
|
||||
<div style={{display: "flex", justifyContent: "center", padding: 16}}>
|
||||
<img
|
||||
src="/logo_rounded.png"
|
||||
alt="Логотип"
|
||||
style={{width: mainLayoutData.collapsed ? 40 : 80, transition: "width 0.2s"}}
|
||||
/>
|
||||
</div>
|
||||
<Menu
|
||||
theme="dark"
|
||||
selectedKeys={[location.pathname]}
|
||||
mode="inline"
|
||||
items={menuItems}
|
||||
onClick={mainLayoutData.handleMenuClick}
|
||||
/>
|
||||
</Sider>
|
||||
{mainLayoutData.screens.xs ? (
|
||||
<>
|
||||
<Content style={{
|
||||
margin: "0 8px",
|
||||
padding: 24,
|
||||
flex: 1,
|
||||
overflow: "auto",
|
||||
background: "#fff",
|
||||
borderRadius: 8,
|
||||
marginTop: "8px"
|
||||
}}>
|
||||
{mainLayoutData.isUserLoading ? (
|
||||
<LoadingIndicator/>
|
||||
) : (
|
||||
<Outlet/>
|
||||
)}
|
||||
</Content>
|
||||
<Layout.Header style={{
|
||||
position: "fixed",
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "0 16px",
|
||||
background: "#001529",
|
||||
zIndex: 1000
|
||||
}}>
|
||||
<div style={{display: "flex", alignItems: "center", paddingRight: 16}}>
|
||||
<img
|
||||
src="/logo_rounded.png"
|
||||
alt="Логотип"
|
||||
style={{width: 40}}
|
||||
/>
|
||||
</div>
|
||||
<Menu
|
||||
theme="dark"
|
||||
mode="horizontal"
|
||||
selectedKeys={[mainLayoutData.location.pathname]}
|
||||
items={menuItems}
|
||||
onClick={mainLayoutData.handleMenuClick}
|
||||
style={{flex: 1, minWidth: 0}}
|
||||
/>
|
||||
</Layout.Header>
|
||||
<Footer style={{textAlign: "center", padding: "12px 0", marginBottom: 48}}>
|
||||
Visus+ © {new Date().getFullYear()}
|
||||
</Footer>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Sider
|
||||
collapsible={!mainLayoutData.screens.xs}
|
||||
collapsed={mainLayoutData.collapsed}
|
||||
onCollapse={mainLayoutData.setCollapsed}
|
||||
style={{height: "100vh", position: "fixed", left: 0, overflow: "auto"}}
|
||||
>
|
||||
<div style={{display: "flex", justifyContent: "center", padding: 16}}>
|
||||
<img
|
||||
src="/logo_rounded.png"
|
||||
alt="Логотип"
|
||||
style={{width: mainLayoutData.collapsed ? 40 : 80, transition: "width 0.2s"}}
|
||||
/>
|
||||
</div>
|
||||
<Menu
|
||||
theme="dark"
|
||||
selectedKeys={[location.pathname]}
|
||||
mode="inline"
|
||||
items={menuItems}
|
||||
onClick={mainLayoutData.handleMenuClick}
|
||||
/>
|
||||
</Sider>
|
||||
|
||||
<Layout
|
||||
style={{marginLeft: mainLayoutData.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"
|
||||
}}>
|
||||
{mainLayoutData.isUserLoading ? (
|
||||
<LoadingIndicator/>
|
||||
) : (
|
||||
<Outlet/>
|
||||
)}
|
||||
</Content>
|
||||
<Footer style={{textAlign: "center"}}>Visus+ © {new Date().getFullYear()}</Footer>
|
||||
</Layout>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Layout
|
||||
style={{marginLeft: mainLayoutData.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"
|
||||
}}>
|
||||
{mainLayoutData.isUserLoading ? (
|
||||
<LoadingIndicator/>
|
||||
) : (
|
||||
<Outlet/>
|
||||
)}
|
||||
</Content>
|
||||
<Footer style={{textAlign: "center"}}>Visus+ © {new Date().getFullYear()}</Footer>
|
||||
</Layout>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
@ -7,7 +7,7 @@ import {
|
||||
PlusOutlined,
|
||||
ClockCircleOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import AppointmentsCalendarTab from "./Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx";
|
||||
import AppointmentsCalendar from "./Components/AppointmentCalendar/AppointmentsCalendar.jsx";
|
||||
import useAppointments from "./useAppointments.js";
|
||||
import dayjs from 'dayjs';
|
||||
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
||||
@ -87,7 +87,7 @@ const AppointmentsPage = () => {
|
||||
min="25%"
|
||||
max="90%"
|
||||
>
|
||||
<AppointmentsCalendarTab
|
||||
<AppointmentsCalendar
|
||||
currentMonth={currentMonth}
|
||||
onMonthChange={handleMonthChange}
|
||||
appointments={appointments} // Добавляем
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import {Calendar} from "antd";
|
||||
import "dayjs/locale/ru";
|
||||
import CalendarCell from "../CalendarCell/CalendarCell.jsx";
|
||||
import useAppointmentCalendarUI from "./useAppointmentCalendarUI.js";
|
||||
import useAppointmentCalendar from "./useAppointmentCalendar.js";
|
||||
import AppointmentsListModal from "../AppointmentsListModal/AppointmentsListModal.jsx";
|
||||
import dayjs from "dayjs";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const AppointmentsCalendarTab = ({currentMonth, onMonthChange, appointments, scheduledAppointments}) => {
|
||||
const appointmentsCalendarUI = useAppointmentCalendarUI(appointments, scheduledAppointments);
|
||||
const AppointmentsCalendar = ({currentMonth, onMonthChange, appointments, scheduledAppointments}) => {
|
||||
const appointmentsCalendarUI = useAppointmentCalendar(appointments, scheduledAppointments);
|
||||
|
||||
const dateCellRender = (value) => {
|
||||
const appointmentsForDate = appointmentsCalendarUI.getAppointmentsByListAndDate(
|
||||
@ -39,12 +39,11 @@ const AppointmentsCalendarTab = ({currentMonth, onMonthChange, appointments, sch
|
||||
<div style={appointmentsCalendarUI.calendarContainerStyle}>
|
||||
<Calendar
|
||||
fullscreen={appointmentsCalendarUI.fullScreenCalendar}
|
||||
value={currentMonth} // Используем currentMonth вместо selectedDate
|
||||
onSelect={appointmentsCalendarUI.onSelect}
|
||||
value={currentMonth}
|
||||
onPanelChange={(value, mode) => {
|
||||
appointmentsCalendarUI.onPanelChange(value, mode);
|
||||
if (mode === "month") {
|
||||
onMonthChange(value); // Вызываем onMonthChange при смене месяца
|
||||
onMonthChange(value);
|
||||
}
|
||||
}}
|
||||
cellRender={dateCellRender}
|
||||
@ -54,11 +53,11 @@ const AppointmentsCalendarTab = ({currentMonth, onMonthChange, appointments, sch
|
||||
);
|
||||
};
|
||||
|
||||
AppointmentsCalendarTab.propTypes = {
|
||||
AppointmentsCalendar.propTypes = {
|
||||
currentMonth: PropTypes.object.isRequired,
|
||||
onMonthChange: PropTypes.func.isRequired,
|
||||
appointments: PropTypes.array.isRequired,
|
||||
scheduledAppointments: PropTypes.array.isRequired,
|
||||
};
|
||||
|
||||
export default AppointmentsCalendarTab;
|
||||
export default AppointmentsCalendar;
|
||||
@ -17,7 +17,7 @@ dayjs.tz.setDefault("Europe/Moscow");
|
||||
|
||||
const { useBreakpoint } = Grid;
|
||||
|
||||
const useAppointmentCalendarUI = (appointments, scheduledAppointments) => {
|
||||
const useAppointmentCalendar = (appointments, scheduledAppointments) => {
|
||||
const dispatch = useDispatch();
|
||||
const selectedDate = dayjs.tz(useSelector((state) => state.appointmentsUI.selectedDate), "Europe/Moscow");
|
||||
|
||||
@ -75,4 +75,4 @@ const useAppointmentCalendarUI = (appointments, scheduledAppointments) => {
|
||||
};
|
||||
};
|
||||
|
||||
export default useAppointmentCalendarUI;
|
||||
export default useAppointmentCalendar;
|
||||
@ -2,7 +2,7 @@ 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";
|
||||
import useCalendarCell from "./useCalendarCell.js";
|
||||
|
||||
const CalendarCell = ({allAppointments, onCellClick, onItemClick}) => {
|
||||
const {
|
||||
@ -18,7 +18,7 @@ const CalendarCell = ({allAppointments, onCellClick, onItemClick}) => {
|
||||
getBadgeText,
|
||||
getTagColor,
|
||||
getBadgeStatus,
|
||||
} = useCalendarCellUI();
|
||||
} = useCalendarCell();
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const useCalendarCellUI = () => {
|
||||
const useCalendarCell = () => {
|
||||
const containerRef = useRef(null);
|
||||
const [isCompressed, setIsCompressed] = useState(false);
|
||||
const COMPRESSION_THRESHOLD = 70;
|
||||
@ -53,7 +53,7 @@ const useCalendarCellUI = () => {
|
||||
|
||||
const compressedCountStyle = {
|
||||
position: "absolute",
|
||||
top: 2,
|
||||
bottom: 12,
|
||||
right: 2,
|
||||
fontSize: 10,
|
||||
fontWeight: "bold",
|
||||
@ -108,4 +108,4 @@ const useCalendarCellUI = () => {
|
||||
};
|
||||
};
|
||||
|
||||
export default useCalendarCellUI;
|
||||
export default useCalendarCell;
|
||||
@ -1,12 +1,12 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { notification } from "antd";
|
||||
import { Grid } from "antd";
|
||||
import {useEffect, useMemo, useState} from "react";
|
||||
import {useDispatch, useSelector} from "react-redux";
|
||||
import {notification} from "antd";
|
||||
import {Grid} from "antd";
|
||||
import {
|
||||
useGetAppointmentsQuery,
|
||||
useGetUpcomingAppointmentsQuery,
|
||||
} from "../../../Api/appointmentsApi.js";
|
||||
import { useGetAllPatientsQuery } from "../../../Api/patientsApi.js";
|
||||
import {useGetAllPatientsQuery} from "../../../Api/patientsApi.js";
|
||||
import {
|
||||
openModal,
|
||||
openScheduledModal,
|
||||
@ -26,12 +26,12 @@ import timezone from "dayjs/plugin/timezone";
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
|
||||
const { useBreakpoint } = Grid;
|
||||
const {useBreakpoint} = Grid;
|
||||
|
||||
const useAppointments = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { userData } = useSelector(state => state.auth);
|
||||
const { collapsed, siderWidth, hovered, selectedAppointment } = useSelector(state => state.appointmentsUI);
|
||||
const {userData} = useSelector(state => state.auth);
|
||||
const {collapsed, siderWidth, hovered, selectedAppointment} = useSelector(state => state.appointmentsUI);
|
||||
const screens = useBreakpoint();
|
||||
|
||||
const [currentMonth, setCurrentMonth] = useState(dayjs().startOf('month'));
|
||||
@ -47,7 +47,7 @@ const useAppointments = () => {
|
||||
data: appointments = [],
|
||||
isLoading: isLoadingAppointments,
|
||||
isError: isErrorAppointments,
|
||||
} = useGetAppointmentsQuery({ doctor_id: userData.id, start_date: startDate, end_date: endDate }, {
|
||||
} = useGetAppointmentsQuery({doctor_id: userData.id, start_date: startDate, end_date: endDate}, {
|
||||
pollingInterval: 60000,
|
||||
skip: !userData.id,
|
||||
});
|
||||
@ -56,7 +56,7 @@ const useAppointments = () => {
|
||||
data: scheduledAppointments = [],
|
||||
isLoading: isLoadingScheduledAppointments,
|
||||
isError: isErrorScheduledAppointments,
|
||||
} = useGetScheduledAppointmentsQuery({ doctor_id: userData.id, start_date: startDate, end_date: endDate }, {
|
||||
} = useGetScheduledAppointmentsQuery({doctor_id: userData.id, start_date: startDate, end_date: endDate}, {
|
||||
pollingInterval: 60000,
|
||||
skip: !userData.id,
|
||||
});
|
||||
@ -90,10 +90,10 @@ const useAppointments = () => {
|
||||
|
||||
const [localSiderWidth, setLocalSiderWidth] = useState(siderWidth);
|
||||
|
||||
const splitterStyle = { flex: 1 };
|
||||
const splitterContentPanelStyle = { padding: 16 };
|
||||
const splitterSiderPanelStyle = { padding: "16px", borderLeft: "1px solid #ddd", overflowY: "auto" };
|
||||
const siderTitleStyle = { marginBottom: 36 };
|
||||
const splitterStyle = {flex: 1};
|
||||
const splitterContentPanelStyle = {padding: 16};
|
||||
const splitterSiderPanelStyle = {padding: "16px", borderLeft: "1px solid #ddd", overflowY: "auto"};
|
||||
const siderTitleStyle = {marginBottom: 36};
|
||||
const siderButtonContainerStyle = {
|
||||
position: "fixed",
|
||||
right: 0,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user