feat: lensIssuesApi
fix(IssuesPage): Исправлены фильтры и пагинация.
This commit is contained in:
parent
f0a712eb9d
commit
b8bc7023a0
@ -1,7 +1,6 @@
|
|||||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||||
import { baseQueryWithAuth } from "./baseQuery.js";
|
import { baseQueryWithAuth } from "./baseQuery.js";
|
||||||
|
|
||||||
|
|
||||||
export const lensIssuesApi = createApi({
|
export const lensIssuesApi = createApi({
|
||||||
reducerPath: 'lensIssuesApi',
|
reducerPath: 'lensIssuesApi',
|
||||||
baseQuery: baseQueryWithAuth,
|
baseQuery: baseQueryWithAuth,
|
||||||
@ -18,24 +17,34 @@ export const lensIssuesApi = createApi({
|
|||||||
start_date: startDate || undefined,
|
start_date: startDate || undefined,
|
||||||
end_date: endDate || undefined,
|
end_date: endDate || undefined,
|
||||||
},
|
},
|
||||||
providesTags: ['LensIssues'],
|
|
||||||
}),
|
}),
|
||||||
providesTags: ['LensIssue'],
|
providesTags: ['LensIssues'],
|
||||||
transformResponse: (response) => {
|
transformResponse: (response) => {
|
||||||
if (!response || !Array.isArray(response.issues)) {
|
if (!response) {
|
||||||
console.warn('Unexpected lens issues API response:', response);
|
console.warn('Empty lens issues API response:', response);
|
||||||
return { issues: [], total_count: 0 };
|
return { issues: [], total_count: 0 };
|
||||||
}
|
}
|
||||||
|
if (Array.isArray(response.results) && typeof response.count === 'number') {
|
||||||
|
return { issues: response.results, total_count: response.count };
|
||||||
|
}
|
||||||
|
if (Array.isArray(response.issues) && typeof response.total_count === 'number') {
|
||||||
return response;
|
return response;
|
||||||
|
}
|
||||||
|
console.warn('Unexpected lens issues API response:', response);
|
||||||
|
return { issues: [], total_count: 0 };
|
||||||
|
},
|
||||||
|
transformErrorResponse: (response) => {
|
||||||
|
console.error('Lens issues API error:', response);
|
||||||
|
return response.data?.detail || 'Unknown error';
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
addLensIssues: builder.mutation({
|
addLensIssues: builder.mutation({
|
||||||
query: (lensIssues) => ({
|
query: (lensIssues) => ({
|
||||||
url: `/lens_issues/`,
|
url: '/lens_issues/',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: lensIssues
|
body: lensIssues,
|
||||||
}),
|
}),
|
||||||
invalidatesTags: ['LensIssues']
|
invalidatesTags: ['LensIssues'],
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -31,7 +31,13 @@ ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend)
|
|||||||
|
|
||||||
const HomePage = () => {
|
const HomePage = () => {
|
||||||
const homePageData = useHomePage();
|
const homePageData = useHomePage();
|
||||||
const homePageUI = useHomePageUI(homePageData.appointments, homePageData.scheduledAppointments, homePageData.patients);
|
const homePageUI = useHomePageUI(
|
||||||
|
homePageData.appointments,
|
||||||
|
homePageData.scheduledAppointments,
|
||||||
|
homePageData.patients,
|
||||||
|
homePageData.upcomingAppointments,
|
||||||
|
homePageData.upcomingScheduledAppointments
|
||||||
|
);
|
||||||
|
|
||||||
if (homePageData.isError) {
|
if (homePageData.isError) {
|
||||||
return (
|
return (
|
||||||
@ -94,7 +100,7 @@ const HomePage = () => {
|
|||||||
<Statistic
|
<Statistic
|
||||||
title="Приемы за месяц"
|
title="Приемы за месяц"
|
||||||
value={
|
value={
|
||||||
homePageData.appointments.filter((a) => dayjs(a.appointment_datetime).isSame(dayjs(), "month")).length
|
homePageData.appointments.length
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
@ -107,7 +113,7 @@ const HomePage = () => {
|
|||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
title={`События на сегодня (${dayjs().format("DD.MM.YYYY")})`}
|
title={`События на сегодня (${dayjs().tz("Europe/Moscow").format("DD.MM.YYYY")})`}
|
||||||
style={homePageUI.sectionStyle}
|
style={homePageUI.sectionStyle}
|
||||||
>
|
>
|
||||||
<List
|
<List
|
||||||
@ -119,7 +125,7 @@ const HomePage = () => {
|
|||||||
>
|
>
|
||||||
<Space>
|
<Space>
|
||||||
<Typography.Text strong>
|
<Typography.Text strong>
|
||||||
{dayjs(item.appointment_datetime || item.scheduled_datetime).format("HH:mm")}
|
{dayjs(item.appointment_datetime || item.scheduled_datetime).tz("Europe/Moscow").format("HH:mm")}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<Typography.Text>
|
<Typography.Text>
|
||||||
{item.patient ? `${item.patient.last_name} ${item.patient.first_name}` : "Без пациента"} -{" "}
|
{item.patient ? `${item.patient.last_name} ${item.patient.first_name}` : "Без пациента"} -{" "}
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
import {Grid} from "antd";
|
import {Grid} from "antd";
|
||||||
import {useEffect, useMemo} from "react";
|
import {useEffect, useMemo} from "react";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import utc from "dayjs/plugin/utc";
|
||||||
|
import timezone from "dayjs/plugin/timezone";
|
||||||
import isBetween from "dayjs/plugin/isBetween";
|
import isBetween from "dayjs/plugin/isBetween";
|
||||||
import {useSelector} from "react-redux"; // Import isBetween plugin
|
|
||||||
|
|
||||||
|
dayjs.extend(utc);
|
||||||
|
dayjs.extend(timezone);
|
||||||
dayjs.extend(isBetween);
|
dayjs.extend(isBetween);
|
||||||
|
|
||||||
const {useBreakpoint} = Grid;
|
const {useBreakpoint} = Grid;
|
||||||
|
|
||||||
const useHomePageUI = (appointments, scheduledAppointments, patients) => {
|
const useHomePageUI = (appointments, scheduledAppointments, patients, upcomingAppointments, upcomingScheduledAppointments) => {
|
||||||
const screens = useBreakpoint();
|
const screens = useBreakpoint();
|
||||||
|
|
||||||
const containerStyle = {padding: screens.xs ? 16 : 24};
|
const containerStyle = {padding: screens.xs ? 16 : 24};
|
||||||
@ -23,10 +26,10 @@ const useHomePageUI = (appointments, scheduledAppointments, patients) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const todayEvents = useMemo(() => {
|
const todayEvents = useMemo(() => {
|
||||||
return [...appointments, ...scheduledAppointments].filter((event) =>
|
return [...upcomingAppointments, ...upcomingScheduledAppointments].filter((event) =>
|
||||||
dayjs(event.appointment_datetime || event.scheduled_datetime).isSame(dayjs(), "day")
|
dayjs(event.appointment_datetime || event.scheduled_datetime).isSame(dayjs(), "day")
|
||||||
);
|
);
|
||||||
}, [appointments, scheduledAppointments]);
|
}, [upcomingAppointments, upcomingScheduledAppointments]);
|
||||||
|
|
||||||
const upcomingBirthdays = useMemo(() => {
|
const upcomingBirthdays = useMemo(() => {
|
||||||
return patients.filter((p) =>
|
return patients.filter((p) =>
|
||||||
@ -38,7 +41,12 @@ const useHomePageUI = (appointments, scheduledAppointments, patients) => {
|
|||||||
const data = Array(7).fill(0);
|
const data = Array(7).fill(0);
|
||||||
appointments
|
appointments
|
||||||
.filter((app) =>
|
.filter((app) =>
|
||||||
dayjs(app.appointment_datetime).isBetween(dayjs().startOf("week"), dayjs().endOf("week"), "day", "[]")
|
dayjs(app.appointment_datetime).isBetween(
|
||||||
|
dayjs().startOf("week"),
|
||||||
|
dayjs().endOf("week"),
|
||||||
|
"day",
|
||||||
|
"[]"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.forEach((app) => {
|
.forEach((app) => {
|
||||||
const dayIndex = dayjs(app.appointment_datetime).day();
|
const dayIndex = dayjs(app.appointment_datetime).day();
|
||||||
@ -51,7 +59,12 @@ const useHomePageUI = (appointments, scheduledAppointments, patients) => {
|
|||||||
const data = Array(7).fill(0);
|
const data = Array(7).fill(0);
|
||||||
scheduledAppointments
|
scheduledAppointments
|
||||||
.filter((app) =>
|
.filter((app) =>
|
||||||
dayjs(app.scheduled_datetime).isBetween(dayjs().startOf("week"), dayjs().endOf("week"), "day", "[]")
|
dayjs(app.scheduled_datetime).isBetween(
|
||||||
|
dayjs().startOf("week"),
|
||||||
|
dayjs().endOf("week"),
|
||||||
|
"day",
|
||||||
|
"[]"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.forEach((app) => {
|
.forEach((app) => {
|
||||||
const dayIndex = dayjs(app.scheduled_datetime).day();
|
const dayIndex = dayjs(app.scheduled_datetime).day();
|
||||||
@ -68,7 +81,7 @@ const useHomePageUI = (appointments, scheduledAppointments, patients) => {
|
|||||||
x: {title: {display: true, text: "День недели"}},
|
x: {title: {display: true, text: "День недели"}},
|
||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: { display: false },
|
legend: {display: true, position: "top"},
|
||||||
title: {display: true, text: "Приемы за неделю"},
|
title: {display: true, text: "Приемы за неделю"},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import LensIssueFormModal from "./Components/LensIssueFormModal/LensIssueFormMod
|
|||||||
import SelectViewMode from "../../Widgets/SelectViewMode/SelectViewMode.jsx";
|
import SelectViewMode from "../../Widgets/SelectViewMode/SelectViewMode.jsx";
|
||||||
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx";
|
||||||
import useIssues from "./useIssues.js";
|
import useIssues from "./useIssues.js";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
const { Title } = Typography;
|
const { Title } = Typography;
|
||||||
const { useBreakpoint } = Grid;
|
const { useBreakpoint } = Grid;
|
||||||
@ -86,7 +87,7 @@ const IssuesPage = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const timeLineItems = issuesData.issues.map(issue => ({
|
const timeLineItems = useMemo(() => issuesData.issues.map(issue => ({
|
||||||
label: dayjs(issue.issue_date).format("DD.MM.YYYY"),
|
label: dayjs(issue.issue_date).format("DD.MM.YYYY"),
|
||||||
children: (
|
children: (
|
||||||
<Row gutter={[16, 16]} align="middle">
|
<Row gutter={[16, 16]} align="middle">
|
||||||
@ -107,7 +108,7 @@ const IssuesPage = () => {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
),
|
),
|
||||||
}));
|
})), [issuesData]);
|
||||||
|
|
||||||
const TimeLineView = () => {
|
const TimeLineView = () => {
|
||||||
const paginatedItems = timeLineItems.slice(
|
const paginatedItems = timeLineItems.slice(
|
||||||
@ -129,7 +130,7 @@ const IssuesPage = () => {
|
|||||||
<Pagination
|
<Pagination
|
||||||
current={issuesData.currentPage}
|
current={issuesData.currentPage}
|
||||||
pageSize={issuesData.pageSize}
|
pageSize={issuesData.pageSize}
|
||||||
total={timeLineItems.length}
|
total={issuesData.total_count}
|
||||||
onChange={issuesData.handlePaginationChange}
|
onChange={issuesData.handlePaginationChange}
|
||||||
showSizeChanger={true}
|
showSizeChanger={true}
|
||||||
pageSizeOptions={["5", "10", "20", "50"]}
|
pageSizeOptions={["5", "10", "20", "50"]}
|
||||||
|
|||||||
@ -40,17 +40,19 @@ const useIssues = () => {
|
|||||||
data: issuesData = {issues: [], total_count: 0},
|
data: issuesData = {issues: [], total_count: 0},
|
||||||
isLoading: isIssuesLoading,
|
isLoading: isIssuesLoading,
|
||||||
isError: isIssuesError,
|
isError: isIssuesError,
|
||||||
error: issuesError
|
error: issuesError,
|
||||||
|
refetch
|
||||||
} = useGetLensIssuesQuery({
|
} = useGetLensIssuesQuery({
|
||||||
page: currentPage,
|
page: currentPage,
|
||||||
pageSize,
|
pageSize,
|
||||||
search: searchText || undefined,
|
search: searchText || undefined,
|
||||||
sortOrder: 'desc',
|
sortOrder: 'desc',
|
||||||
startDate: startFilterDate || undefined,
|
startDate: startFilterDate ? dayjs(startFilterDate).format('YYYY-MM-DD') : undefined,
|
||||||
endDate: endFilterDate || undefined,
|
endDate: endFilterDate ? dayjs(endFilterDate).format('YYYY-MM-DD') : undefined,
|
||||||
}, {
|
}, {
|
||||||
pollingInterval: 20000,
|
pollingInterval: 20000,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {data: patients = [], isLoading: isPatientsLoading, isError: isPatientsError} = useGetAllPatientsQuery();
|
const {data: patients = [], isLoading: isPatientsLoading, isError: isPatientsError} = useGetAllPatientsQuery();
|
||||||
const {data: lenses = [], isLoading: isLensesLoading, isError: isLensesError} = useGetNotIssuedLensesQuery();
|
const {data: lenses = [], isLoading: isLensesLoading, isError: isLensesError} = useGetNotIssuedLensesQuery();
|
||||||
const [addIssue, {isLoading: isAdding}] = useAddLensIssuesMutation();
|
const [addIssue, {isLoading: isAdding}] = useAddLensIssuesMutation();
|
||||||
@ -108,19 +110,23 @@ const useIssues = () => {
|
|||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
dispatch(setSearchText(tempSearchText));
|
dispatch(setSearchText(tempSearchText));
|
||||||
dispatch(setCurrentPage(1));
|
dispatch(setCurrentPage(1));
|
||||||
|
refetch();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClearSearch = () => {
|
const handleClearSearch = () => {
|
||||||
setTempSearchText('');
|
setTempSearchText('');
|
||||||
dispatch(setSearchText(''));
|
dispatch(setSearchText(''));
|
||||||
dispatch(setCurrentPage(1));
|
dispatch(setCurrentPage(1));
|
||||||
|
refetch();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSetViewMode = (mode) => dispatch(setViewMode(mode));
|
const handleSetViewMode = (mode) => dispatch(setViewMode(mode));
|
||||||
const handleSetCurrentPage = (page) => dispatch(setCurrentPage(page));
|
const handleSetCurrentPage = (page) => {
|
||||||
|
dispatch(setCurrentPage(page));
|
||||||
|
};
|
||||||
|
|
||||||
const handleSetPageSize = (size) => {
|
const handleSetPageSize = (size) => {
|
||||||
dispatch(setPageSize(size));
|
dispatch(setPageSize(size));
|
||||||
dispatch(setCurrentPage(1));
|
|
||||||
};
|
};
|
||||||
const handleCloseModal = () => dispatch(closeModal());
|
const handleCloseModal = () => dispatch(closeModal());
|
||||||
const handleSelectIssue = (issue) => dispatch(selectIssue(issue));
|
const handleSelectIssue = (issue) => dispatch(selectIssue(issue));
|
||||||
@ -134,6 +140,7 @@ const useIssues = () => {
|
|||||||
const handlePaginationChange = (page, pageSize) => {
|
const handlePaginationChange = (page, pageSize) => {
|
||||||
handleSetCurrentPage(page);
|
handleSetCurrentPage(page);
|
||||||
handleSetPageSize(pageSize);
|
handleSetPageSize(pageSize);
|
||||||
|
refetch();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFilterDateChange = (dates) => {
|
const handleFilterDateChange = (dates) => {
|
||||||
@ -142,6 +149,7 @@ const useIssues = () => {
|
|||||||
dispatch(setStartFilterDate(start.toISOString()));
|
dispatch(setStartFilterDate(start.toISOString()));
|
||||||
dispatch(setEndFilterDate(end.toISOString()));
|
dispatch(setEndFilterDate(end.toISOString()));
|
||||||
dispatch(setCurrentPage(1));
|
dispatch(setCurrentPage(1));
|
||||||
|
refetch();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -149,6 +157,7 @@ const useIssues = () => {
|
|||||||
dispatch(setStartFilterDate(null));
|
dispatch(setStartFilterDate(null));
|
||||||
dispatch(setEndFilterDate(null));
|
dispatch(setEndFilterDate(null));
|
||||||
dispatch(setCurrentPage(1));
|
dispatch(setCurrentPage(1));
|
||||||
|
refetch();
|
||||||
};
|
};
|
||||||
|
|
||||||
const pagination = {
|
const pagination = {
|
||||||
@ -158,18 +167,22 @@ const useIssues = () => {
|
|||||||
showSizeChanger: true,
|
showSizeChanger: true,
|
||||||
pageSizeOptions: ["5", "10", "20", "50"],
|
pageSizeOptions: ["5", "10", "20", "50"],
|
||||||
onChange: handlePaginationChange,
|
onChange: handlePaginationChange,
|
||||||
|
onShowSizeChange: handlePaginationChange,
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmitFormModal = async (issueDate, patientId, lensId) => {
|
const handleSubmitFormModal = async (issueDate, patientId, lensId) => {
|
||||||
dispatch(closeModal());
|
dispatch(closeModal());
|
||||||
try {
|
try {
|
||||||
await addIssue({ issue_date: issueDate, patient_id: patientId, lens_id: lensId }).unwrap();
|
const formattedIssueDate = dayjs(issueDate).format('YYYY-MM-DD');
|
||||||
|
await addIssue({issue_date: formattedIssueDate, patient_id: patientId, lens_id: lensId}).unwrap();
|
||||||
notification.success({
|
notification.success({
|
||||||
message: "Линза выдана",
|
message: "Линза выдана",
|
||||||
description: "Линза успешно выдана пациенту.",
|
description: "Линза успешно выдана пациенту.",
|
||||||
placement: "topRight",
|
placement: "topRight",
|
||||||
});
|
});
|
||||||
|
refetch();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Add lens issue error:', error);
|
||||||
notification.error({
|
notification.error({
|
||||||
message: "Ошибка выдачи линзы",
|
message: "Ошибка выдачи линзы",
|
||||||
description: error?.data?.detail || "Не удалось выдать линзу пациенту.",
|
description: error?.data?.detail || "Не удалось выдать линзу пациенту.",
|
||||||
@ -180,6 +193,7 @@ const useIssues = () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
issues: issuesData.issues,
|
issues: issuesData.issues,
|
||||||
|
total_count: issuesData.total_count,
|
||||||
patients,
|
patients,
|
||||||
lenses,
|
lenses,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user