сделал просмотр приемов и запланированных приемов по клику на ячейку календаря
This commit is contained in:
parent
55369ac1a4
commit
b541bef7aa
@ -1,21 +1,19 @@
|
|||||||
import {Button, FloatButton, Result, Tabs, Typography} from "antd";
|
import { Button, FloatButton, Result, Tabs, Typography } from "antd";
|
||||||
import {Splitter} from "antd";
|
import { Splitter } from "antd";
|
||||||
import {CalendarOutlined, TableOutlined, MenuFoldOutlined, MenuUnfoldOutlined, PlusOutlined} from "@ant-design/icons";
|
import { CalendarOutlined, TableOutlined, MenuFoldOutlined, MenuUnfoldOutlined, PlusOutlined } from "@ant-design/icons";
|
||||||
import AppointmentsCalendarTab from "./Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx";
|
import AppointmentsCalendarTab from "./Components/AppointmentCalendarTab/AppointmentsCalendarTab.jsx";
|
||||||
import AppointmentsTableTab from "./Components/AppointmentTableTab/AppointmentsTableTab.jsx";
|
import AppointmentsTableTab from "./Components/AppointmentTableTab/AppointmentsTableTab.jsx";
|
||||||
import useAppointmentsUI from "./useAppointmentsUI.js";
|
import useAppointmentsUI from "./useAppointmentsUI.js";
|
||||||
import useAppointments from "./useAppointments.js";
|
import useAppointments from "./useAppointments.js";
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx";
|
import LoadingIndicator from "../../Widgets/LoadingIndicator.jsx";
|
||||||
import AppointmentFormModal
|
import AppointmentFormModal from "./Components/AppointmentFormModal/AppointmentFormModal.jsx";
|
||||||
from "./Components/AppointmentFormModal/AppointmentFormModal.jsx";
|
import { useDispatch } from "react-redux";
|
||||||
import {useDispatch} from "react-redux";
|
import { closeModal, openModal } from "../../../Redux/Slices/appointmentsSlice.js";
|
||||||
import {closeModal, openModal} from "../../../Redux/Slices/appointmentsSlice.js";
|
import AppointmentViewModal from "./Components/AppointmentViewModal/AppointmentViewModal.jsx";
|
||||||
import AppointmentViewModal
|
|
||||||
from "./Components/AppointmentViewModal/AppointmentViewModal.jsx";
|
|
||||||
import ScheduledAppointmentFormModal from "./Components/ScheduledAppintmentFormModal/ScheduledAppointmentFormModal.jsx";
|
import ScheduledAppointmentFormModal from "./Components/ScheduledAppintmentFormModal/ScheduledAppointmentFormModal.jsx";
|
||||||
import ScheduledAppointmentsViewModal
|
import ScheduledAppointmentsViewModal from "./Components/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx";
|
||||||
from "./Components/ScheduledAppointmentsViewModal/ScheduledAppointmentsViewModal.jsx";
|
import AppointmentsListModal from "./Components/AppointmentsListModal/AppointmentsListModal.jsx";
|
||||||
|
|
||||||
const AppointmentsPage = () => {
|
const AppointmentsPage = () => {
|
||||||
const appointmentsData = useAppointments();
|
const appointmentsData = useAppointments();
|
||||||
@ -30,14 +28,14 @@ const AppointmentsPage = () => {
|
|||||||
{
|
{
|
||||||
key: "1",
|
key: "1",
|
||||||
label: "Календарь приемов",
|
label: "Календарь приемов",
|
||||||
children: <AppointmentsCalendarTab/>,
|
children: <AppointmentsCalendarTab />,
|
||||||
icon: <CalendarOutlined/>,
|
icon: <CalendarOutlined />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "2",
|
key: "2",
|
||||||
label: "Таблица приемов",
|
label: "Таблица приемов",
|
||||||
children: <AppointmentsTableTab/>,
|
children: <AppointmentsTableTab />,
|
||||||
icon: <TableOutlined/>,
|
icon: <TableOutlined />,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -52,7 +50,7 @@ const AppointmentsPage = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{appointmentsData.isLoading ? (
|
{appointmentsData.isLoading ? (
|
||||||
<LoadingIndicator/>
|
<LoadingIndicator />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Splitter
|
<Splitter
|
||||||
@ -68,7 +66,7 @@ const AppointmentsPage = () => {
|
|||||||
min="25%"
|
min="25%"
|
||||||
max="90%"
|
max="90%"
|
||||||
>
|
>
|
||||||
<Tabs defaultActiveKey="1" items={items}/>
|
<Tabs defaultActiveKey="1" items={items} />
|
||||||
</Splitter.Panel>
|
</Splitter.Panel>
|
||||||
|
|
||||||
{appointmentsPageUI.showSplitterPanel && (
|
{appointmentsPageUI.showSplitterPanel && (
|
||||||
@ -83,7 +81,7 @@ const AppointmentsPage = () => {
|
|||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
{appointmentsPageUI.upcomingEvents.length ? (
|
{appointmentsPageUI.upcomingEvents.length ? (
|
||||||
<ul>
|
<ul>
|
||||||
{appointmentsPageUI.upcomingEvents.map(app => (
|
{appointmentsPageUI.upcomingEvents.map((app) => (
|
||||||
<li key={app.id}>
|
<li key={app.id}>
|
||||||
{dayjs(app.appointment_datetime || app.scheduled_datetime)
|
{dayjs(app.appointment_datetime || app.scheduled_datetime)
|
||||||
.format('DD.MM.YYYY HH:mm')} -
|
.format('DD.MM.YYYY HH:mm')} -
|
||||||
@ -105,7 +103,7 @@ const AppointmentsPage = () => {
|
|||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={appointmentsPageUI.handleToggleSider}
|
onClick={appointmentsPageUI.handleToggleSider}
|
||||||
icon={appointmentsPageUI.collapsed ? <MenuUnfoldOutlined/> : <MenuFoldOutlined/>}
|
icon={appointmentsPageUI.collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||||||
style={appointmentsPageUI.siderButtonStyle}
|
style={appointmentsPageUI.siderButtonStyle}
|
||||||
>
|
>
|
||||||
{appointmentsPageUI.siderButtonText}
|
{appointmentsPageUI.siderButtonText}
|
||||||
@ -115,32 +113,29 @@ const AppointmentsPage = () => {
|
|||||||
placement={"left"}
|
placement={"left"}
|
||||||
trigger="hover"
|
trigger="hover"
|
||||||
type="primary"
|
type="primary"
|
||||||
icon={<PlusOutlined/>}
|
icon={<PlusOutlined />}
|
||||||
tooltip="Создать"
|
tooltip="Создать"
|
||||||
>
|
>
|
||||||
<FloatButton
|
<FloatButton
|
||||||
icon={<PlusOutlined/>}
|
icon={<PlusOutlined />}
|
||||||
onClick={() => dispatch(openModal())}
|
onClick={() => dispatch(openModal())}
|
||||||
tooltip="Прием"
|
tooltip="Прием"
|
||||||
/>
|
/>
|
||||||
<FloatButton
|
<FloatButton
|
||||||
icon={<CalendarOutlined/>}
|
icon={<CalendarOutlined />}
|
||||||
onClick={appointmentsPageUI.openCreateScheduledAppointmentModal}
|
onClick={appointmentsPageUI.openCreateScheduledAppointmentModal}
|
||||||
tooltip="Запланированный прием"
|
tooltip="Запланированный прием"
|
||||||
/>
|
/>
|
||||||
</FloatButton.Group>
|
</FloatButton.Group>
|
||||||
|
|
||||||
<AppointmentFormModal
|
<AppointmentFormModal onCancel={handleCancelModal} />
|
||||||
onCancel={handleCancelModal}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AppointmentViewModal
|
<AppointmentViewModal
|
||||||
visible={appointmentsPageUI.selectedAppointment !== null}
|
visible={appointmentsPageUI.selectedAppointment !== null}
|
||||||
onCancel={appointmentsPageUI.handleCancelViewModal}
|
onCancel={appointmentsPageUI.handleCancelViewModal}
|
||||||
/>
|
/>
|
||||||
|
<ScheduledAppointmentFormModal />
|
||||||
<ScheduledAppointmentFormModal/>
|
<ScheduledAppointmentsViewModal />
|
||||||
<ScheduledAppointmentsViewModal/>
|
<AppointmentsListModal />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import {Calendar} from "antd";
|
import { Calendar } from "antd";
|
||||||
import 'dayjs/locale/ru';
|
import 'dayjs/locale/ru';
|
||||||
import CalendarCell from "../../../../Widgets/CalendarCell.jsx";
|
import CalendarCell from "../../../../Widgets/CalendarCell.jsx";
|
||||||
import useAppointments from "../../useAppointments.js";
|
import useAppointments from "../../useAppointments.js";
|
||||||
import useAppointmentCalendarUI from "./useAppointmentCalendarUI.js";
|
import useAppointmentCalendarUI from "./useAppointmentCalendarUI.js";
|
||||||
|
import AppointmentsListModal from "../AppointmentsListModal/AppointmentsListModal.jsx";
|
||||||
|
|
||||||
const AppointmentsCalendarTab = () => {
|
const AppointmentsCalendarTab = () => {
|
||||||
const appointmentsData = useAppointments();
|
const appointmentsData = useAppointments();
|
||||||
@ -40,6 +41,7 @@ const AppointmentsCalendarTab = () => {
|
|||||||
onSelect={appointmentsCalendarUI.onSelect}
|
onSelect={appointmentsCalendarUI.onSelect}
|
||||||
cellRender={dateCellRender}
|
cellRender={dateCellRender}
|
||||||
/>
|
/>
|
||||||
|
<AppointmentsListModal />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import {useDispatch, useSelector} from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import utc from "dayjs/plugin/utc";
|
import utc from "dayjs/plugin/utc";
|
||||||
import timezone from "dayjs/plugin/timezone";
|
import timezone from "dayjs/plugin/timezone";
|
||||||
import {Grid} from "antd";
|
import { Grid } from "antd";
|
||||||
import {
|
import {
|
||||||
openModal, setSelectedAppointment,
|
openAppointmentsListModal,
|
||||||
setSelectedAppointments,
|
setSelectedAppointment,
|
||||||
setSelectedScheduledAppointment,
|
setSelectedScheduledAppointment,
|
||||||
} from "../../../../../Redux/Slices/appointmentsSlice.js";
|
} from "../../../../../Redux/Slices/appointmentsSlice.js";
|
||||||
|
|
||||||
@ -13,31 +13,26 @@ dayjs.extend(utc);
|
|||||||
dayjs.extend(timezone);
|
dayjs.extend(timezone);
|
||||||
dayjs.tz.setDefault('Europe/Moscow');
|
dayjs.tz.setDefault('Europe/Moscow');
|
||||||
|
|
||||||
const {useBreakpoint} = Grid;
|
const { useBreakpoint } = Grid;
|
||||||
|
|
||||||
const useAppointmentCalendarUI = (appointments, scheduledAppointments) => {
|
const useAppointmentCalendarUI = (appointments, scheduledAppointments) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const selectedDate = dayjs.tz(useSelector(state => state.appointmentsUI.selectedDate), 'Europe/Moscow');
|
const selectedDate = dayjs.tz(useSelector((state) => state.appointmentsUI.selectedDate), 'Europe/Moscow');
|
||||||
|
|
||||||
const screens = useBreakpoint();
|
const screens = useBreakpoint();
|
||||||
const fullScreenCalendar = !screens.xs;
|
const fullScreenCalendar = !screens.xs;
|
||||||
|
|
||||||
const calendarContainerStyle = {padding: 20};
|
const calendarContainerStyle = { padding: 20 };
|
||||||
|
|
||||||
const onSelect = (date) => {
|
const onSelect = (date) => {
|
||||||
const selectedDateStr = date.format('YYYY-MM-DD');
|
const selectedDateStr = date.format('YYYY-MM-DD');
|
||||||
// dispatch(setSelectedDate(selectedDateStr));
|
const appointmentsForDate = appointments.filter((app) =>
|
||||||
|
|
||||||
const appointmentsForDate = appointments.filter(app =>
|
|
||||||
dayjs(app.appointment_datetime).format('YYYY-MM-DD') === selectedDateStr
|
dayjs(app.appointment_datetime).format('YYYY-MM-DD') === selectedDateStr
|
||||||
);
|
);
|
||||||
|
const scheduledForDate = scheduledAppointments.filter((app) =>
|
||||||
const scheduledForDate = scheduledAppointments.filter(app =>
|
|
||||||
dayjs(app.scheduled_datetime).format('YYYY-MM-DD') === selectedDateStr
|
dayjs(app.scheduled_datetime).format('YYYY-MM-DD') === selectedDateStr
|
||||||
);
|
);
|
||||||
|
dispatch(openAppointmentsListModal([...appointmentsForDate, ...scheduledForDate]));
|
||||||
dispatch(setSelectedAppointments([...appointmentsForDate, ...scheduledForDate]));
|
|
||||||
dispatch(openModal());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onOpenAppointmentModal = (appointment) => {
|
const onOpenAppointmentModal = (appointment) => {
|
||||||
@ -50,9 +45,8 @@ const useAppointmentCalendarUI = (appointments, scheduledAppointments) => {
|
|||||||
|
|
||||||
const getAppointmentsByListAndDate = (list, value, isScheduled = false) => {
|
const getAppointmentsByListAndDate = (list, value, isScheduled = false) => {
|
||||||
const date = value.format('YYYY-MM-DD');
|
const date = value.format('YYYY-MM-DD');
|
||||||
return list.filter(app =>
|
return list.filter((app) =>
|
||||||
dayjs(isScheduled ? app.scheduled_datetime : app.appointment_datetime)
|
dayjs(isScheduled ? app.scheduled_datetime : app.appointment_datetime).format('YYYY-MM-DD') === date
|
||||||
.format('YYYY-MM-DD') === date
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,78 @@
|
|||||||
|
import { Button, List, Modal, Typography } from "antd";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import {
|
||||||
|
closeAppointmentsListModal,
|
||||||
|
setSelectedAppointment,
|
||||||
|
setSelectedScheduledAppointment
|
||||||
|
} from "../../../../../Redux/Slices/appointmentsSlice.js";
|
||||||
|
|
||||||
|
const AppointmentsListModal = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const { appointmentsListModalVisible, selectedDateAppointments } = useSelector(
|
||||||
|
(state) => state.appointmentsUI
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
dispatch(closeAppointmentsListModal());
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleItemClick = (appointment) => {
|
||||||
|
if (appointment.appointment_datetime) {
|
||||||
|
dispatch(setSelectedAppointment(appointment));
|
||||||
|
} else {
|
||||||
|
dispatch(setSelectedScheduledAppointment(appointment));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title="Приемы на выбранную дату"
|
||||||
|
open={appointmentsListModalVisible}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
footer={null}
|
||||||
|
width={600}
|
||||||
|
>
|
||||||
|
<Typography.Title level={4}>Список приемов</Typography.Title>
|
||||||
|
{selectedDateAppointments.length ? (
|
||||||
|
<List
|
||||||
|
dataSource={selectedDateAppointments}
|
||||||
|
renderItem={(item) => (
|
||||||
|
<List.Item
|
||||||
|
onClick={() => handleItemClick(item)}
|
||||||
|
style={{ cursor: "pointer", padding: "8px 0" }}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<b>Время:</b>{" "}
|
||||||
|
{item.appointment_datetime
|
||||||
|
? dayjs(item.appointment_datetime).format("DD.MM.YYYY HH:mm")
|
||||||
|
: item.scheduled_datetime
|
||||||
|
? dayjs(item.scheduled_datetime).format("DD.MM.YYYY HH:mm")
|
||||||
|
: "Не указано"}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>Тип:</b>{" "}
|
||||||
|
{item.appointment_datetime ? "Прием" : "Запланированный прием"}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>Пациент:</b>{" "}
|
||||||
|
{item.patient
|
||||||
|
? `${item.patient.last_name} ${item.patient.first_name}`
|
||||||
|
: "Не указан"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<p>Нет приемов на эту дату</p>
|
||||||
|
)}
|
||||||
|
<Button onClick={handleCancel} style={{ marginTop: 16 }}>
|
||||||
|
Закрыть
|
||||||
|
</Button>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AppointmentsListModal;
|
||||||
@ -2,14 +2,15 @@ import { createSlice } from '@reduxjs/toolkit';
|
|||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
modalVisible: false,
|
modalVisible: false,
|
||||||
collapsed: true,
|
collapsed: false,
|
||||||
siderWidth: 300,
|
siderWidth: 300,
|
||||||
hovered: false,
|
hovered: false,
|
||||||
selectedAppointment: null,
|
selectedAppointment: null,
|
||||||
selectedScheduledAppointment: null,
|
selectedScheduledAppointment: null,
|
||||||
scheduledModalVisible: false,
|
scheduledModalVisible: false,
|
||||||
scheduledData: null,
|
scheduledData: null,
|
||||||
selectedAppointments: [], // Новое поле для хранения массива выбранных приемов
|
appointmentsListModalVisible: false,
|
||||||
|
selectedDateAppointments: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const appointmentsSlice = createSlice({
|
const appointmentsSlice = createSlice({
|
||||||
@ -47,8 +48,13 @@ const appointmentsSlice = createSlice({
|
|||||||
state.modalVisible = true;
|
state.modalVisible = true;
|
||||||
state.scheduledData = action.payload;
|
state.scheduledData = action.payload;
|
||||||
},
|
},
|
||||||
setSelectedAppointments(state, action) {
|
openAppointmentsListModal(state, action) {
|
||||||
state.selectedAppointments = action.payload;
|
state.appointmentsListModalVisible = true;
|
||||||
|
state.selectedDateAppointments = action.payload;
|
||||||
|
},
|
||||||
|
closeAppointmentsListModal(state) {
|
||||||
|
state.appointmentsListModalVisible = false;
|
||||||
|
state.selectedDateAppointments = [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -57,13 +63,15 @@ export const {
|
|||||||
openModal,
|
openModal,
|
||||||
closeModal,
|
closeModal,
|
||||||
toggleSider,
|
toggleSider,
|
||||||
|
setSiderWidth,
|
||||||
setHovered,
|
setHovered,
|
||||||
setSelectedAppointment,
|
setSelectedAppointment,
|
||||||
setSelectedScheduledAppointment,
|
setSelectedScheduledAppointment,
|
||||||
openScheduledModal,
|
openScheduledModal,
|
||||||
closeScheduledModal,
|
closeScheduledModal,
|
||||||
openModalWithScheduledData,
|
openModalWithScheduledData,
|
||||||
setSelectedAppointments,
|
openAppointmentsListModal,
|
||||||
|
closeAppointmentsListModal,
|
||||||
} = appointmentsSlice.actions;
|
} = appointmentsSlice.actions;
|
||||||
|
|
||||||
export default appointmentsSlice.reducer;
|
export default appointmentsSlice.reducer;
|
||||||
Loading…
x
Reference in New Issue
Block a user