feat: Исправление фильтрации и UI для выдачи линз
This commit is contained in:
parent
b8bc7023a0
commit
0a7fd16a29
@ -1,3 +1,4 @@
|
||||
from datetime import date
|
||||
from typing import Optional, Sequence, Tuple, Literal
|
||||
|
||||
from sqlalchemy import select, desc, or_, func, asc
|
||||
@ -17,8 +18,8 @@ class LensIssuesRepository:
|
||||
limit: int = 10,
|
||||
search: Optional[str] = None,
|
||||
sort_order: Literal["asc", "desc"] = "desc",
|
||||
start_date: Optional[str] = None,
|
||||
end_date: Optional[str] = None
|
||||
start_date: Optional[date] = None,
|
||||
end_date: Optional[date] = None
|
||||
) -> Tuple[Sequence[LensIssue], int]:
|
||||
stmt = (
|
||||
select(LensIssue)
|
||||
@ -62,6 +63,7 @@ class LensIssuesRepository:
|
||||
)
|
||||
if start_date:
|
||||
count_stmt = count_stmt.filter(LensIssue.issue_date >= start_date)
|
||||
|
||||
if end_date:
|
||||
count_stmt = count_stmt.filter(LensIssue.issue_date <= end_date)
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
from datetime import date
|
||||
from typing import Optional, Literal
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
@ -23,8 +24,8 @@ async def get_all_lens_issues(
|
||||
page_size: int = Query(10, ge=1, le=100),
|
||||
search: Optional[str] = Query(None),
|
||||
sort_order: Literal["asc", "desc"] = Query("desc"),
|
||||
start_date: Optional[str] = Query(None),
|
||||
end_date: Optional[str] = Query(None),
|
||||
start_date: Optional[date] = Query(None),
|
||||
end_date: Optional[date] = Query(None),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user=Depends(get_current_user),
|
||||
):
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
from datetime import date
|
||||
from typing import Optional, Literal, Tuple
|
||||
|
||||
from fastapi import HTTPException
|
||||
@ -28,8 +29,8 @@ class LensIssuesService:
|
||||
limit: int = 10,
|
||||
search: Optional[str] = None,
|
||||
sort_order: Literal["asc", "desc"] = "desc",
|
||||
start_date: Optional[str] = None,
|
||||
end_date: Optional[str] = None
|
||||
start_date: Optional[date] = None,
|
||||
end_date: Optional[date] = None
|
||||
) -> Tuple[list[LensIssueEntity], int]:
|
||||
lens_issues, total_count = await self.lens_issues_repository.get_all(
|
||||
skip=skip,
|
||||
|
||||
@ -25,7 +25,6 @@ import timezone from "dayjs/plugin/timezone";
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
dayjs.tz.setDefault("Europe/Moscow");
|
||||
|
||||
const { useBreakpoint } = Grid;
|
||||
|
||||
@ -35,13 +34,13 @@ const useAppointments = () => {
|
||||
const { collapsed, siderWidth, hovered, selectedAppointment } = useSelector(state => state.appointmentsUI);
|
||||
const screens = useBreakpoint();
|
||||
|
||||
const [currentMonth, setCurrentMonth] = useState(dayjs().tz("Europe/Moscow").startOf('month'));
|
||||
const [currentMonth, setCurrentMonth] = useState(dayjs().startOf('month'));
|
||||
|
||||
const startDate = currentMonth.startOf('month').tz("Europe/Moscow").format('YYYY-MM-DD');
|
||||
const endDate = currentMonth.endOf('month').tz("Europe/Moscow").format('YYYY-MM-DD');
|
||||
const startDate = currentMonth.startOf('month').format('YYYY-MM-DD');
|
||||
const endDate = currentMonth.endOf('month').format('YYYY-MM-DD');
|
||||
|
||||
const handleMonthChange = (newMonth) => {
|
||||
setCurrentMonth(dayjs(newMonth).tz("Europe/Moscow").startOf('month'));
|
||||
setCurrentMonth(dayjs(newMonth).startOf('month'));
|
||||
};
|
||||
|
||||
const {
|
||||
@ -155,7 +154,7 @@ const useAppointments = () => {
|
||||
|
||||
const upcomingEvents = useMemo(() =>
|
||||
[...upcomingAppointments, ...upcomingScheduledAppointments]
|
||||
.sort((a, b) => dayjs(a.appointment_datetime || a.scheduled_datetime).tz("Europe/Moscow") - dayjs(b.appointment_datetime || b.scheduled_datetime).tz("Europe/Moscow"))
|
||||
.sort((a, b) => dayjs(a.appointment_datetime || a.scheduled_datetime) - dayjs(b.appointment_datetime || b.scheduled_datetime))
|
||||
.slice(0, 5),
|
||||
[upcomingAppointments, upcomingScheduledAppointments]
|
||||
);
|
||||
|
||||
@ -13,17 +13,17 @@ import {
|
||||
Pagination,
|
||||
Result
|
||||
} from "antd";
|
||||
import { DatabaseOutlined, PlusOutlined, UnorderedListOutlined } from "@ant-design/icons";
|
||||
import {DatabaseOutlined, PlusOutlined, UnorderedListOutlined} from "@ant-design/icons";
|
||||
import LensIssueViewModal from "./Components/LensIssueViewModal/LensIssueViewModal.jsx";
|
||||
import dayjs from "dayjs";
|
||||
import LensIssueFormModal from "./Components/LensIssueFormModal/LensIssueFormModal.jsx";
|
||||
import SelectViewMode from "../../Widgets/SelectViewMode/SelectViewMode.jsx";
|
||||
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
||||
import useIssues from "./useIssues.js";
|
||||
import { useMemo } from "react";
|
||||
import {useMemo} from "react";
|
||||
|
||||
const { Title } = Typography;
|
||||
const { useBreakpoint } = Grid;
|
||||
const {Title} = Typography;
|
||||
const {useBreakpoint} = Grid;
|
||||
|
||||
const IssuesPage = () => {
|
||||
const issuesData = useIssues();
|
||||
@ -33,12 +33,12 @@ const IssuesPage = () => {
|
||||
{
|
||||
value: "table",
|
||||
label: "Таблица",
|
||||
icon: <DatabaseOutlined style={issuesData.viewModIconStyle} />,
|
||||
icon: <DatabaseOutlined style={issuesData.viewModIconStyle}/>,
|
||||
},
|
||||
{
|
||||
value: "timeline",
|
||||
label: "Лента",
|
||||
icon: <UnorderedListOutlined style={issuesData.viewModIconStyle} />,
|
||||
icon: <UnorderedListOutlined style={issuesData.viewModIconStyle}/>,
|
||||
},
|
||||
];
|
||||
|
||||
@ -87,59 +87,49 @@ const IssuesPage = () => {
|
||||
/>
|
||||
);
|
||||
|
||||
const timeLineItems = useMemo(() => issuesData.issues.map(issue => ({
|
||||
label: dayjs(issue.issue_date).format("DD.MM.YYYY"),
|
||||
children: (
|
||||
<Row gutter={[16, 16]} align="middle">
|
||||
<Col xs={24} sm={24} md={13}>
|
||||
<p style={{ textAlign: "right" }}>Пациент: {issue.patient.last_name} {issue.patient.first_name}</p>
|
||||
</Col>
|
||||
<Col xs={24} sm={24} md={5}>
|
||||
<p style={{ textAlign: "right" }}>Линза: {issue.lens.side} {issue.lens.diameter}</p>
|
||||
</Col>
|
||||
<Col xs={24} sm={24} md={6}>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => issuesData.handleSelectIssue(issue)}
|
||||
style={{ marginRight: 40 }}
|
||||
>
|
||||
Подробнее
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
})), [issuesData]);
|
||||
|
||||
const TimeLineView = () => {
|
||||
const paginatedItems = timeLineItems.slice(
|
||||
(issuesData.currentPage - 1) * issuesData.pageSize,
|
||||
issuesData.currentPage * issuesData.pageSize
|
||||
);
|
||||
const timeLineItems = useMemo(() => issuesData.issues.map(issue => ({
|
||||
label: dayjs(issue.issue_date).format("DD.MM.YYYY"),
|
||||
children: (
|
||||
<Row gutter={[16, 16]} align="middle">
|
||||
<Col xs={24} sm={24} md={13}>
|
||||
<p style={{textAlign: "right"}}>Пациент: {issue.patient.last_name} {issue.patient.first_name}</p>
|
||||
</Col>
|
||||
<Col xs={24} sm={24} md={5}>
|
||||
<p style={{textAlign: "right"}}>Линза: {issue.lens.side} {issue.lens.diameter}</p>
|
||||
</Col>
|
||||
<Col xs={24} sm={24} md={6}>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => issuesData.handleSelectIssue(issue)}
|
||||
style={{marginRight: 40}}
|
||||
>
|
||||
Подробнее
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
})), []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Timeline
|
||||
items={paginatedItems}
|
||||
items={timeLineItems}
|
||||
mode={screens.xs ? "left" : "right"}
|
||||
/>
|
||||
<Row
|
||||
style={{ textAlign: "center", marginTop: 20 }}
|
||||
style={{textAlign: "center", marginTop: 20}}
|
||||
align="middle"
|
||||
justify="end"
|
||||
>
|
||||
<Pagination
|
||||
current={issuesData.currentPage}
|
||||
pageSize={issuesData.pageSize}
|
||||
total={issuesData.total_count}
|
||||
onChange={issuesData.handlePaginationChange}
|
||||
showSizeChanger={true}
|
||||
pageSizeOptions={["5", "10", "20", "50"]}
|
||||
{...issuesData.pagination}
|
||||
/>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
if (issuesData.isError) return (
|
||||
<Result
|
||||
status="error"
|
||||
@ -150,14 +140,13 @@ const IssuesPage = () => {
|
||||
|
||||
return (
|
||||
<div style={issuesData.containerStyle}>
|
||||
<Title level={1}><DatabaseOutlined /> Выдача линз</Title>
|
||||
<Title level={1}><DatabaseOutlined/> Выдача линз</Title>
|
||||
<Row gutter={[16, 16]} style={issuesData.filterBarStyle}>
|
||||
<Col xs={24} sm={24} md={12}>
|
||||
<Input
|
||||
placeholder="Поиск по пациенту или врачу"
|
||||
value={issuesData.tempSearchText}
|
||||
onChange={(e) => issuesData.handleSetTempSearchText(e.target.value)}
|
||||
onPressEnter={issuesData.handleSearch}
|
||||
style={issuesData.formItemStyle}
|
||||
allowClear
|
||||
onClear={issuesData.handleClearSearch}
|
||||
@ -199,15 +188,15 @@ const IssuesPage = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
{issuesData.isLoading ? (
|
||||
<LoadingIndicator />
|
||||
<LoadingIndicator/>
|
||||
) : issuesData.viewMode === "table" ? (
|
||||
<TableView />
|
||||
<TableView/>
|
||||
) : (
|
||||
<TimeLineView />
|
||||
<TimeLineView/>
|
||||
)}
|
||||
|
||||
<FloatButton
|
||||
icon={<PlusOutlined />}
|
||||
icon={<PlusOutlined/>}
|
||||
type="primary"
|
||||
onClick={issuesData.handleAddIssue}
|
||||
tooltip="Добавить выдачу линзы"
|
||||
|
||||
@ -105,7 +105,10 @@ const useIssues = () => {
|
||||
borderRadius: 8
|
||||
};
|
||||
|
||||
const handleSetTempSearchText = (value) => setTempSearchText(value);
|
||||
const handleSetTempSearchText = (value) => {
|
||||
setTempSearchText(value);
|
||||
handleSearch();
|
||||
};
|
||||
|
||||
const handleSearch = () => {
|
||||
dispatch(setSearchText(tempSearchText));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user