feat: Добавлена фильтрация пациентов по поисковой строке

This commit is contained in:
Андрей Дувакин 2025-06-07 15:20:22 +05:00
parent a2635ed03e
commit 1d8888da87
3 changed files with 138 additions and 139 deletions

View File

@ -9,28 +9,28 @@ import {
Button,
Popconfirm,
Typography,
Result, Tooltip
Result,
Tooltip
} from "antd";
import {
BuildOutlined,
PlusOutlined,
SortAscendingOutlined,
SortDescendingOutlined, TableOutlined,
TeamOutlined
SortDescendingOutlined,
TableOutlined,
TeamOutlined,
} from "@ant-design/icons";
import PatientListCard from "../../Dummies/PatientListCard.jsx";
import PatientFormModal from "../../Dummies/PatientFormModal/PatientFormModal.jsx";
import SelectViewMode from "../../Widgets/SelectViewMode/SelectViewMode.jsx";
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
import usePatients from "./usePatients.js";
import usePatientsUI from "./usePatientsUI.js";
const { Option } = Select;
const { Title } = Typography;
const {Option} = Select;
const {Title} = Typography;
const PatientsPage = () => {
const patientsData = usePatients();
const patientsUI = usePatientsUI(patientsData.patients, patientsData.totalCount);
const columns = [
{
@ -55,7 +55,7 @@ const PatientsPage = () => {
title: "Дата рождения",
dataIndex: "birthday",
sorter: true,
render: patientsUI.formatDate,
render: patientsData.formatDate,
},
{
title: "Телефон",
@ -71,7 +71,7 @@ const PatientsPage = () => {
render: (_, record) => (
<Row gutter={[8, 8]}>
<Col xs={24} xl={12}>
<Button block onClick={() => patientsUI.handleEditPatient(record)}>Изменить</Button>
<Button block onClick={() => patientsData.handleEditPatient(record)}>Изменить</Button>
</Col>
<Col xs={24} xl={12}>
<Popconfirm
@ -92,12 +92,12 @@ const PatientsPage = () => {
{
value: "tile",
label: "Плитка",
icon: <BuildOutlined style={patientsUI.viewModIconStyle}/>
icon: <BuildOutlined style={patientsData.viewModIconStyle}/>
},
{
value: "table",
label: "Таблица",
icon: <TableOutlined style={patientsUI.viewModIconStyle}/>
icon: <TableOutlined style={patientsData.viewModIconStyle}/>
}
];
@ -110,25 +110,27 @@ const PatientsPage = () => {
);
return (
<div style={patientsUI.containerStyle}>
<div style={patientsData.containerStyle}>
<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}>
<Input
placeholder="Поиск пациента"
value={patientsUI.searchText}
onChange={(e) => patientsUI.handleSetSearchText(e.target.value)}
style={patientsUI.formItemStyle}
value={patientsData.searchText}
onChange={(e) => patientsData.handleSetSearchText(e.target.value)}
onPressEnter={patientsData.handleSearch}
style={patientsData.formItemStyle}
allowClear
onClear={patientsData.handleClearSearch}
/>
</Col>
{patientsUI.viewMode === "tile" && (
{patientsData.viewMode === "tile" && (
<Col xs={24} md={5} sm={6} xl={3} xxl={2}>
<Tooltip title={"Сортировка пациентов"}>
<Select
value={patientsUI.sortOrder}
onChange={patientsUI.handleSetSortOrder}
style={patientsUI.formItemStyle}
value={patientsData.sortOrder}
onChange={patientsData.handleSetSortOrder}
style={patientsData.formItemStyle}
>
<Option value="asc"><SortAscendingOutlined/> А-Я</Option>
<Option value="desc"><SortDescendingOutlined/> Я-А</Option>
@ -136,13 +138,13 @@ const PatientsPage = () => {
</Tooltip>
</Col>
)}
<Col xs={24} md={patientsUI.viewMode === "tile" ? 5 : 10}
sm={patientsUI.viewMode === "tile" ? 8 : 14}
xl={patientsUI.viewMode === "tile" ? 3 : 5}
xxl={patientsUI.viewMode === "tile" ? 3 : 5}>
<Col xs={24} md={patientsData.viewMode === "tile" ? 5 : 10}
sm={patientsData.viewMode === "tile" ? 8 : 14}
xl={patientsData.viewMode === "tile" ? 3 : 5}
xxl={patientsData.viewMode === "tile" ? 3 : 5}>
<SelectViewMode
viewMode={patientsUI.viewMode}
setViewMode={patientsUI.handleSetViewMode}
viewMode={patientsData.viewMode}
setViewMode={patientsData.handleSetViewMode}
localStorageKey={"viewModePatients"}
toolTipText={"Формат отображения пациентов"}
viewModes={viewModes}
@ -150,33 +152,33 @@ const PatientsPage = () => {
</Col>
</Row>
{patientsData.isLoading ? <LoadingIndicator/> : patientsUI.viewMode === "tile" ? (
{patientsData.isLoading ? <LoadingIndicator/> : patientsData.viewMode === "tile" ? (
<List
grid={{ gutter: 16, column: 3 }}
dataSource={patientsUI.filteredPatients}
grid={{gutter: 16, column: 3}}
dataSource={patientsData.filteredPatients}
renderItem={patient => (
<List.Item>
<PatientListCard
patient={patient}
handleEditPatient={patientsUI.handleEditPatient}
handleEditPatient={patientsData.handleEditPatient}
handleDeletePatient={patientsData.handleDeletePatient}
/>
</List.Item>
)}
pagination={patientsUI.pagination}
pagination={patientsData.pagination}
/>
) : (
<Table
columns={columns}
dataSource={patientsUI.filteredPatients}
pagination={patientsUI.pagination}
dataSource={patientsData.filteredPatients}
pagination={patientsData.pagination}
/>
)}
<FloatButton
icon={<PlusOutlined/>}
type="primary"
onClick={patientsUI.handleAddPatient}
onClick={patientsData.handleAddPatient}
tooltip="Добавить пациента"
/>

View File

@ -1,22 +1,64 @@
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { notification } from "antd";
import {
useDeletePatientMutation,
useGetPatientsQuery,
useDeletePatientMutation,
} 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 { 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(
{ page: currentPage, pageSize, search: searchText },
{ page: currentPage, pageSize, search: tempSearchText || undefined },
{
pollingInterval: 20000,
pollingInterval: 20000, // Автообновление каждые 20 секунд
refetchOnMountOrArgChange: true, // Обновление при изменении параметров
}
);
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) => {
try {
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 {
searchText: tempSearchText,
sortOrder,
viewMode,
isModalVisible,
currentPage,
pageSize,
containerStyle,
filterBarStyle,
formItemStyle,
viewModIconStyle,
pagination,
patients: data.patients,
totalCount: data.total_count,
isLoading,
isError,
filteredPatients: data.patients.map(p => ({ ...p, key: p.id })),
handleSetSearchText: handleSetTempSearchText,
handleClearSearch,
handleDeletePatient,
handleSetSortOrder,
handleSetViewMode,
handleCloseModal,
handleAddPatient,
handleEditPatient,
formatDate,
handlePaginationChange,
};
};

View File

@ -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;