сделал отображение линз в виде карточек и таблицы, изменил модальное подверждение на всплывающую подсказку

This commit is contained in:
Андрей Дувакин 2025-03-01 17:13:43 +05:00
parent 44d1dbb745
commit a99db338cd
5 changed files with 205 additions and 85 deletions

View File

@ -1,4 +1,4 @@
import {Card, Modal, Tooltip} from "antd";
import {Card, Popconfirm, Tooltip} from "antd";
import PropTypes from "prop-types";
import {DeleteOutlined, EditOutlined, EyeOutlined} from "@ant-design/icons";
import {useState} from "react";
@ -7,15 +7,9 @@ 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 deleteLens = () => {
handleDeleteLens(lens.id);
}
const handleViewLens = () => {
setShowModalInfo(true);
@ -29,10 +23,17 @@ const LensListCard = ({lens, handleEditLens, handleDeleteLens}) => {
<EditOutlined onClick={() => handleEditLens(lens)}/>
</Tooltip>,
<Tooltip title="Удаление линзы" key={"deleteLens"}>
<Popconfirm
title="Удаление линзы"
description="Вы уверены, что хотите удалить линзу?"
onConfirm={deleteLens}
okText="Да, удалить"
cancelText="Отмена"
>
<DeleteOutlined
onClick={deleteLensConfirm}
style={{color: "red"}}
/>
</Popconfirm>
</Tooltip>,
];

View File

@ -1,4 +1,4 @@
import {Card, Modal, Tooltip} from "antd";
import {Card, Modal, Popconfirm, Tooltip} from "antd";
import PropTypes from "prop-types";
import {DeleteOutlined, EditOutlined, EyeOutlined} from "@ant-design/icons";
import {useState} from "react";
@ -9,14 +9,9 @@ const PatientListCard = ({patient, handleEditPatient, handleDeletePatient}) => {
const birthday = new Date(patient.birthday)
const deletePatientConfirm = () => {
Modal.confirm({
title: "Удаление пациента",
content: `Вы уверены, что хотите удалить пациента ${patient.last_name} ${patient.first_name}?`,
okText: "Да, удалить",
cancelText: "Отмена",
onOk: () => handleDeletePatient(patient.id),
});
const deletePatient = () => {
handleDeletePatient(patient.id);
};
const handleViewPatient = () => {
@ -38,10 +33,17 @@ const PatientListCard = ({patient, handleEditPatient, handleDeletePatient}) => {
/>
</Tooltip>,
<Tooltip title="Удаление пациента" key={"deletePatient"}>
<Popconfirm
title="Удаление пациента"
description="Вы уверены, что хотите удалить пациента?"
onConfirm={deletePatient}
okText="Да, удалить"
cancelText="Отмена"
>
<DeleteOutlined
onClick={deletePatientConfirm}
style={{color: "red"}}
/>
</Popconfirm>
</Tooltip>,
];

View File

@ -1,34 +1,30 @@
import PropTypes from "prop-types";
import {Card, Modal, Tooltip} from "antd";
import {Card, Modal, Popconfirm, Tooltip} from "antd";
import {DeleteOutlined, EditOutlined, PlusOutlined} from "@ant-design/icons";
const SetListCard = ({set, handleEditSet, handleDeleteSet, handleAppendSet}) => {
const confirmSetDelete = () => {
Modal.confirm({
title: "Удаление набора",
content: `Вы уверены, что хотите удалить набор ${set.title}?`,
okText: "Да, удалить",
cancelText: "Отмена",
onOk: () => handleDeleteSet(set.id),
});
const deleteSet = () => {
handleDeleteSet(set.id);
};
const confirmAppendSet = () => {
Modal.confirm({
title: "Добавление набора",
content: `Вы уверены, что хотите добавить набор ${set.title} в общий список линз?`,
okText: "Да, добавить",
cancelText: "Отмена",
onOk: () => handleAppendSet(set),
});
const appendSet = () => {
handleAppendSet(set);
};
const actions = [
<Tooltip title="Добавление набора в общий список линз" key={"add"}>
<PlusOutlined
onClick={confirmAppendSet}
/>
<Popconfirm
title="Добавление набора в общий список линз"
description="Вы уверены, что хотите добавить набор в общий список линз?"
onConfirm={appendSet}
okText="Да, добавить"
cancelText="Отмена"
>
<PlusOutlined/>
</Popconfirm>
</Tooltip>,
<Tooltip title="Редактирование набора" key={"edit"}>
@ -40,10 +36,17 @@ const SetListCard = ({set, handleEditSet, handleDeleteSet, handleAppendSet}) =>
</Tooltip>,
<Tooltip title="Удаление набора" key={"delete"}>
<Popconfirm
title="Удаление набора"
description="Вы уверены, что хотите удалить набор?"
onConfirm={deleteSet}
okText="Да, удалить"
cancelText="Отмена"
>
<DeleteOutlined
style={{color: "red"}}
onClick={confirmSetDelete}
/>
</Popconfirm>
</Tooltip>,
];

View File

@ -10,7 +10,7 @@ import {
Button,
Form,
InputNumber,
Card, Grid, notification
Card, Grid, notification, Dropdown, Table, Popconfirm
} from "antd";
import {LoadingOutlined, PlusOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
import LensCard from "../components/lenses/LensListCard.jsx";
@ -32,6 +32,7 @@ const LensesPage = () => {
const [pageSize, setPageSize] = useState(10);
const [searchText, setSearchText] = useState("");
const [viewMode, setViewMode] = useState("tile");
const [lenses, setLenses] = useState([]);
const [loading, setLoading] = useState(true);
const [isModalVisible, setIsModalVisible] = useState(false);
@ -183,10 +184,137 @@ const LensesPage = () => {
setIsModalVisible(false);
};
const TileView = () => (
<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);
},
}}
/>
);
const columns = [
{
title: "Тор",
dataIndex: "tor",
key: "tor",
sorter: (a, b) => a.tor - b.tor,
},
{
title: "Диаметр",
dataIndex: "diameter",
key: "diameter",
sorter: (a, b) => a.diameter - b.diameter,
},
{
title: "Пресетная рефракция",
dataIndex: "preset_refraction",
key: "preset_refraction",
sorter: (a, b) => a.preset_refraction - b.preset_refraction,
},
{
title: "Периферия торичность",
dataIndex: "periphery_toricity",
key: "periphery_toricity",
sorter: (a, b) => a.periphery_toricity - b.periphery_toricity,
},
{
title: "FVC",
dataIndex: "fvc",
key: "fvc",
sorter: (a, b) => a.fvc - b.fvc,
},
{
title: "Trial",
dataIndex: "trial",
key: "trial",
sorter: (a, b) => a.trial - b.trial,
},
{
title: "Сторона",
dataIndex: "side",
key: "side",
filters: [
{text: "Левая", value: "левая"},
{text: "Правая", value: "правая"},
],
onFilter: (value, record) => record.side === value,
},
{
title: "Выдана",
dataIndex: "issued",
key: "issued",
render: (issued) => (issued ? "Да" : "Нет"),
filters: [
{text: "Да", value: true},
{text: "Нет", value: false},
],
onFilter: (value, record) => record.issued === value,
},
{
title: "Действия",
key: "actions",
fixed: 'right',
render: (text, record) => (
<div style={{display: "flex", gap: "8px"}}>
<Button onClick={() => handleEditLens(record)}>Изменить</Button>
<Popconfirm
title="Вы уверены, что хотите удалить линзу?"
onConfirm={() => handleDeleteLens(record.id)}
okText="Да, удалить"
cancelText="Отмена"
>
<Button danger>Удалить</Button>
</Popconfirm>
</div>
),
},
];
const TableView = () => (
<Table
columns={columns}
dataSource={filteredLenses}
scroll={{
x: "max-content"
}}
pagination={{
current,
pageSize,
showSizeChanger: true,
pageSizeOptions: ["5", "10", "20", "50"],
onChange: (page, newPageSize) => {
setCurrent(page);
setPageSize(newPageSize);
},
}}
/>
);
return (
<div style={{padding: 20}}>
<Row gutter={[16, 16]} style={{marginBottom: 20}}>
<Col xs={24} md={17} sm={14} xl={20}>
<Col xs={24} md={14} sm={10} xl={16}>
<Input
placeholder="Поиск линзы"
value={searchText}
@ -203,6 +331,16 @@ const LensesPage = () => {
Расширенный поиск
</Button>
</Col>
<Col xs={24} md={3} sm={4} xl={2}>
<Select
value={viewMode}
onChange={(value) => setViewMode(value)}
style={{width: "100%"}}
>
<Option value={"tile"}>Плиткой</Option>
<Option value={"table"}>Таблицей</Option>
</Select>
</Col>
</Row>
{showAdvancedSearch && (
@ -324,38 +462,13 @@ const LensesPage = () => {
)}
{loading ? (
<div style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100vh",
}}>
<div style={{display: "flex", justifyContent: "center", alignItems: "center", height: "100vh"}}>
<Spin indicator={<LoadingOutlined style={{fontSize: 64, color: "#1890ff"}} spin/>}/>
</div>
) : viewMode === "tile" ? (
<TileView/>
) : (
<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);
},
}}
/>
<TableView/>
)}
<FloatButton

View File

@ -123,11 +123,12 @@ const PatientsPage = () => {
if (selectedPatient) {
await editPatient(newPatient);
} else {
await addPatient(newPatient);
await addNewPatient(newPatient);
}
setIsModalVisible(false);
await fetchPatients();
} catch (error) {
console.log(error);
notification.error({
message: "Ошибка",
description: error.response?.status === 401
@ -147,7 +148,7 @@ const PatientsPage = () => {
});
};
const addPatient = async (patient) => {
const addNewPatient = async (patient) => {
await addPatient(user.token, patient);
notification.success({
message: "Пациент добавлен",