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

This commit is contained in:
Андрей Дувакин 2025-06-07 14:54:05 +05:00
parent 67fa9db57a
commit a2635ed03e
7 changed files with 44 additions and 17 deletions

View File

@ -1,6 +1,6 @@
from typing import Sequence, Optional, Tuple
from sqlalchemy import select, func
from sqlalchemy import select, func, or_
from sqlalchemy.ext.asyncio import AsyncSession
from app.domain.models import Patient
@ -10,12 +10,37 @@ class PatientsRepository:
def __init__(self, db: AsyncSession):
self.db = db
async def get_all(self, skip: int = 0, limit: int = 10) -> Tuple[Sequence[Patient], int]:
stmt = select(Patient).offset(skip).limit(limit)
async def get_all(self, skip: int = 0, limit: int = 10, search: str = None) -> Tuple[Sequence[Patient], int]:
stmt = select(Patient)
if search:
search = f"%{search}%"
stmt = stmt.filter(
or_(
Patient.last_name.ilike(search),
Patient.first_name.ilike(search),
Patient.patronymic.ilike(search),
Patient.email.ilike(search),
Patient.phone.ilike(search)
)
)
stmt = stmt.offset(skip).limit(limit)
result = await self.db.execute(stmt)
patients = result.scalars().all()
count_stmt = select(func.count()).select_from(Patient)
if search:
search = f"%{search}%"
count_stmt = count_stmt.filter(
or_(
Patient.last_name.ilike(search),
Patient.first_name.ilike(search),
Patient.patronymic.ilike(search),
Patient.email.ilike(search),
Patient.phone.ilike(search)
)
)
count_result = await self.db.execute(count_stmt)
total_count = count_result.scalar()

View File

@ -19,11 +19,12 @@ router = APIRouter()
async def get_all_patients(
page: int = Query(1, ge=1, description="Page number"),
page_size: int = Query(10, ge=1, le=100, description="Number of patients per page"),
search: str = Query(None, description="Search term for filtering patients"),
db: AsyncSession = Depends(get_db),
user=Depends(get_current_user),
):
patients_service = PatientsService(db)
patients, total_count = await patients_service.get_all_patients(page, page_size)
patients, total_count = await patients_service.get_all_patients(page, page_size, search)
return {"patients": patients, "total_count": total_count}

View File

@ -13,9 +13,10 @@ class PatientsService:
def __init__(self, db: AsyncSession):
self.patient_repository = PatientsRepository(db)
async def get_all_patients(self, page: int = 1, page_size: int = 10) -> Tuple[list[PatientEntity], int]:
async def get_all_patients(self, page: int = 1, page_size: int = 10, search: str = None) -> Tuple[
list[PatientEntity], int]:
skip = (page - 1) * page_size
patients, total_count = await self.patient_repository.get_all(skip=skip, limit=page_size)
patients, total_count = await self.patient_repository.get_all(skip=skip, limit=page_size, search=search)
return (
[self.model_to_entity(patient) for patient in patients],
total_count

View File

@ -7,9 +7,9 @@ export const patientsApi = createApi({
tagTypes: ['Patient'],
endpoints: (builder) => ({
getPatients: builder.query({
query: ({ page, pageSize }) => ({
query: ({ page, pageSize, search }) => ({
url: '/patients/',
params: { page, page_size: pageSize },
params: { page, page_size: pageSize, search: search || undefined },
}),
providesTags: ['Patients'],
}),

View File

@ -37,7 +37,7 @@ const PatientsPage = () => {
title: "Фамилия",
dataIndex: "last_name",
key: "last_name",
sorter: true, // Сортировка будет на сервере, если добавить
sorter: true,
},
{
title: "Имя",
@ -109,8 +109,6 @@ const PatientsPage = () => {
/>
);
console.log(patientsData.isLoading)
return (
<div style={patientsUI.containerStyle}>
<Title level={1}><TeamOutlined/> Пациенты</Title>

View File

@ -6,17 +6,15 @@ import {
import { useSelector } from "react-redux";
const usePatients = () => {
const { currentPage, pageSize } = useSelector(state => state.patientsUI);
const { currentPage, pageSize, searchText } = useSelector(state => state.patientsUI);
const { data = { patients: [], total_count: 0 }, isLoading, isError } = useGetPatientsQuery(
{ page: currentPage, pageSize },
{ page: currentPage, pageSize, search: searchText },
{
pollingInterval: 20000,
}
);
console.log(data);
const [deletePatient] = useDeletePatientMutation();
const handleDeletePatient = async (patientId) => {

View File

@ -1,5 +1,6 @@
import { useEffect, useMemo } from "react";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { debounce } from "lodash";
import {
closeModal,
openModal,
@ -34,7 +35,10 @@ const usePatientsUI = (patients, totalCount) => {
const formItemStyle = { width: "100%" };
const viewModIconStyle = { marginRight: 8 };
const handleSetSearchText = (value) => dispatch(setSearchText(value));
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));