From 744a5402a037740624756dfc4f52e6fd01b38091 Mon Sep 17 00:00:00 2001 From: andrei Date: Mon, 10 Mar 2025 17:56:43 +0500 Subject: [PATCH] =?UTF-8?q?=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B8=D1=81=D1=82=D0=BE=D1=80=D0=B8=D0=B8=20=D0=B2=D1=8B=D0=B4?= =?UTF-8?q?=D0=B0=D1=87=D0=B8=20=D0=BB=D0=B8=D0=BD=D0=B7=20=D0=B2=20=D0=B2?= =?UTF-8?q?=D0=B8=D0=B4=D0=B5=20=D0=BB=D0=B5=D0=BD=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web-app/src/components/SelectViewMode.jsx | 22 +-- .../lens_issues/LensIssueFormModal.jsx | 143 +++++++----------- web-app/src/pages/IssuesPage.jsx | 137 ++++++++++++++--- web-app/src/pages/LensesPage.jsx | 25 ++- web-app/src/pages/PatientsPage.jsx | 19 ++- 5 files changed, 221 insertions(+), 125 deletions(-) diff --git a/web-app/src/components/SelectViewMode.jsx b/web-app/src/components/SelectViewMode.jsx index 7e83f5a..2f073ff 100644 --- a/web-app/src/components/SelectViewMode.jsx +++ b/web-app/src/components/SelectViewMode.jsx @@ -4,7 +4,7 @@ import PropTypes from "prop-types"; const {Option} = Select; -const SelectViewMode = ({viewMode, setViewMode, localStorageKey, toolTipText}) => { +const SelectViewMode = ({viewMode, setViewMode, localStorageKey, toolTipText, viewModes}) => { return ( - - + {viewModes.map(viewMode => ( + + ))} @@ -35,6 +33,12 @@ SelectViewMode.propTypes = { viewMode: PropTypes.string.isRequired, setViewMode: PropTypes.func.isRequired, localStorageKey: PropTypes.string.isRequired, + toolTipText: PropTypes.string.isRequired, + viewModes: PropTypes.arrayOf(PropTypes.shape({ + value: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + icon: PropTypes.element, + })).isRequired, }; export default SelectViewMode; \ No newline at end of file diff --git a/web-app/src/components/lens_issues/LensIssueFormModal.jsx b/web-app/src/components/lens_issues/LensIssueFormModal.jsx index 09a39ad..241687e 100644 --- a/web-app/src/components/lens_issues/LensIssueFormModal.jsx +++ b/web-app/src/components/lens_issues/LensIssueFormModal.jsx @@ -1,14 +1,19 @@ import {useEffect, useState} from "react"; -import {Modal, Input, Button, notification, Typography, Collapse, Steps, Row, Alert, Col, DatePicker, Spin} from "antd"; +import { + Modal, Input, Button, notification, Typography, Collapse, Steps, Row, Alert, Col, DatePicker, Spin, Grid +} from "antd"; import PropTypes from "prop-types"; import getAllPatients from "../../api/patients/GetAllPatients.jsx"; import {useAuth} from "../../AuthContext.jsx"; import dayjs from "dayjs"; import getNotIssuedLenses from "../../api/lenses/GetNotIssuedLenses.jsx"; +const {useBreakpoint} = Grid; const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { const {user} = useAuth(); + const screens = useBreakpoint(); + const [patients, setPatients] = useState([]); const [lenses, setLenses] = useState([]); @@ -37,8 +42,7 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { } catch (error) { console.error(error); notification.error({ - message: "Ошибка загрузки пациентов", - description: "Проверьте подключение к сети.", + message: "Ошибка загрузки пациентов", description: "Проверьте подключение к сети.", }); } }; @@ -50,8 +54,7 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { } catch (error) { console.error(error); notification.error({ - message: "Ошибка загрузки линз", - description: "Проверьте подключение к сети.", + message: "Ошибка загрузки линз", description: "Проверьте подключение к сети.", }); } }; @@ -79,21 +82,18 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { .some(value => value.toLowerCase().includes(searchLower)); }); - const patientsItems = filteredPatients.map((patient) => ( - { + const patientsItems = filteredPatients.map((patient) => ({ key: patient.id, label: `${patient.last_name} ${patient.first_name} (${new Date(patient.birthday).toLocaleDateString("ru-RU")})`, - children: -
-

Пациент: {patient.last_name} {patient.first_name}

-

Дата рождения: {new Date(patient.birthday).toLocaleDateString("ru-RU")}

-

Диагноз: {patient.diagnosis}

-

Email: {patient.email}

-

Телефон: {patient.phone}

- -
, - } - )); + children:
+

Пациент: {patient.last_name} {patient.first_name}

+

Дата рождения: {new Date(patient.birthday).toLocaleDateString("ru-RU")}

+

Диагноз: {patient.diagnosis}

+

Email: {patient.email}

+

Телефон: {patient.phone}

+ +
, + })); const filteredLenses = lenses.filter((lens) => { const searchLower = searchLensString.toLowerCase(); @@ -103,25 +103,20 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { .some(value => value.toLowerCase().includes(searchLower)); }) - const lensesItems = filteredLenses.map((lens) => ( - { - key: lens.id, - label: `Линза ${lens.side} ${lens.diameter} мм`, - children: -
-

Диаметр: {lens.diameter}

-

Тор: {lens.tor}

-

Пресетная рефракция: {lens.preset_refraction}

-

Диаметр: {lens.diameter}

-

FVC: {lens.fvc}

-

Острота зрения (Trial): {lens.trial}

-

Периферийная торичность: {lens.periphery_toricity}

-

Сторона: {lens.side}

-

Esa: {lens.esa}

- -
, - } - )); + const lensesItems = filteredLenses.map((lens) => ({ + key: lens.id, label: `Линза ${lens.side} ${lens.diameter} мм`, children:
+

Диаметр: {lens.diameter}

+

Тор: {lens.tor}

+

Пресетная рефракция: {lens.preset_refraction}

+

Диаметр: {lens.diameter}

+

FVC: {lens.fvc}

+

Острота зрения (Trial): {lens.trial}

+

Периферийная торичность: {lens.periphery_toricity}

+

Сторона: {lens.side}

+

Esa: {lens.esa}

+ +
, + })); const SelectPatientStep = () => { return selectedPatient ? ( @@ -139,9 +134,7 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { > Выбрать другого пациента - - ) : ( - <> + ) : (<> { items={patientsItems} /> - - ) + ) }; const SelectLensStep = () => { - return selectedLens ? ( -
+ return selectedLens ? (
{selectedLens.diameter} {selectedLens.tor} {selectedLens.preset_refraction} @@ -181,9 +172,7 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { > Выбрать другую линзу -
- ) : ( - <> +
) : (<> { items={lensesItems} /> - - ) + ) }; const ConfirmStep = () => { - return ( - <> + return (<> {

Сторона: {selectedLens.side}

Esa: {selectedLens.esa}

- - ); + ); }; - const steps = [ - { - title: 'Выбор пациента', - content: , - }, - { - title: 'Выбор линзы', - content: , - }, - { - title: 'Подтверждение', - content: , - }, - ]; + const steps = [{ + title: 'Выбор пациента', content: , + }, { + title: 'Выбор линзы', content: , + }, { + title: 'Подтверждение', content: , + },]; const isActiveNextButton = () => { if (currentStep === 0 && !selectedPatient) { @@ -286,8 +265,7 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { return currentStep === steps.length - 1; }; - return ( - { @@ -299,28 +277,22 @@ const LensIssueFormModal = ({visible, onCancel, onSubmit}) => { }} footer={null} maskClosable={false} - width={window.innerWidth > 768 ? 700 : "90%"} + width={!screens.xs ? 700 : "90%"} centered > - {loading ? ( -
+ {loading ? (
-
- ) : ( -
+
) : (
{steps[currentStep].content} -
- )} +
)} - {window.innerWidth > 768 && ( - 768 ? "horizontal" : "vertical"} - /> - )} + direction={!screens.xs ? "horizontal" : "vertical"} + />)} { {isActiveFinishButton() ? "Завершить" : "Далее"} -
- ); + ); }; LensIssueFormModal.propTypes = { - visible: PropTypes.bool.isRequired, - onCancel: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, + visible: PropTypes.bool.isRequired, onCancel: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired, }; export default LensIssueFormModal; diff --git a/web-app/src/pages/IssuesPage.jsx b/web-app/src/pages/IssuesPage.jsx index bb70ab0..29059b0 100644 --- a/web-app/src/pages/IssuesPage.jsx +++ b/web-app/src/pages/IssuesPage.jsx @@ -1,23 +1,40 @@ -import {notification, Spin, Table, Input, Row, Col, DatePicker, Tooltip, Button, FloatButton, Typography} from "antd"; +import { + notification, + Spin, + Table, + Input, + Row, + Col, + DatePicker, + Tooltip, + Button, + FloatButton, + Typography, + Timeline, Grid +} from "antd"; import getAllLensIssues from "../api/lens_issues/GetAllLensIssues.jsx"; import {useEffect, useState} from "react"; import {useAuth} from "../AuthContext.jsx"; -import {DatabaseOutlined, LoadingOutlined, PlusOutlined} from "@ant-design/icons"; +import {DatabaseOutlined, LoadingOutlined, PlusOutlined, UnorderedListOutlined} from "@ant-design/icons"; import LensIssueViewModal from "../components/lens_issues/LensIssueViewModal.jsx"; import dayjs from "dayjs"; import LensIssueFormModal from "../components/lens_issues/LensIssueFormModal.jsx"; import addLensIssue from "../api/lens_issues/AddLensIssue.jsx"; +import SelectViewMode from "../components/SelectViewMode.jsx"; const {Title} = Typography; +const {useBreakpoint} = Grid; const IssuesPage = () => { const {user} = useAuth(); + const screens = useBreakpoint(); const [loading, setLoading] = useState(true); const [lensIssues, setLensIssues] = useState([]); const [searchTerm, setSearchTerm] = useState(""); const [selectedIssue, setSelectedIssue] = useState(null); const [isModalVisible, setIsModalVisible] = useState(false); + const [viewMode, setViewMode] = useState("table"); const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(10); @@ -27,6 +44,7 @@ const IssuesPage = () => { useEffect(() => { fetchLensIssuesWithCache(); + fetchViewModeFromCache(); document.title = "Выдача линз"; }, []); @@ -49,6 +67,13 @@ const IssuesPage = () => { } }; + const fetchViewModeFromCache = () => { + const cachedViewMode = localStorage.getItem("viewModeIssues"); + if (cachedViewMode) { + setViewMode(cachedViewMode); + } + }; + const handleAddIssue = () => { setSelectedIssue(null); setIsModalVisible(true); @@ -123,6 +148,19 @@ const IssuesPage = () => { } ); + const viewModes = [ + { + value: "table", + label: "Таблица", + icon: , + }, + { + value: "timeline", + label: "Лента", + icon: , + }, + ]; + const columns = [ { title: "Дата выдачи", @@ -158,25 +196,77 @@ const IssuesPage = () => { }, ]; + const TableView = () => ( + { + setCurrentPage(page); + setPageSize(newPageSize); + }, + }} + showSorterTooltip={false} + /> + ); + + const timeLineItems = filteredIssues.map(issue => ({ + label: dayjs(issue.issue_date).format("DD.MM.YYYY"), + children: ( + + +

Пациент: {issue.patient.last_name} {issue.patient.first_name}

+ + +

Линза: {issue.lens.side} {issue.lens.diameter}

+ + + + + + ), + })); + + const TimeLineView = () => ( + + ); + return (
<DatabaseOutlined/> Выдача линз -
+ { setStartFilterDate(null); setEndFilterDate(null); }} - style={{marginLeft: 10}} type={"primary"} block > @@ -212,29 +301,27 @@ const IssuesPage = () => { )} - + + + {loading ? (
}/>
+ ) : viewMode === "table" ? ( + ) : ( -
{ - setCurrentPage(page); - setPageSize(newPageSize); - }, - }} - showSorterTooltip={false} - /> + )} { } }; + const fetchViewModeFromCache = () => { const cachedViewMode = localStorage.getItem("viewModeLenses"); if (cachedViewMode) { @@ -226,6 +233,19 @@ const LensesPage = () => { /> ); + const viewModes = [ + { + value: "tile", + label: "Плитка", + icon: + }, + { + value: "table", + label: "Таблица", + icon: + } + ]; + const columns = [ { title: "Тор", @@ -354,6 +374,7 @@ const LensesPage = () => { setViewMode={setViewMode} localStorageKey={"viewModeLenses"} toolTipText={"Формат отображения линз"} + viewModes={viewModes} /> diff --git a/web-app/src/pages/PatientsPage.jsx b/web-app/src/pages/PatientsPage.jsx index e6ba86a..66857dc 100644 --- a/web-app/src/pages/PatientsPage.jsx +++ b/web-app/src/pages/PatientsPage.jsx @@ -15,10 +15,11 @@ import { Typography } from "antd"; import { + BuildOutlined, LoadingOutlined, PlusOutlined, SortAscendingOutlined, - SortDescendingOutlined, + SortDescendingOutlined, TableOutlined, TeamOutlined } from "@ant-design/icons"; import {useAuth} from "../AuthContext.jsx"; @@ -223,6 +224,19 @@ const PatientsPage = () => { /> ); + const viewModes = [ + { + value: "tile", + label: "Плитка", + icon: + }, + { + value: "table", + label: "Таблица", + icon: + } + ]; + const columns = [ { title: "Фамилия", @@ -352,11 +366,12 @@ const PatientsPage = () => { setViewMode={setViewMode} localStorageKey={"viewModePatients"} toolTipText={"Формат отображения пациентов"} + viewModes={viewModes} /> - {loading ? ( + {loading ? (