feat: lensIssues - Добавлена возможность получения lensIssue по lensId

This commit is contained in:
Андрей Дувакин 2025-07-04 07:35:20 +05:00
parent 1541aba89f
commit 551af24be9
6 changed files with 132 additions and 14 deletions

View File

@ -85,6 +85,15 @@ class LensIssuesRepository:
result = await self.db.execute(stmt)
return result.scalars().all()
async def get_by_lens_id(self, lens_id: int) -> Optional[LensIssue]:
stmt = (
select(LensIssue)
.filter_by(lens_id=lens_id)
.options(joinedload(LensIssue.patient))
)
result = await self.db.execute(stmt)
return result.scalars().first()
async def get_by_id(self, lens_issue_id: int) -> Optional[LensIssue]:
stmt = select(LensIssue).filter_by(id=lens_issue_id)
result = await self.db.execute(stmt)

View File

@ -60,6 +60,21 @@ async def get_lens_issues_by_patient(
return await lens_issues_service.get_lens_issues_by_patient_id(patient_id)
@router.get(
'/by-lens/{lens_id}/',
response_model=Optional[LensIssueEntity],
summary="Get lens issues by lens id",
description="Returns a paginated list of lens issues by lens id",
)
async def get_lens_issues_by_lens_id(
lens_id: int,
db: AsyncSession = Depends(get_db),
user=Depends(get_current_user),
):
lens_issues_service = LensIssuesService(db)
return await lens_issues_service.get_lens_issue_by_lens_id(lens_id)
@router.post(
"/",
response_model=LensIssueEntity,

View File

@ -1,5 +1,5 @@
from datetime import date
from typing import Optional, Literal, Tuple
from typing import Optional, Literal, Tuple, Any, Coroutine
from fastapi import HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
@ -56,13 +56,24 @@ class LensIssuesService:
lens_issues = await self.lens_issues_repository.get_by_patient_id(patient.id)
print(lens_issues)
return [
self.model_to_entity(lens_issue)
for lens_issue in lens_issues
]
async def get_lens_issue_by_lens_id(self, lens_id: int) -> Optional[LensIssueEntity]:
lens = await self.lenses_repository.get_by_id(lens_id)
if not lens:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail='Линза с таким ID не найдена',
)
lens_issue = await self.lens_issues_repository.get_by_lens_id(lens_id)
return self.model_to_entity(lens_issue)
async def create_lens_issue(self, lens_issue: LensIssueEntity, user_id: int) -> Optional[LensIssueEntity]:
patient = await self.patient_repository.get_by_id(lens_issue.patient_id)

View File

@ -50,6 +50,10 @@ export const lensIssuesApi = createApi({
query: (patientId) => `/lens_issues/by-patient/${patientId}/`,
providesTags: ['LensIssues'],
}),
getLensIssueByLens: builder.query({
query: (lensId) => `/lens_issues/by-lens/${lensId}/`,
providesTags: ['LensIssues'],
}),
}),
});
@ -57,4 +61,5 @@ export const {
useGetLensIssuesQuery,
useAddLensIssuesMutation,
useGetLensIssuesByPatientQuery,
useGetLensIssueByLensQuery,
} = lensIssuesApi;

View File

@ -0,0 +1,22 @@
import {useGetLensIssueByLensQuery} from "../../../../../../../Api/lensIssuesApi.js";
const useLensViewModal = (lens, visible) => {
const {
data: lensIssue = null,
isLoading: isLensIssueLoading,
isError: isLensIssueError,
} = useGetLensIssueByLensQuery(lens?.id, {
skip: !visible || !lens?.id,
pollingInterval: 60000,
refetchOnMountOrArgChange: true,
});
return {
lensIssue,
isLensIssueLoading,
isLensIssueError,
};
};
export default useLensViewModal;

View File

@ -1,10 +1,61 @@
import {Button, Col, Modal, Row, Typography, Divider} from "antd";
import {Button, Col, Modal, Row, Typography, Divider, Collapse, Result} from "antd";
import PropTypes from "prop-types";
import {PatientPropType} from "../../../../../Types/patientPropType.js";
import usePatientsViewModal from "./usePatientsViewModal.js";
import LoadingIndicator from "../../../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
const {Text, Title} = Typography;
const PatientViewModal = ({visible, onCancel, patient}) => {
const {lensIssues, isLensIssuesLoading, isLensIssuesError} = usePatientsViewModal(patient, visible);
if (isLensIssuesLoading) {
return (
<Modal title="Просмотр пациента" open={visible} onCancel={onCancel} footer={null}>
<LoadingIndicator/>
</Modal>
);
}
if (isLensIssuesError) {
return (
<Modal title="Просмотр пациента" open={visible} onCancel={onCancel} footer={null}>
<Result
status="error"
title="Ошибка"
subTitle="Не удалось загрузить данные о выданных линзах"
extra={<Button type="primary" onClick={onCancel}>Закрыть</Button>}
/>
</Modal>
);
}
const items = lensIssues.length ? lensIssues.map((issue) => {
return {
key: issue.id,
label: `${new Date(issue.issue_date).toLocaleDateString('ru-RU')}`,
children: issue.lens ? (
<div>
<p><b>id:</b> {issue.lens.id}</p>
<p><b>Линза:</b> {issue.lens.side}</p>
<p><b>Диаметр:</b> {issue.lens.diameter}</p>
<p><b>Тор:</b> {issue.lens.tor}</p>
<p><b>Пресетная рефракция:</b> {issue.lens.preset_refraction}</p>
<p><b>Периферийная торичность:</b> {issue.lens.periphery_toricity}</p>
<p><b>FVC:</b> {issue.lens.fvc}</p>
<p><b>ESP:</b> {issue.lens.esa}</p>
</div>
) : (
<p>Данные о линзе отсутствуют</p>
),
};
}) : [{
key: 'no-lenses',
label: 'Нет выданных линз',
children: <p>У пациента нет выданных линз</p>,
}];
const { Text, Title } = Typography;
const PatientViewModal = ({ visible, onCancel, patient }) => {
return (
<Modal
title="Просмотр пациента"
@ -18,12 +69,12 @@ const PatientViewModal = ({ visible, onCancel, patient }) => {
>
<Row gutter={24}>
<Col xs={24} md={12}>
<div style={{ marginBottom: 12 }}>
<div style={{marginBottom: 12}}>
<Title level={5}>👤 ФИО</Title>
<Text>{`${patient.last_name} ${patient.first_name} ${patient.patronymic || ''}`}</Text>
</div>
<div style={{ marginBottom: 12 }}>
<div style={{marginBottom: 12}}>
<Title level={5}>🎂 Дата рождения</Title>
<Text>
{new Date(patient.birthday).toLocaleDateString('ru-RU', {
@ -36,34 +87,39 @@ const PatientViewModal = ({ visible, onCancel, patient }) => {
</Col>
<Col xs={24} md={12}>
<div style={{ marginBottom: 12 }}>
<div style={{marginBottom: 12}}>
<Title level={5}>📞 Телефон</Title>
<Text>{patient.phone || 'Не указан'}</Text>
</div>
<div style={{ marginBottom: 12 }}>
<div style={{marginBottom: 12}}>
<Title level={5}> Email</Title>
<Text>{patient.email || 'Не указан'}</Text>
</div>
<div style={{ marginBottom: 12 }}>
<div style={{marginBottom: 12}}>
<Title level={5}>🏠 Адрес</Title>
<Text>{patient.address || 'Не указан'}</Text>
</div>
</Col>
</Row>
<Divider />
<Divider/>
<div style={{ marginBottom: 12 }}>
<div style={{marginBottom: 12}}>
<Title level={5}>🩺 Диагноз</Title>
<Text>{patient.diagnosis || 'Не указан'}</Text>
</div>
<div style={{ marginBottom: 12 }}>
<div style={{marginBottom: 12}}>
<Title level={5}>👓 Коррекция</Title>
<Text>{patient.correction || 'Не указ'}</Text>
</div>
<Typography.Title level={5}>📦 Выданные линзы</Typography.Title>
<Collapse
items={items}
/>
</Modal>
);
};