diff --git a/web-app/src/api/lenses/UpdateLens.jsx b/web-app/src/api/lenses/UpdateLens.jsx
index ddf7cc7..2980ee6 100644
--- a/web-app/src/api/lenses/UpdateLens.jsx
+++ b/web-app/src/api/lenses/UpdateLens.jsx
@@ -3,7 +3,6 @@ import CONFIG from "../../core/Config.jsx";
const updateLens = async (token, lensId, lensData) => {
- console.log(lensId, lensData);
try {
const response = await axios.put(`${CONFIG.BASE_URL}/lenses/${lensId}/`, lensData, {
headers: {
diff --git a/web-app/src/components/SelectViewMode.jsx b/web-app/src/components/SelectViewMode.jsx
new file mode 100644
index 0000000..7e83f5a
--- /dev/null
+++ b/web-app/src/components/SelectViewMode.jsx
@@ -0,0 +1,40 @@
+import {BuildOutlined, TableOutlined} from "@ant-design/icons";
+import {Select, Tooltip} from "antd";
+import PropTypes from "prop-types";
+
+const {Option} = Select;
+
+const SelectViewMode = ({viewMode, setViewMode, localStorageKey, toolTipText}) => {
+ return (
+
+
+
+
+ )
+};
+
+SelectViewMode.propTypes = {
+ viewMode: PropTypes.string.isRequired,
+ setViewMode: PropTypes.func.isRequired,
+ localStorageKey: PropTypes.string.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
new file mode 100644
index 0000000..4205539
--- /dev/null
+++ b/web-app/src/components/lens_issues/LensIssueFormModal.jsx
@@ -0,0 +1,193 @@
+import {useEffect, useState} from "react";
+import {Modal, Form, Input, Select, Collapse, Button, notification, List} from "antd";
+import PropTypes from "prop-types";
+import getAllPatients from "../../api/patients/GetAllPatients.jsx";
+import getAllLenses from "../../api/lenses/GetAllLenses.jsx";
+import {useAuth} from "../../AuthContext.jsx";
+
+const {Option} = Select;
+const {Panel} = Collapse;
+
+const LensIssueFormModal = ({visible, onCancel, onSubmit}) => {
+ const {user} = useAuth();
+
+ const [form] = Form.useForm();
+ const [patients, setPatients] = useState([]);
+ const [lenses, setLenses] = useState([]);
+ const [selectedPatient, setSelectedPatient] = useState(null);
+ const [selectedLens, setSelectedLens] = useState(null);
+
+ const [searchPatientString, setSearchPatientString] = useState("");
+ const [searchLensString, setSearchLensString] = useState("");
+
+ useEffect(() => {
+ if (visible) {
+ fetchPatients();
+ fetchLenses();
+ }
+ }, [visible]);
+
+ const fetchPatients = async () => {
+ try {
+ const data = await getAllPatients(user.token);
+ setPatients(data);
+ } catch (error) {
+ console.log(error);
+ notification.error({
+ message: "Ошибка загрузки пациентов",
+ description: "Проверьте подключение к сети.",
+ });
+ }
+ };
+
+ const fetchLenses = async () => {
+ try {
+ const data = await getAllLenses(user.token);
+ setLenses(data);
+ } catch (error) {
+ console.log(error);
+ notification.error({
+ message: "Ошибка загрузки линз",
+ description: "Проверьте подключение к сети.",
+ });
+ }
+ };
+
+ const handleOk = async () => {
+ try {
+ const values = await form.validateFields();
+ onSubmit({...values, patient: selectedPatient, lens: selectedLens});
+ form.resetFields();
+ setSelectedPatient(null);
+ setSelectedLens(null);
+ } catch (errorInfo) {
+ console.log("Validation Failed:", errorInfo);
+ }
+ };
+
+ const flteredPatients = patients
+ .filter((patient) => {
+ const searchLower = searchPatientString.toLowerCase();
+
+ return Object.values(patient)
+ .filter(value => typeof value === "string")
+ .some(value => value.toLowerCase().includes(searchLower));
+ });
+
+ const filteredLenses = lenses
+ .filter((lens) => {
+ const searchLower = searchLensString.toLowerCase();
+ return lens.side.toLowerCase().includes(searchLower);
+ });
+
+ const items = flteredPatients.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}
+
,
+ }
+ ));
+
+ return (
+ {
+ form.resetFields();
+ setSelectedPatient(null);
+ setSelectedLens(null);
+ onCancel();
+ }}
+ onOk={handleOk}
+ okText="Сохранить"
+ cancelText="Отмена"
+ maskClosable={false}
+ centered
+ >
+
+ setSearchPatientString(e.target.value)}
+ style={{marginBottom: 16}}
+ allowClear
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+LensIssueFormModal.propTypes = {
+ visible: PropTypes.bool.isRequired,
+ onCancel: PropTypes.func.isRequired,
+ onSubmit: PropTypes.func.isRequired,
+ lensIssue: PropTypes.shape({
+ issue_date: PropTypes.string,
+ patient: PropTypes.shape({
+ first_name: PropTypes.string,
+ last_name: PropTypes.string,
+ patronymic: PropTypes.string,
+ birthday: PropTypes.string,
+ address: PropTypes.string,
+ email: PropTypes.string,
+ phone: PropTypes.string,
+ diagnosis: PropTypes.string,
+ correction: PropTypes.string,
+ }),
+ doctor: PropTypes.shape({
+ last_name: PropTypes.string,
+ first_name: PropTypes.string,
+ login: PropTypes.string,
+ }),
+ lens: PropTypes.shape({
+ id: PropTypes.number.isRequired,
+ tor: PropTypes.number.isRequired,
+ diameter: PropTypes.number.isRequired,
+ esa: PropTypes.number.isRequired,
+ fvc: PropTypes.number.isRequired,
+ preset_refraction: PropTypes.number.isRequired,
+ periphery_toricity: PropTypes.number.isRequired,
+ side: PropTypes.string.isRequired,
+ issued: PropTypes.bool.isRequired,
+ trial: PropTypes.number.isRequired,
+ }),
+ }),
+};
+
+export default LensIssueFormModal;
diff --git a/web-app/src/pages/IssuesPage.jsx b/web-app/src/pages/IssuesPage.jsx
index 2a9b17a..8675c80 100644
--- a/web-app/src/pages/IssuesPage.jsx
+++ b/web-app/src/pages/IssuesPage.jsx
@@ -1,10 +1,13 @@
-import {notification, Spin, Table, Input, Row, Col, DatePicker, Tooltip, Button, FloatButton} from "antd";
+import {notification, Spin, Table, Input, Row, Col, DatePicker, Tooltip, Button, FloatButton, Typography} from "antd";
import getAllLensIssues from "../api/lens_issues/GetAllLensIssues.jsx";
import {useEffect, useState} from "react";
import {useAuth} from "../AuthContext.jsx";
-import {LoadingOutlined, PlusOutlined} from "@ant-design/icons";
+import {DatabaseOutlined, LoadingOutlined, PlusOutlined} from "@ant-design/icons";
import LensIssueViewModal from "../components/lens_issues/LensIssueViewModal.jsx";
import dayjs from "dayjs";
+import LensIssueFormModal from "../components/lens_issues/LensIssueFormModal.jsx";
+
+const {Title} = Typography;
const IssuesPage = () => {
const {user} = useAuth();
@@ -13,6 +16,7 @@ const IssuesPage = () => {
const [lensIssues, setLensIssues] = useState([]);
const [searchTerm, setSearchTerm] = useState("");
const [selectedIssue, setSelectedIssue] = useState(null);
+ const [isModalVisible, setIsModalVisible] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
@@ -22,6 +26,7 @@ const IssuesPage = () => {
useEffect(() => {
fetchLensIssuesWithCache();
+ document.title = "Выдача линз";
}, []);
useEffect(() => {
@@ -43,13 +48,21 @@ const IssuesPage = () => {
const handleAddIssue = () => {
setSelectedIssue(null);
-
+ setIsModalVisible(true);
};
const handleCloseViewModal = () => {
setSelectedIssue(null);
};
+ const handleCloseFormModal = () => {
+ setIsModalVisible(false);
+ };
+
+ const handleSubmitFormModal = () => {
+
+ };
+
const fetchLensIssues = async () => {
try {
const data = await getAllLensIssues(user.token);
@@ -129,6 +142,7 @@ const IssuesPage = () => {
return (
+
Выдача линз
{
tooltip={"Добавить выдачу линзы"}
/>
+
+
{
const {user} = useAuth();
@@ -53,6 +62,7 @@ const LensesPage = () => {
useEffect(() => {
fetchLensWithCache();
fetchViewModeFromCache();
+ document.title = "Линзы";
}, []);
useEffect(() => {
@@ -98,11 +108,6 @@ const LensesPage = () => {
}
};
- const handleChangeViewMode = (mode) => {
- setViewMode(mode);
- localStorage.setItem("viewModeLenses", mode);
- };
-
const filteredLenses = lenses.filter((lens) => {
const textMatch = Object.values(lens).some((value) =>
value?.toString().toLowerCase().includes(searchText.toLowerCase())
@@ -324,6 +329,7 @@ const LensesPage = () => {
return (
+
Линзы
{
-
-
-
+
diff --git a/web-app/src/pages/LoginPage.jsx b/web-app/src/pages/LoginPage.jsx
index 652372b..c68b8b7 100644
--- a/web-app/src/pages/LoginPage.jsx
+++ b/web-app/src/pages/LoginPage.jsx
@@ -16,6 +16,7 @@ const LoginPage = () => {
if (user) {
navigate("/");
}
+ document.title = "Авторизация";
}, [user, navigate]);
const onFinish = async (values) => {
diff --git a/web-app/src/pages/PatientsPage.jsx b/web-app/src/pages/PatientsPage.jsx
index 239cb8a..e6ba86a 100644
--- a/web-app/src/pages/PatientsPage.jsx
+++ b/web-app/src/pages/PatientsPage.jsx
@@ -1,6 +1,26 @@
import {useEffect, useState} from "react";
-import {Input, Select, List, FloatButton, Row, Col, Spin, notification, Tooltip, Table, Button, Popconfirm} from "antd";
-import {LoadingOutlined, PlusOutlined} from "@ant-design/icons";
+import {
+ Input,
+ Select,
+ List,
+ FloatButton,
+ Row,
+ Col,
+ Spin,
+ notification,
+ Tooltip,
+ Table,
+ Button,
+ Popconfirm,
+ Typography
+} from "antd";
+import {
+ LoadingOutlined,
+ PlusOutlined,
+ SortAscendingOutlined,
+ SortDescendingOutlined,
+ TeamOutlined
+} from "@ant-design/icons";
import {useAuth} from "../AuthContext.jsx";
import getAllPatients from "../api/patients/GetAllPatients.jsx";
import PatientListCard from "../components/patients/PatientListCard.jsx";
@@ -8,8 +28,10 @@ import PatientFormModal from "../components/patients/PatientFormModal.jsx";
import updatePatient from "../api/patients/UpdatePatient.jsx";
import addPatient from "../api/patients/AddPatient.jsx";
import deletePatient from "../api/patients/DeletePatient.jsx";
+import SelectViewMode from "../components/SelectViewMode.jsx";
const {Option} = Select;
+const {Title} = Typography
const PatientsPage = () => {
const {user} = useAuth();
@@ -28,6 +50,7 @@ const PatientsPage = () => {
useEffect(() => {
fetchPatientsWithCache();
fetchViewModeFromCache();
+ document.title = "Пациенты";
}, []);
useEffect(() => {
@@ -80,11 +103,6 @@ const PatientsPage = () => {
}
};
- const handleChangeViewMode = (mode) => {
- setViewMode(mode);
- localStorage.setItem("viewModePatients", mode);
- };
-
const filteredPatients = patients
.filter((patient) => {
const searchLower = searchText.toLowerCase();
@@ -293,8 +311,9 @@ const PatientsPage = () => {
return (