сделал заготовку под страницу с линзами
This commit is contained in:
parent
ddd551adb4
commit
8b7c427602
@ -23,7 +23,7 @@ class LensesService:
|
|||||||
tor=lens.tor,
|
tor=lens.tor,
|
||||||
trial=lens.trial,
|
trial=lens.trial,
|
||||||
esa=lens.esa,
|
esa=lens.esa,
|
||||||
fvc=lens.fvs,
|
fvc=lens.fvc,
|
||||||
preset_refraction=lens.preset_refraction,
|
preset_refraction=lens.preset_refraction,
|
||||||
diameter=lens.diameter,
|
diameter=lens.diameter,
|
||||||
periphery_toricity=lens.periphery_toricity,
|
periphery_toricity=lens.periphery_toricity,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ from starlette.middleware.cors import CORSMiddleware
|
|||||||
from app.controllers.auth_router import router as auth_router
|
from app.controllers.auth_router import router as auth_router
|
||||||
from app.controllers.register_routes import router as register_router
|
from app.controllers.register_routes import router as register_router
|
||||||
from app.controllers.patients_router import router as patients_router
|
from app.controllers.patients_router import router as patients_router
|
||||||
|
from app.controllers.lenses_router import router as lens_router
|
||||||
from app.settings import settings
|
from app.settings import settings
|
||||||
|
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ def start_app():
|
|||||||
api_app.include_router(auth_router, prefix=settings.APP_PREFIX, tags=['auth'])
|
api_app.include_router(auth_router, prefix=settings.APP_PREFIX, tags=['auth'])
|
||||||
api_app.include_router(register_router, prefix=settings.APP_PREFIX, tags=['register'])
|
api_app.include_router(register_router, prefix=settings.APP_PREFIX, tags=['register'])
|
||||||
api_app.include_router(patients_router, prefix=settings.APP_PREFIX, tags=['patients'])
|
api_app.include_router(patients_router, prefix=settings.APP_PREFIX, tags=['patients'])
|
||||||
|
api_app.include_router(lens_router, prefix=settings.APP_PREFIX, tags=['lenses'])
|
||||||
|
|
||||||
return api_app
|
return api_app
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import {Routes, Route, Navigate} from "react-router-dom";
|
import {Routes, Route, Navigate} from "react-router-dom";
|
||||||
import PrivateRoute from "./components/patients/PrivateRoute.jsx";
|
import PrivateRoute from "./components/PrivateRoute.jsx";
|
||||||
import LoginPage from "./pages/LoginPage.jsx";
|
import LoginPage from "./pages/LoginPage.jsx";
|
||||||
import MainLayout from "./layouts/MainLayout.jsx";
|
import MainLayout from "./layouts/MainLayout.jsx";
|
||||||
import PatientsPage from "./pages/PatientsPage.jsx";
|
import PatientsPage from "./pages/PatientsPage.jsx";
|
||||||
|
|||||||
22
web-app/src/api/lenses/AddLens.jsx
Normal file
22
web-app/src/api/lenses/AddLens.jsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import CONFIG from "../../core/Config.jsx";
|
||||||
|
import axios from "axios";
|
||||||
|
import {useAuth} from "../../AuthContext.jsx";
|
||||||
|
|
||||||
|
|
||||||
|
const addLens = async (token, lens) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`${CONFIG.BASE_URL}/lenses/`, lens, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
if (error.response?.status === 401) {
|
||||||
|
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
|
||||||
|
}
|
||||||
|
throw new Error(error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default addLens;
|
||||||
21
web-app/src/api/lenses/DeleteLens.jsx
Normal file
21
web-app/src/api/lenses/DeleteLens.jsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import CONFIG from "../../core/Config.jsx";
|
||||||
|
|
||||||
|
|
||||||
|
const deleteLens = async (token, lens_id) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.delete(`${CONFIG.BASE_URL}/lenses/${lens_id}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
if (error.response?.status === 401) {
|
||||||
|
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
|
||||||
|
}
|
||||||
|
throw new Error(error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default deleteLens;
|
||||||
20
web-app/src/api/lenses/GetAllLenses.jsx
Normal file
20
web-app/src/api/lenses/GetAllLenses.jsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import CONFIG from "../../core/Config.jsx";
|
||||||
|
|
||||||
|
const getAllLenses = async (token) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`${CONFIG.BASE_URL}/lenses/`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
if (error.response?.status === 401) {
|
||||||
|
throw Error("Ошибка авторизации: пользователь неяден или токен недействителен");
|
||||||
|
}
|
||||||
|
throw Error(error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getAllLenses;
|
||||||
20
web-app/src/api/lenses/UpdateLens.jsx
Normal file
20
web-app/src/api/lenses/UpdateLens.jsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
|
||||||
|
const updateLens = async (token, lensId, lensData) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.put(`${CONFIG.BASE_URL}/lenses/${lensId}/`, lensData, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
if (error.response?.status === 401) {
|
||||||
|
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
|
||||||
|
}
|
||||||
|
throw new Error(error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default updateLens;
|
||||||
@ -2,7 +2,7 @@ import axios from "axios";
|
|||||||
import CONFIG from "../../core/Config.jsx";
|
import CONFIG from "../../core/Config.jsx";
|
||||||
|
|
||||||
|
|
||||||
const AddPatient = async (token, patient) => {
|
const addPatient = async (token, patient) => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(`${CONFIG.BASE_URL}/patients/`, patient, {
|
const response = await axios.post(`${CONFIG.BASE_URL}/patients/`, patient, {
|
||||||
headers: {
|
headers: {
|
||||||
@ -11,8 +11,11 @@ const AddPatient = async (token, patient) => {
|
|||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error.response?.status === 401) {
|
||||||
|
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
|
||||||
|
}
|
||||||
throw new Error(error.message);
|
throw new Error(error.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AddPatient;
|
export default addPatient;
|
||||||
@ -2,7 +2,7 @@ import axios from "axios";
|
|||||||
import CONFIG from "../../core/Config.jsx";
|
import CONFIG from "../../core/Config.jsx";
|
||||||
|
|
||||||
|
|
||||||
const DeletePatient = async (token, patient_id) => {
|
const deletePatient = async (token, patient_id) => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.delete(`${CONFIG.BASE_URL}/patients/${patient_id}/`, {
|
const response = await axios.delete(`${CONFIG.BASE_URL}/patients/${patient_id}/`, {
|
||||||
headers: {
|
headers: {
|
||||||
@ -11,9 +11,12 @@ const DeletePatient = async (token, patient_id) => {
|
|||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error.response?.status === 401) {
|
||||||
|
throw new Error("Ошибка авторизации: пользователь не найден или токен недействителен");
|
||||||
|
}
|
||||||
throw new Error(error.message);
|
throw new Error(error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default DeletePatient;
|
export default deletePatient;
|
||||||
@ -3,11 +3,6 @@ import CONFIG from "../../core/Config.jsx";
|
|||||||
|
|
||||||
|
|
||||||
const getAllPatients = async (token) => {
|
const getAllPatients = async (token) => {
|
||||||
|
|
||||||
if (!token) {
|
|
||||||
throw new Error("Ошибка авторизации: пользователь не аутентифицирован");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`${CONFIG.BASE_URL}/patients/`, {
|
const response = await axios.get(`${CONFIG.BASE_URL}/patients/`, {
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@ -3,10 +3,6 @@ import CONFIG from "../../core/Config.jsx";
|
|||||||
|
|
||||||
|
|
||||||
const updatePatient = async (token, patientId, patientData) => {
|
const updatePatient = async (token, patientId, patientData) => {
|
||||||
if (!token) {
|
|
||||||
throw new Error("Ошибка авторизации: пользователь не аутентифицирован");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.put(`${CONFIG.BASE_URL}/patients/${patientId}/`, patientData, {
|
const response = await axios.put(`${CONFIG.BASE_URL}/patients/${patientId}/`, patientData, {
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import {Navigate, Outlet} from "react-router-dom";
|
import {Navigate, Outlet} from "react-router-dom";
|
||||||
import {useAuth} from "../../AuthContext.jsx";
|
import {useAuth} from "../AuthContext.jsx";
|
||||||
|
|
||||||
const PrivateRoute = () => {
|
const PrivateRoute = () => {
|
||||||
const {user} = useAuth();
|
const {user} = useAuth();
|
||||||
0
web-app/src/components/lenses/LensFormModal.jsx
Normal file
0
web-app/src/components/lenses/LensFormModal.jsx
Normal file
81
web-app/src/components/lenses/LensListCard.jsx
Normal file
81
web-app/src/components/lenses/LensListCard.jsx
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import { Card, Modal, Tooltip } from "antd";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import { DeleteOutlined, EditOutlined, EyeOutlined } from "@ant-design/icons";
|
||||||
|
import { useState } from "react";
|
||||||
|
import LensViewModal from "./LensViewModal.jsx";
|
||||||
|
|
||||||
|
const LensListCard = ({ lens, handleEditLens, handleDeleteLens }) => {
|
||||||
|
const [showModalInfo, setShowModalInfo] = useState(false);
|
||||||
|
|
||||||
|
const deleteLensConfirm = () => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "Удаление линзы",
|
||||||
|
content: `Вы уверены, что хотите удалить линзу с параметрами ${lens.side} ${lens.diameter}мм?`,
|
||||||
|
okText: "Да, удалить",
|
||||||
|
cancelText: "Отмена",
|
||||||
|
onOk: () => handleDeleteLens(lens.id),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleViewLens = () => {
|
||||||
|
setShowModalInfo(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const actions = [
|
||||||
|
<Tooltip title="Просмотр линзы" key={"viewLens"}>
|
||||||
|
<EyeOutlined onClick={handleViewLens} />
|
||||||
|
</Tooltip>,
|
||||||
|
<Tooltip title="Редактирование линзы" key={"editLens"}>
|
||||||
|
<EditOutlined onClick={() => handleEditLens(lens)} />
|
||||||
|
</Tooltip>,
|
||||||
|
<Tooltip title="Удаление линзы" key={"deleteLens"}>
|
||||||
|
<DeleteOutlined
|
||||||
|
onClick={deleteLensConfirm}
|
||||||
|
style={{ color: "red" }}
|
||||||
|
/>
|
||||||
|
</Tooltip>,
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card
|
||||||
|
type="inner"
|
||||||
|
title={`Линза ${lens.side} ${lens.diameter} мм`}
|
||||||
|
actions={actions}
|
||||||
|
>
|
||||||
|
<p><strong>🔬 Тор:</strong> {lens.tor} D</p>
|
||||||
|
<p><strong>📏 Диаметр:</strong> {lens.diameter} мм</p>
|
||||||
|
<p><strong>🔄 Пресетная рефракция:</strong> {lens.preset_refraction} D</p>
|
||||||
|
<p><strong>⚙️ Перефирийная торичность:</strong> {lens.periphery_toricity} D</p>
|
||||||
|
{lens.issued && <p><strong>✅ Линза выдана</strong></p>}
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{showModalInfo && (
|
||||||
|
<LensViewModal
|
||||||
|
visible={showModalInfo}
|
||||||
|
onCancel={() => setShowModalInfo(false)}
|
||||||
|
lens={lens}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
LensListCard.propTypes = {
|
||||||
|
lens: PropTypes.shape({
|
||||||
|
id: PropTypes.number.isRequired,
|
||||||
|
tor: PropTypes.number.isRequired,
|
||||||
|
trial: PropTypes.number,
|
||||||
|
esa: PropTypes.number,
|
||||||
|
fvc: PropTypes.number,
|
||||||
|
preset_refraction: PropTypes.number.isRequired,
|
||||||
|
diameter: PropTypes.number.isRequired,
|
||||||
|
periphery_toricity: PropTypes.number.isRequired,
|
||||||
|
side: PropTypes.string.isRequired,
|
||||||
|
issued: PropTypes.bool.isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
handleEditLens: PropTypes.func.isRequired,
|
||||||
|
handleDeleteLens: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LensListCard;
|
||||||
80
web-app/src/components/lenses/LensViewModal.jsx
Normal file
80
web-app/src/components/lenses/LensViewModal.jsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import {Button, Col, Modal, Row, Typography, Divider} from "antd";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
const {Text, Title} = Typography;
|
||||||
|
|
||||||
|
const LensViewModal = ({visible, onCancel, lens}) => {
|
||||||
|
if (!lens) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title="Просмотр линзы"
|
||||||
|
open={visible}
|
||||||
|
onCancel={onCancel}
|
||||||
|
footer={
|
||||||
|
<Button onClick={onCancel} type="primary">
|
||||||
|
Закрыть
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Row gutter={24}>
|
||||||
|
<Col xs={24} md={12}>
|
||||||
|
<div style={{marginBottom: 12}}>
|
||||||
|
<Title level={5}>🔬 Тор</Title>
|
||||||
|
<Text>{lens.tor} D</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{marginBottom: 12}}>
|
||||||
|
<Title level={5}>📏 Диаметр</Title>
|
||||||
|
<Text>{lens.diameter} мм</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{marginBottom: 12}}>
|
||||||
|
<Title level={5}>🔄 Пресетная рефракция</Title>
|
||||||
|
<Text>{lens.preset_refraction} D</Text>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col xs={24} md={12}>
|
||||||
|
<div style={{marginBottom: 12}}>
|
||||||
|
<Title level={5}>⚙️ Перефирийная торичность</Title>
|
||||||
|
<Text>{lens.periphery_toricity} D</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{marginBottom: 12}}>
|
||||||
|
<Title level={5}>⛓ Сторона</Title>
|
||||||
|
<Text>{lens.side}</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{marginBottom: 12}}>
|
||||||
|
<Title level={5}>✅ Статус выдачи</Title>
|
||||||
|
<Text>{lens.issued ? 'Выдана' : 'Не выдана'}</Text>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Divider/>
|
||||||
|
|
||||||
|
<div style={{marginBottom: 12}}>
|
||||||
|
<Title level={5}>⚖️ Пробная линза (Trial)</Title>
|
||||||
|
<Text>{lens.trial.toFixed(2)} D</Text>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
LensViewModal.propTypes = {
|
||||||
|
visible: PropTypes.bool.isRequired,
|
||||||
|
onCancel: PropTypes.func.isRequired,
|
||||||
|
lens: PropTypes.shape({
|
||||||
|
tor: PropTypes.number.isRequired,
|
||||||
|
diameter: 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 LensViewModal;
|
||||||
@ -1,12 +1,156 @@
|
|||||||
|
import {useState, useEffect} from "react";
|
||||||
|
import {Input, Select, List, FloatButton, Row, Col, Spin} from "antd";
|
||||||
|
import {LoadingOutlined, PlusOutlined} from "@ant-design/icons";
|
||||||
|
import LensCard from "../components/lenses/LensListCard.jsx";
|
||||||
|
import getAllLenses from "../api/lenses/GetAllLenses.jsx";
|
||||||
|
import addLens from "../api/lenses/AddLens.jsx";
|
||||||
|
import updateLens from "../api/lenses/UpdateLens.jsx";
|
||||||
|
import deleteLens from "../api/lenses/DeleteLens.jsx";
|
||||||
|
import {useAuth} from "../AuthContext.jsx";
|
||||||
|
|
||||||
|
const {Option} = Select;
|
||||||
|
|
||||||
|
const LensesPage = () => {
|
||||||
|
const {user} = useAuth();
|
||||||
|
|
||||||
const LensPage = () => {
|
const [current, setCurrent] = useState(1);
|
||||||
return (
|
const [pageSize, setPageSize] = useState(10);
|
||||||
<>
|
|
||||||
|
|
||||||
</>
|
const [searchText, setSearchText] = useState("");
|
||||||
)
|
const [sortOrder, setSortOrder] = useState("asc");
|
||||||
|
const [lenses, setLenses] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
|
const [selectedLens, setSelectedLens] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchLenses();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchLenses = async () => {
|
||||||
|
if (!user || !user.token) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await getAllLenses(user.token);
|
||||||
|
setLenses(data);
|
||||||
|
setLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Ошибка загрузки линз:", error);
|
||||||
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export default LensPage;
|
const filteredLenses = lenses.filter((lens) =>
|
||||||
|
Object.values(lens).some((value) =>
|
||||||
|
value?.toString().toLowerCase().includes(searchText.toLowerCase())
|
||||||
|
)
|
||||||
|
).sort((a, b) => {
|
||||||
|
return sortOrder === "asc"
|
||||||
|
? a.preset_refraction - b.preset_refraction
|
||||||
|
: b.preset_refraction - a.preset_refraction;
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleAddLens = () => {
|
||||||
|
setSelectedLens(null);
|
||||||
|
setIsModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditLens = (lens) => {
|
||||||
|
setSelectedLens(lens);
|
||||||
|
setIsModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteLens = async (lensId) => {
|
||||||
|
if (!user || !user.token) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await deleteLens(lensId, user.token);
|
||||||
|
fetchLenses(user.token);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Ошибка удаления линзы:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleModalSubmit = async (lensData) => {
|
||||||
|
try {
|
||||||
|
if (selectedLens) {
|
||||||
|
await updateLens(selectedLens.id, lensData);
|
||||||
|
} else {
|
||||||
|
await addLens(lensData);
|
||||||
|
}
|
||||||
|
setIsModalVisible(false);
|
||||||
|
fetchLenses();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Ошибка сохранения линзы:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{padding: 20}}>
|
||||||
|
<Row gutter={[16, 16]} style={{marginBottom: 20}}>
|
||||||
|
<Col xs={24} sm={16}>
|
||||||
|
<Input
|
||||||
|
placeholder="Поиск линзы"
|
||||||
|
value={searchText}
|
||||||
|
onChange={(e) => setSearchText(e.target.value)}
|
||||||
|
style={{width: "100%"}}
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
<Col xs={24} sm={8}>
|
||||||
|
<Select
|
||||||
|
value={sortOrder}
|
||||||
|
onChange={(value) => setSortOrder(value)}
|
||||||
|
style={{width: "100%"}}
|
||||||
|
>
|
||||||
|
<Option value="asc">По возрастанию рефракции</Option>
|
||||||
|
<Option value="desc">По убыванию рефракции</Option>
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
{loading ? (
|
||||||
|
<Spin indicator={<LoadingOutlined style={{fontSize: 48}} spin/>}/>
|
||||||
|
) : (
|
||||||
|
<List
|
||||||
|
grid={{gutter: 16, xs: 1, sm: 1, md: 2, lg: 3, xl: 4}}
|
||||||
|
dataSource={filteredLenses}
|
||||||
|
renderItem={(lens) => (
|
||||||
|
<List.Item>
|
||||||
|
<LensCard
|
||||||
|
lens={lens}
|
||||||
|
handleDeleteLens={() => handleDeleteLens(lens.id)}
|
||||||
|
handleEditLens={() => handleEditLens(lens)}
|
||||||
|
/>
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
pagination={{
|
||||||
|
current,
|
||||||
|
pageSize,
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: ["5", "10", "20", "50"],
|
||||||
|
onChange: (page, newPageSize) => {
|
||||||
|
setCurrent(page);
|
||||||
|
setPageSize(newPageSize);
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<FloatButton
|
||||||
|
icon={<PlusOutlined/>}
|
||||||
|
style={{position: "fixed", bottom: 20, right: 20}}
|
||||||
|
onClick={handleAddLens}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/*<LensModal*/}
|
||||||
|
{/* visible={isModalVisible}*/}
|
||||||
|
{/* onCancel={() => setIsModalVisible(false)}*/}
|
||||||
|
{/* onSubmit={handleModalSubmit}*/}
|
||||||
|
{/* lens={selectedLens}*/}
|
||||||
|
{/*/>*/}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LensesPage;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user