feat: Добавлена фильтрация пациентов по поисковой строке
This commit is contained in:
parent
67fa9db57a
commit
a2635ed03e
@ -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()
|
||||
|
||||
|
||||
@ -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}
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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'],
|
||||
}),
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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) => {
|
||||
|
||||
@ -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));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user