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 (
Выдача линз
-
+
{
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 ? (