сделал заготовку модального окна, а также починил переадресацию при перезагрузке стринцы
This commit is contained in:
parent
cb3860297a
commit
6c2a6e4c00
10
web-app/package-lock.json
generated
10
web-app/package-lock.json
generated
@ -13,6 +13,7 @@
|
||||
"@react-buddy/palette-antd": "^5.3.0",
|
||||
"antd": "^5.23.1",
|
||||
"axios": "^1.7.9",
|
||||
"moment": "^2.30.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
@ -4006,6 +4007,15 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
"@react-buddy/palette-antd": "^5.3.0",
|
||||
"antd": "^5.23.1",
|
||||
"axios": "^1.7.9",
|
||||
"moment": "^2.30.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
|
||||
@ -11,11 +11,11 @@ const AppRouter = () => (
|
||||
|
||||
<Route element={<PrivateRoute/>}>
|
||||
<Route element={<MainLayout/>}>
|
||||
<Route path={"/"} element={<p>1234</p>}/>
|
||||
<Route path={"/patients"} element={<PatientsPage/>}/>
|
||||
<Route path={"*"} element={<Navigate to={"/"}/>}/>
|
||||
<Route path={"/"} element={<p>1234</p>}/>
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path={"*"} element={<Navigate to={"/"}/>}/>
|
||||
</Routes>
|
||||
)
|
||||
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
import {createContext, useState, useContext, useEffect} from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import loginUser from "./api/LoginRequest.jsx";
|
||||
import {Spin} from "antd";
|
||||
|
||||
const AuthContext = createContext(undefined);
|
||||
|
||||
export const AuthProvider = ({children}) => {
|
||||
const [user, setUser] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem("access_token");
|
||||
if (token) {
|
||||
setUser({token});
|
||||
}
|
||||
setIsLoading(false);
|
||||
}, []);
|
||||
|
||||
const login = async (loginData) => {
|
||||
@ -30,6 +33,10 @@ export const AuthProvider = ({children}) => {
|
||||
setUser(null);
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <Spin/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{user, login, logout}}>
|
||||
{children}
|
||||
|
||||
128
web-app/src/components/PatientModal.jsx
Normal file
128
web-app/src/components/PatientModal.jsx
Normal file
@ -0,0 +1,128 @@
|
||||
import {useEffect} from "react";
|
||||
import {Modal, Form, Input, DatePicker} from "antd";
|
||||
import moment from "moment";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const {TextArea} = Input;
|
||||
|
||||
const PatientModal = ({visible, onCancel, onSubmit, patient}) => {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
if (patient) {
|
||||
form.setFieldsValue({
|
||||
...patient,
|
||||
birthday: patient.birthday ? moment(patient.birthday) : null,
|
||||
});
|
||||
} else {
|
||||
form.resetFields();
|
||||
}
|
||||
}, [patient, form]);
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
if (values.birthday) {
|
||||
values.birthday = values.birthday.format("YYYY-MM-DD");
|
||||
}
|
||||
onSubmit(values);
|
||||
} catch (errorInfo) {
|
||||
console.log("Validation Failed:", errorInfo);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={patient ? "Редактировать пациента" : "Добавить пациента"}
|
||||
open={visible}
|
||||
onCancel={onCancel}
|
||||
onOk={handleOk}
|
||||
okText="Сохранить"
|
||||
cancelText="Отмена"
|
||||
centered
|
||||
maskClosable={false}
|
||||
bodyStyle={{padding: 24}}
|
||||
style={{top: 20}}
|
||||
>
|
||||
<Form form={form} layout="vertical">
|
||||
<Form.Item
|
||||
name="first_name"
|
||||
label="Имя"
|
||||
rules={[{required: true, message: "Введите имя"}]}
|
||||
>
|
||||
<Input placeholder="Введите имя"/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="last_name"
|
||||
label="Фамилия"
|
||||
rules={[{required: true, message: "Введите фамилию"}]}
|
||||
>
|
||||
<Input placeholder="Введите фамилию"/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="patronymic"
|
||||
label="Отчество"
|
||||
>
|
||||
<Input placeholder="Введите отчество (необязательно)"/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="birthday"
|
||||
label="Дата рождения"
|
||||
rules={[{required: true, message: "Выберите дату рождения"}]}
|
||||
>
|
||||
<DatePicker style={{width: "100%"}} format="YYYY-MM-DD"/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="address"
|
||||
label="Адрес"
|
||||
>
|
||||
<Input placeholder="Введите адрес"/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="email"
|
||||
label="Email"
|
||||
rules={[{type: "email", message: "Введите корректный email"}]}
|
||||
>
|
||||
<Input placeholder="Введите email"/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="phone"
|
||||
label="Телефон"
|
||||
>
|
||||
<Input placeholder="Введите телефон"/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="diagnosis"
|
||||
label="Диагноз"
|
||||
>
|
||||
<TextArea rows={3} placeholder="Введите диагноз"/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="correction"
|
||||
label="Коррекция"
|
||||
>
|
||||
<TextArea rows={3} placeholder="Введите информацию о коррекции"/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
PatientModal.propTypes = {
|
||||
visible: PropTypes.bool.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
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,
|
||||
}),
|
||||
};
|
||||
|
||||
export default PatientModal;
|
||||
@ -1,9 +1,10 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Input, Select, List, FloatButton, Row, Col } from "antd";
|
||||
import { Input, Select, List, FloatButton, Row, Col, message } from "antd";
|
||||
import { PlusOutlined } from "@ant-design/icons";
|
||||
import { useAuth } from "../AuthContext.jsx";
|
||||
import getAllPatients from "../api/GetAllPatients.jsx";
|
||||
import PatientListCard from "../components/PatientListCard.jsx";
|
||||
import PatientModal from "../components/PatientModal.jsx"; // Подключаем модальное окно
|
||||
|
||||
const { Search } = Input;
|
||||
const { Option } = Select;
|
||||
@ -18,6 +19,9 @@ const PatientsPage = () => {
|
||||
const [current, setCurrent] = useState(1);
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const [selectedPatient, setSelectedPatient] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchPatients = async () => {
|
||||
if (!user || !user.token) return;
|
||||
@ -45,6 +49,36 @@ const PatientsPage = () => {
|
||||
: fullNameB.localeCompare(fullNameA);
|
||||
});
|
||||
|
||||
const handleAddPatient = () => {
|
||||
setSelectedPatient(null);
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
|
||||
const handleEditPatient = (patient) => {
|
||||
setSelectedPatient(patient);
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setIsModalVisible(false);
|
||||
};
|
||||
|
||||
const handleSubmit = (newPatient) => {
|
||||
if (selectedPatient) {
|
||||
setPatients((prevPatients) =>
|
||||
prevPatients.map((p) =>
|
||||
p.id === selectedPatient.id ? { ...p, ...newPatient } : p
|
||||
)
|
||||
);
|
||||
message.success("Пациент успешно обновлен!");
|
||||
} else {
|
||||
setPatients((prevPatients) => [...prevPatients, { id: Date.now(), ...newPatient }]);
|
||||
message.success("Пациент успешно добавлен!");
|
||||
}
|
||||
|
||||
setIsModalVisible(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ padding: 20 }}>
|
||||
<Row gutter={[16, 16]} style={{ marginBottom: 20 }}>
|
||||
@ -71,8 +105,12 @@ const PatientsPage = () => {
|
||||
grid={{ gutter: 16, column: 1 }}
|
||||
dataSource={filteredPatients}
|
||||
renderItem={(patient) => (
|
||||
<List.Item>
|
||||
<PatientListCard patient={patient} />
|
||||
<List.Item
|
||||
onClick={() => {
|
||||
handleEditPatient(patient);
|
||||
}}
|
||||
>
|
||||
<PatientListCard patient={patient}/>
|
||||
</List.Item>
|
||||
)}
|
||||
pagination={{
|
||||
@ -90,7 +128,14 @@ const PatientsPage = () => {
|
||||
<FloatButton
|
||||
icon={<PlusOutlined />}
|
||||
style={{ position: "fixed", bottom: 20, right: 20 }}
|
||||
onClick={() => console.log("Добавить пациента")}
|
||||
onClick={handleAddPatient}
|
||||
/>
|
||||
|
||||
<PatientModal
|
||||
visible={isModalVisible}
|
||||
onCancel={handleCancel}
|
||||
onSubmit={handleSubmit}
|
||||
patient={selectedPatient}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user