Перемещены и рефакторизованы виджеты и хуки для улучшения структуры. Обновлены стили и тексты в модальных окнах.
179 lines
9.4 KiB
JavaScript
179 lines
9.4 KiB
JavaScript
import {Button, FloatButton, List, Result, Space, Typography} from "antd";
|
||
import {Splitter} from "antd";
|
||
import {
|
||
CalendarOutlined,
|
||
MenuFoldOutlined,
|
||
MenuUnfoldOutlined,
|
||
PlusOutlined,
|
||
ClockCircleOutlined, DatabaseOutlined
|
||
} from "@ant-design/icons";
|
||
import AppointmentsCalendarTab from "./Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx";
|
||
import useAppointmentsUI from "./useAppointmentsUI.js";
|
||
import useAppointments from "./useAppointments.js";
|
||
import dayjs from 'dayjs';
|
||
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
||
import AppointmentFormModal from "../../Dummies/AppointmentFormModal/AppointmentFormModal.jsx";
|
||
import {useDispatch} from "react-redux";
|
||
import {
|
||
closeModal,
|
||
openModal,
|
||
setSelectedAppointment,
|
||
setSelectedScheduledAppointment
|
||
} from "../../../Redux/Slices/appointmentsSlice.js";
|
||
import AppointmentViewModal from "../../Widgets/AppointmentViewModal/AppointmentViewModal.jsx";
|
||
import ScheduledAppointmentFormModal from "../../Dummies/ScheduledAppintmentFormModal/ScheduledAppointmentFormModal.jsx";
|
||
import ScheduledAppointmentsViewModal
|
||
from "../../Widgets/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx";
|
||
import AppointmentsListModal from "./Components/AppointmentsListModal/AppointmentsListModal.jsx";
|
||
|
||
const AppointmentsPage = () => {
|
||
const appointmentsData = useAppointments();
|
||
const appointmentsPageUI = useAppointmentsUI(appointmentsData.appointments, appointmentsData.scheduledAppointments);
|
||
const dispatch = useDispatch();
|
||
|
||
const handleEventClick = (event) => {
|
||
if (event.appointment_datetime) {
|
||
dispatch(setSelectedAppointment(event));
|
||
} else {
|
||
dispatch(setSelectedScheduledAppointment(event));
|
||
}
|
||
};
|
||
|
||
if (appointmentsData.isError) return (
|
||
<Result
|
||
status="error"
|
||
title="Ошибка"
|
||
subTitle="Произошла ошибка в работе страницы"
|
||
/>
|
||
);
|
||
|
||
return (
|
||
<>
|
||
<Typography.Title level={1}><CalendarOutlined/> Приемы</Typography.Title>
|
||
{appointmentsData.isLoading ? (
|
||
<LoadingIndicator/>
|
||
) : (
|
||
<>
|
||
<Splitter
|
||
style={appointmentsPageUI.splitterStyle}
|
||
min={200}
|
||
max={400}
|
||
initial={appointmentsPageUI.siderWidth}
|
||
onChange={appointmentsPageUI.setSiderWidth}
|
||
>
|
||
<Splitter.Panel
|
||
style={appointmentsPageUI.splitterContentPanelStyle}
|
||
defaultSize="80%"
|
||
min="25%"
|
||
max="90%"
|
||
>
|
||
<AppointmentsCalendarTab/>
|
||
</Splitter.Panel>
|
||
|
||
{appointmentsPageUI.showSplitterPanel && (
|
||
<Splitter.Panel
|
||
style={appointmentsPageUI.splitterSiderPanelStyle}
|
||
defaultSize="20%"
|
||
min="20%"
|
||
max="75%"
|
||
>
|
||
<Typography.Title level={3} style={appointmentsPageUI.siderTitleStyle}>
|
||
Предстоящие события
|
||
</Typography.Title>
|
||
{appointmentsPageUI.upcomingEvents.length ? (
|
||
<List
|
||
dataSource={appointmentsPageUI.upcomingEvents.sort((a, b) =>
|
||
dayjs(a.appointment_datetime || a.scheduled_datetime).diff(
|
||
dayjs(b.appointment_datetime || b.scheduled_datetime)
|
||
)
|
||
)}
|
||
renderItem={(item) => (
|
||
<List.Item
|
||
onClick={() => handleEventClick(item)}
|
||
style={{
|
||
padding: "12px",
|
||
marginBottom: "8px",
|
||
borderRadius: "4px",
|
||
background: item.appointment_datetime ? "#e6f7ff" : "#f6ffed",
|
||
cursor: "pointer",
|
||
transition: "background 0.3s",
|
||
}}
|
||
onMouseEnter={(e) => (e.currentTarget.style.background = item.appointment_datetime ? "#d9efff" : "#efffdb")}
|
||
onMouseLeave={(e) => (e.currentTarget.style.background = item.appointment_datetime ? "#e6f7ff" : "#f6ffed")}
|
||
>
|
||
<Space direction="vertical" size={2}>
|
||
<Space>
|
||
{item.appointment_datetime ? (
|
||
<ClockCircleOutlined style={{color: "#1890ff"}}/>
|
||
) : (
|
||
<CalendarOutlined style={{color: "#52c41a"}}/>
|
||
)}
|
||
<Typography.Text strong>
|
||
{dayjs(item.appointment_datetime || item.scheduled_datetime).format('DD.MM.YYYY HH:mm')}
|
||
</Typography.Text>
|
||
</Space>
|
||
<Typography.Text>
|
||
{item.appointment_datetime ? 'Прием' : 'Запланировано'}
|
||
{item.patient ? ` - ${item.patient.last_name} ${item.patient.first_name}` : ''}
|
||
</Typography.Text>
|
||
<Typography.Text type="secondary">
|
||
Тип: {item.type?.title || 'Не указан'}
|
||
</Typography.Text>
|
||
{dayjs(item.appointment_datetime || item.scheduled_datetime).isSame(dayjs(), 'day') && (
|
||
<Typography.Text type="warning">Сегодня</Typography.Text>
|
||
)}
|
||
</Space>
|
||
</List.Item>
|
||
)}
|
||
/>
|
||
) : (
|
||
<Typography.Text type="secondary">Нет предстоящих событий</Typography.Text>
|
||
)}
|
||
</Splitter.Panel>
|
||
)}
|
||
</Splitter>
|
||
<div
|
||
style={appointmentsPageUI.siderButtonContainerStyle}
|
||
onMouseEnter={appointmentsPageUI.handleHoverSider}
|
||
onMouseLeave={appointmentsPageUI.handleLeaveSider}
|
||
>
|
||
<Button
|
||
type="primary"
|
||
onClick={appointmentsPageUI.handleToggleSider}
|
||
icon={appointmentsPageUI.collapsed ? <MenuUnfoldOutlined/> : <MenuFoldOutlined/>}
|
||
style={appointmentsPageUI.siderButtonStyle}
|
||
>
|
||
{appointmentsPageUI.siderButtonText}
|
||
</Button>
|
||
</div>
|
||
<FloatButton.Group
|
||
placement={"left"}
|
||
trigger="hover"
|
||
type="primary"
|
||
icon={<PlusOutlined/>}
|
||
tooltip="Создать"
|
||
>
|
||
<FloatButton
|
||
icon={<PlusOutlined/>}
|
||
onClick={() => dispatch(openModal())}
|
||
tooltip="Прием"
|
||
/>
|
||
<FloatButton
|
||
icon={<CalendarOutlined/>}
|
||
onClick={appointmentsPageUI.openCreateScheduledAppointmentModal}
|
||
tooltip="Запланированный прием"
|
||
/>
|
||
</FloatButton.Group>
|
||
|
||
<AppointmentFormModal/>
|
||
<AppointmentViewModal/>
|
||
<ScheduledAppointmentFormModal/>
|
||
<ScheduledAppointmentsViewModal/>
|
||
<AppointmentsListModal/>
|
||
</>
|
||
)}
|
||
</>
|
||
);
|
||
};
|
||
|
||
export default AppointmentsPage; |