feat: Добавлена фильтрация пациентов по поисковой строке
This commit is contained in:
parent
a2635ed03e
commit
1d8888da87
@ -9,28 +9,28 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
Typography,
|
Typography,
|
||||||
Result, Tooltip
|
Result,
|
||||||
|
Tooltip
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import {
|
import {
|
||||||
BuildOutlined,
|
BuildOutlined,
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
SortAscendingOutlined,
|
SortAscendingOutlined,
|
||||||
SortDescendingOutlined, TableOutlined,
|
SortDescendingOutlined,
|
||||||
TeamOutlined
|
TableOutlined,
|
||||||
|
TeamOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import PatientListCard from "../../Dummies/PatientListCard.jsx";
|
import PatientListCard from "../../Dummies/PatientListCard.jsx";
|
||||||
import PatientFormModal from "../../Dummies/PatientFormModal/PatientFormModal.jsx";
|
import PatientFormModal from "../../Dummies/PatientFormModal/PatientFormModal.jsx";
|
||||||
import SelectViewMode from "../../Widgets/SelectViewMode/SelectViewMode.jsx";
|
import SelectViewMode from "../../Widgets/SelectViewMode/SelectViewMode.jsx";
|
||||||
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
||||||
import usePatients from "./usePatients.js";
|
import usePatients from "./usePatients.js";
|
||||||
import usePatientsUI from "./usePatientsUI.js";
|
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
const {Title} = Typography;
|
const {Title} = Typography;
|
||||||
|
|
||||||
const PatientsPage = () => {
|
const PatientsPage = () => {
|
||||||
const patientsData = usePatients();
|
const patientsData = usePatients();
|
||||||
const patientsUI = usePatientsUI(patientsData.patients, patientsData.totalCount);
|
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
@ -55,7 +55,7 @@ const PatientsPage = () => {
|
|||||||
title: "Дата рождения",
|
title: "Дата рождения",
|
||||||
dataIndex: "birthday",
|
dataIndex: "birthday",
|
||||||
sorter: true,
|
sorter: true,
|
||||||
render: patientsUI.formatDate,
|
render: patientsData.formatDate,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Телефон",
|
title: "Телефон",
|
||||||
@ -71,7 +71,7 @@ const PatientsPage = () => {
|
|||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<Row gutter={[8, 8]}>
|
<Row gutter={[8, 8]}>
|
||||||
<Col xs={24} xl={12}>
|
<Col xs={24} xl={12}>
|
||||||
<Button block onClick={() => patientsUI.handleEditPatient(record)}>Изменить</Button>
|
<Button block onClick={() => patientsData.handleEditPatient(record)}>Изменить</Button>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={24} xl={12}>
|
<Col xs={24} xl={12}>
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
@ -92,12 +92,12 @@ const PatientsPage = () => {
|
|||||||
{
|
{
|
||||||
value: "tile",
|
value: "tile",
|
||||||
label: "Плитка",
|
label: "Плитка",
|
||||||
icon: <BuildOutlined style={patientsUI.viewModIconStyle}/>
|
icon: <BuildOutlined style={patientsData.viewModIconStyle}/>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "table",
|
value: "table",
|
||||||
label: "Таблица",
|
label: "Таблица",
|
||||||
icon: <TableOutlined style={patientsUI.viewModIconStyle}/>
|
icon: <TableOutlined style={patientsData.viewModIconStyle}/>
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -110,25 +110,27 @@ const PatientsPage = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={patientsUI.containerStyle}>
|
<div style={patientsData.containerStyle}>
|
||||||
<Title level={1}><TeamOutlined/> Пациенты</Title>
|
<Title level={1}><TeamOutlined/> Пациенты</Title>
|
||||||
<Row gutter={[16, 16]} style={patientsUI.filterBarStyle}>
|
<Row gutter={[16, 16]} style={patientsData.filterBarStyle}>
|
||||||
<Col xs={24} md={14} sm={10} xl={18} xxl={19}>
|
<Col xs={24} md={14} sm={10} xl={18} xxl={19}>
|
||||||
<Input
|
<Input
|
||||||
placeholder="Поиск пациента"
|
placeholder="Поиск пациента"
|
||||||
value={patientsUI.searchText}
|
value={patientsData.searchText}
|
||||||
onChange={(e) => patientsUI.handleSetSearchText(e.target.value)}
|
onChange={(e) => patientsData.handleSetSearchText(e.target.value)}
|
||||||
style={patientsUI.formItemStyle}
|
onPressEnter={patientsData.handleSearch}
|
||||||
|
style={patientsData.formItemStyle}
|
||||||
allowClear
|
allowClear
|
||||||
|
onClear={patientsData.handleClearSearch}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
{patientsUI.viewMode === "tile" && (
|
{patientsData.viewMode === "tile" && (
|
||||||
<Col xs={24} md={5} sm={6} xl={3} xxl={2}>
|
<Col xs={24} md={5} sm={6} xl={3} xxl={2}>
|
||||||
<Tooltip title={"Сортировка пациентов"}>
|
<Tooltip title={"Сортировка пациентов"}>
|
||||||
<Select
|
<Select
|
||||||
value={patientsUI.sortOrder}
|
value={patientsData.sortOrder}
|
||||||
onChange={patientsUI.handleSetSortOrder}
|
onChange={patientsData.handleSetSortOrder}
|
||||||
style={patientsUI.formItemStyle}
|
style={patientsData.formItemStyle}
|
||||||
>
|
>
|
||||||
<Option value="asc"><SortAscendingOutlined/> А-Я</Option>
|
<Option value="asc"><SortAscendingOutlined/> А-Я</Option>
|
||||||
<Option value="desc"><SortDescendingOutlined/> Я-А</Option>
|
<Option value="desc"><SortDescendingOutlined/> Я-А</Option>
|
||||||
@ -136,13 +138,13 @@ const PatientsPage = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
<Col xs={24} md={patientsUI.viewMode === "tile" ? 5 : 10}
|
<Col xs={24} md={patientsData.viewMode === "tile" ? 5 : 10}
|
||||||
sm={patientsUI.viewMode === "tile" ? 8 : 14}
|
sm={patientsData.viewMode === "tile" ? 8 : 14}
|
||||||
xl={patientsUI.viewMode === "tile" ? 3 : 5}
|
xl={patientsData.viewMode === "tile" ? 3 : 5}
|
||||||
xxl={patientsUI.viewMode === "tile" ? 3 : 5}>
|
xxl={patientsData.viewMode === "tile" ? 3 : 5}>
|
||||||
<SelectViewMode
|
<SelectViewMode
|
||||||
viewMode={patientsUI.viewMode}
|
viewMode={patientsData.viewMode}
|
||||||
setViewMode={patientsUI.handleSetViewMode}
|
setViewMode={patientsData.handleSetViewMode}
|
||||||
localStorageKey={"viewModePatients"}
|
localStorageKey={"viewModePatients"}
|
||||||
toolTipText={"Формат отображения пациентов"}
|
toolTipText={"Формат отображения пациентов"}
|
||||||
viewModes={viewModes}
|
viewModes={viewModes}
|
||||||
@ -150,33 +152,33 @@ const PatientsPage = () => {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
{patientsData.isLoading ? <LoadingIndicator/> : patientsUI.viewMode === "tile" ? (
|
{patientsData.isLoading ? <LoadingIndicator/> : patientsData.viewMode === "tile" ? (
|
||||||
<List
|
<List
|
||||||
grid={{gutter: 16, column: 3}}
|
grid={{gutter: 16, column: 3}}
|
||||||
dataSource={patientsUI.filteredPatients}
|
dataSource={patientsData.filteredPatients}
|
||||||
renderItem={patient => (
|
renderItem={patient => (
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<PatientListCard
|
<PatientListCard
|
||||||
patient={patient}
|
patient={patient}
|
||||||
handleEditPatient={patientsUI.handleEditPatient}
|
handleEditPatient={patientsData.handleEditPatient}
|
||||||
handleDeletePatient={patientsData.handleDeletePatient}
|
handleDeletePatient={patientsData.handleDeletePatient}
|
||||||
/>
|
/>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
)}
|
)}
|
||||||
pagination={patientsUI.pagination}
|
pagination={patientsData.pagination}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Table
|
<Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
dataSource={patientsUI.filteredPatients}
|
dataSource={patientsData.filteredPatients}
|
||||||
pagination={patientsUI.pagination}
|
pagination={patientsData.pagination}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<FloatButton
|
<FloatButton
|
||||||
icon={<PlusOutlined/>}
|
icon={<PlusOutlined/>}
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={patientsUI.handleAddPatient}
|
onClick={patientsData.handleAddPatient}
|
||||||
tooltip="Добавить пациента"
|
tooltip="Добавить пациента"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@ -1,22 +1,64 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { notification } from "antd";
|
import { notification } from "antd";
|
||||||
import {
|
import {
|
||||||
useDeletePatientMutation,
|
|
||||||
useGetPatientsQuery,
|
useGetPatientsQuery,
|
||||||
|
useDeletePatientMutation,
|
||||||
} from "../../../Api/patientsApi.js";
|
} from "../../../Api/patientsApi.js";
|
||||||
import { useSelector } from "react-redux";
|
import {
|
||||||
|
closeModal,
|
||||||
|
openModal,
|
||||||
|
selectPatient,
|
||||||
|
setCurrentPage,
|
||||||
|
setPageSize,
|
||||||
|
setSortOrder,
|
||||||
|
setViewMode
|
||||||
|
} from "../../../Redux/Slices/patientsSlice.js";
|
||||||
|
import { getCachedInfo } from "../../../Utils/cachedInfoUtils.js";
|
||||||
|
|
||||||
const usePatients = () => {
|
const usePatients = () => {
|
||||||
const { currentPage, pageSize, searchText } = useSelector(state => state.patientsUI);
|
const dispatch = useDispatch();
|
||||||
|
const {
|
||||||
|
sortOrder,
|
||||||
|
viewMode,
|
||||||
|
isModalVisible,
|
||||||
|
currentPage,
|
||||||
|
pageSize,
|
||||||
|
} = useSelector(state => state.patientsUI);
|
||||||
|
|
||||||
|
const [tempSearchText, setTempSearchText] = useState("");
|
||||||
|
|
||||||
const { data = { patients: [], total_count: 0 }, isLoading, isError } = useGetPatientsQuery(
|
const { data = { patients: [], total_count: 0 }, isLoading, isError } = useGetPatientsQuery(
|
||||||
{ page: currentPage, pageSize, search: searchText },
|
{ page: currentPage, pageSize, search: tempSearchText || undefined },
|
||||||
{
|
{
|
||||||
pollingInterval: 20000,
|
pollingInterval: 20000, // Автообновление каждые 20 секунд
|
||||||
|
refetchOnMountOrArgChange: true, // Обновление при изменении параметров
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const [deletePatient] = useDeletePatientMutation();
|
const [deletePatient] = useDeletePatientMutation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = "Пациенты";
|
||||||
|
const cachedViewMode = getCachedInfo("viewModePatients");
|
||||||
|
if (cachedViewMode) dispatch(setViewMode(cachedViewMode));
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const containerStyle = { padding: 20 };
|
||||||
|
const filterBarStyle = { marginBottom: 20 };
|
||||||
|
const formItemStyle = { width: "100%" };
|
||||||
|
const viewModIconStyle = { marginRight: 8 };
|
||||||
|
|
||||||
|
const handleSetTempSearchText = (value) => {
|
||||||
|
setTempSearchText(value);
|
||||||
|
dispatch(setCurrentPage(1)); // Сбрасываем на первую страницу при изменении поиска
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearSearch = () => {
|
||||||
|
setTempSearchText("");
|
||||||
|
dispatch(setCurrentPage(1));
|
||||||
|
};
|
||||||
|
|
||||||
const handleDeletePatient = async (patientId) => {
|
const handleDeletePatient = async (patientId) => {
|
||||||
try {
|
try {
|
||||||
await deletePatient(patientId).unwrap();
|
await deletePatient(patientId).unwrap();
|
||||||
@ -34,12 +76,67 @@ const usePatients = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSetSortOrder = (value) => dispatch(setSortOrder(value));
|
||||||
|
const handleSetCurrentPage = (page) => dispatch(setCurrentPage(page));
|
||||||
|
const handleSetPageSize = (size) => dispatch(setPageSize(size));
|
||||||
|
const handleSetViewMode = (mode) => dispatch(setViewMode(mode));
|
||||||
|
const handleCloseModal = () => dispatch(closeModal());
|
||||||
|
|
||||||
|
const handlePaginationChange = (page, pageSize) => {
|
||||||
|
handleSetCurrentPage(page);
|
||||||
|
handleSetPageSize(pageSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddPatient = () => {
|
||||||
|
dispatch(selectPatient(null));
|
||||||
|
dispatch(openModal());
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditPatient = (patient) => {
|
||||||
|
dispatch(selectPatient(patient));
|
||||||
|
dispatch(openModal());
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDate = (date) => new Date(date).toLocaleDateString();
|
||||||
|
|
||||||
|
const pagination = {
|
||||||
|
current: currentPage,
|
||||||
|
pageSize: pageSize,
|
||||||
|
total: data.total_count,
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: ["5", "10", "20", "50"],
|
||||||
|
onChange: (page, newPageSize) => {
|
||||||
|
handlePaginationChange(page, newPageSize);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
searchText: tempSearchText,
|
||||||
|
sortOrder,
|
||||||
|
viewMode,
|
||||||
|
isModalVisible,
|
||||||
|
currentPage,
|
||||||
|
pageSize,
|
||||||
|
containerStyle,
|
||||||
|
filterBarStyle,
|
||||||
|
formItemStyle,
|
||||||
|
viewModIconStyle,
|
||||||
|
pagination,
|
||||||
patients: data.patients,
|
patients: data.patients,
|
||||||
totalCount: data.total_count,
|
totalCount: data.total_count,
|
||||||
isLoading,
|
isLoading,
|
||||||
isError,
|
isError,
|
||||||
|
filteredPatients: data.patients.map(p => ({ ...p, key: p.id })),
|
||||||
|
handleSetSearchText: handleSetTempSearchText,
|
||||||
|
handleClearSearch,
|
||||||
handleDeletePatient,
|
handleDeletePatient,
|
||||||
|
handleSetSortOrder,
|
||||||
|
handleSetViewMode,
|
||||||
|
handleCloseModal,
|
||||||
|
handleAddPatient,
|
||||||
|
handleEditPatient,
|
||||||
|
formatDate,
|
||||||
|
handlePaginationChange,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,100 +0,0 @@
|
|||||||
import { useEffect } from "react";
|
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
|
||||||
import { debounce } from "lodash";
|
|
||||||
import {
|
|
||||||
closeModal,
|
|
||||||
openModal,
|
|
||||||
selectPatient,
|
|
||||||
setCurrentPage,
|
|
||||||
setPageSize,
|
|
||||||
setSearchText,
|
|
||||||
setSortOrder,
|
|
||||||
setViewMode
|
|
||||||
} from "../../../Redux/Slices/patientsSlice.js";
|
|
||||||
import { getCachedInfo } from "../../../Utils/cachedInfoUtils.js";
|
|
||||||
|
|
||||||
const usePatientsUI = (patients, totalCount) => {
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
const {
|
|
||||||
searchText,
|
|
||||||
sortOrder,
|
|
||||||
viewMode,
|
|
||||||
isModalVisible,
|
|
||||||
currentPage,
|
|
||||||
pageSize,
|
|
||||||
} = useSelector(state => state.patientsUI);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
document.title = "Пациенты";
|
|
||||||
const cachedViewMode = getCachedInfo("viewModePatients");
|
|
||||||
if (cachedViewMode) dispatch(setViewMode(cachedViewMode));
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
const containerStyle = { padding: 20 };
|
|
||||||
const filterBarStyle = { marginBottom: 20 };
|
|
||||||
const formItemStyle = { width: "100%" };
|
|
||||||
const viewModIconStyle = { marginRight: 8 };
|
|
||||||
|
|
||||||
const handleSetSearchText = debounce((value) => {
|
|
||||||
dispatch(setSearchText(value));
|
|
||||||
dispatch(setCurrentPage(1)); // Сбрасываем на первую страницу при новом поиске
|
|
||||||
}, 300);
|
|
||||||
const handleSetSortOrder = (value) => dispatch(setSortOrder(value));
|
|
||||||
const handleSetCurrentPage = (page) => dispatch(setCurrentPage(page));
|
|
||||||
const handleSetPageSize = (size) => dispatch(setPageSize(size));
|
|
||||||
const handleSetViewMode = (mode) => dispatch(setViewMode(mode));
|
|
||||||
const handleCloseModal = () => dispatch(closeModal());
|
|
||||||
|
|
||||||
const handlePaginationChange = (page, pageSize) => {
|
|
||||||
handleSetCurrentPage(page);
|
|
||||||
handleSetPageSize(pageSize);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleAddPatient = () => {
|
|
||||||
dispatch(selectPatient(null));
|
|
||||||
dispatch(openModal());
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEditPatient = (patient) => {
|
|
||||||
dispatch(selectPatient(patient));
|
|
||||||
dispatch(openModal());
|
|
||||||
};
|
|
||||||
|
|
||||||
const formatDate = (date) => new Date(date).toLocaleDateString();
|
|
||||||
|
|
||||||
const pagination = {
|
|
||||||
current: currentPage,
|
|
||||||
pageSize: pageSize,
|
|
||||||
total: totalCount,
|
|
||||||
showSizeChanger: true,
|
|
||||||
pageSizeOptions: ["5", "10", "20", "50"],
|
|
||||||
onChange: (page, newPageSize) => {
|
|
||||||
handlePaginationChange(page, newPageSize);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
searchText,
|
|
||||||
sortOrder,
|
|
||||||
viewMode,
|
|
||||||
isModalVisible,
|
|
||||||
currentPage,
|
|
||||||
pageSize,
|
|
||||||
containerStyle,
|
|
||||||
filterBarStyle,
|
|
||||||
formItemStyle,
|
|
||||||
viewModIconStyle,
|
|
||||||
pagination,
|
|
||||||
filteredPatients: patients.map(p => ({ ...p, key: p.id })),
|
|
||||||
handleSetSearchText,
|
|
||||||
handleSetSortOrder,
|
|
||||||
handleSetViewMode,
|
|
||||||
handleCloseModal,
|
|
||||||
handleAddPatient,
|
|
||||||
handleEditPatient,
|
|
||||||
formatDate,
|
|
||||||
handlePaginationChange,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default usePatientsUI;
|
|
||||||
Loading…
x
Reference in New Issue
Block a user