сделал удаление пациента и перенес дейсвтия редактирования в кнопки на карточке
This commit is contained in:
parent
defe869e3e
commit
1c53632382
@ -37,3 +37,12 @@ async def update_patient(
|
|||||||
):
|
):
|
||||||
patients_service = PatientsService(db)
|
patients_service = PatientsService(db)
|
||||||
return await patients_service.update_patient(patient_id, patient)
|
return await patients_service.update_patient(patient_id, patient)
|
||||||
|
|
||||||
|
@router.delete("/patients/{patient_id}/", response_model=bool)
|
||||||
|
async def delete_patient(
|
||||||
|
patient_id: int,
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
user=Depends(get_current_user)
|
||||||
|
):
|
||||||
|
patient_service = PatientsService(db)
|
||||||
|
return await patient_service.delete_patient(patient_id)
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import datetime
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import jwt
|
import jwt
|
||||||
|
from fastapi import HTTPException
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from app.application.users_repository import UsersRepository
|
from app.application.users_repository import UsersRepository
|
||||||
@ -21,7 +22,7 @@ class AuthService:
|
|||||||
"user_id": user.id
|
"user_id": user.id
|
||||||
}
|
}
|
||||||
|
|
||||||
return None
|
raise HTTPException(status_code=403, detail="Invalid login or password")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_access_token(data: dict) -> str:
|
def create_access_token(data: dict) -> str:
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
from fastapi import HTTPException
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from app.application.patients_repository import PatientsRepository
|
from app.application.patients_repository import PatientsRepository
|
||||||
@ -81,4 +82,12 @@ class PatientsService:
|
|||||||
correction=patient_model.correction,
|
correction=patient_model.correction,
|
||||||
)
|
)
|
||||||
|
|
||||||
return None
|
raise HTTPException(status_code=404, detail="Patient not found")
|
||||||
|
|
||||||
|
async def delete_patient(self, patient_id: int) -> Optional[bool]:
|
||||||
|
result = await self.patient_repository.delete(patient_id) is not None
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
raise HTTPException(status_code=404, detail="Patient not found")
|
||||||
|
|
||||||
|
return result
|
||||||
|
|||||||
@ -11,7 +11,7 @@ const AddPatient = async (token, patient) => {
|
|||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error.response.data.message);
|
throw new Error(error.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
19
web-app/src/api/patients/DeletePatient.jsx
Normal file
19
web-app/src/api/patients/DeletePatient.jsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import CONFIG from "../../core/Config.jsx";
|
||||||
|
|
||||||
|
|
||||||
|
const DeletePatient = async (token, patient_id) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.delete(`${CONFIG.BASE_URL}/patients/${patient_id}/`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default DeletePatient;
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import CONFIG from "../../core/Config.jsx";
|
import CONFIG from "../../core/Config.jsx";
|
||||||
|
|
||||||
|
|
||||||
const getAllPatients = async (token) => {
|
const getAllPatients = async (token) => {
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
|
|||||||
@ -1,17 +1,43 @@
|
|||||||
import { Card } from "antd";
|
import {Card, Modal} from "antd";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
|
import {DeleteOutlined, EditOutlined} from "@ant-design/icons";
|
||||||
|
|
||||||
const PatientListCard = ({ patient }) => {
|
const PatientListCard = ({patient, handleEditPatient, handleDeletePatient}) => {
|
||||||
const birthday = new Date(patient.birthday)
|
const birthday = new Date(patient.birthday)
|
||||||
|
|
||||||
|
const deletePatientConfirm = () => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "Удаление пациента",
|
||||||
|
content: `Вы уверены, что хотите удалить пациента ${patient.last_name} ${patient.first_name}?`,
|
||||||
|
okText: "Да, удалить",
|
||||||
|
cancelText: "Отмена",
|
||||||
|
onOk: () => handleDeletePatient(patient.id),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
hoverable
|
|
||||||
type="inner"
|
type="inner"
|
||||||
title={`${patient.last_name} ${patient.first_name}`}
|
title={`${patient.last_name} ${patient.first_name}`}
|
||||||
style={{ marginBottom: 16, borderRadius: 12 }}
|
actions={[
|
||||||
|
<EditOutlined
|
||||||
|
onClick={() => {
|
||||||
|
handleEditPatient(patient);
|
||||||
|
}}
|
||||||
|
key={"editPatient"}
|
||||||
|
/>,
|
||||||
|
<DeleteOutlined
|
||||||
|
onClick={deletePatientConfirm}
|
||||||
|
key={"deletePatient"}
|
||||||
|
style={{color: "red"}}
|
||||||
|
/>
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
<p><strong>📅 Дата рождения:</strong> {birthday.toLocaleString('ru-RU', {month: 'long', day: 'numeric', year: 'numeric'})}</p>
|
<p><strong>📅 Дата рождения:</strong> {birthday.toLocaleString('ru-RU', {
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric',
|
||||||
|
year: 'numeric'
|
||||||
|
})}</p>
|
||||||
{patient.phone && <p><strong>📞 Телефон:</strong> {patient.phone}</p>}
|
{patient.phone && <p><strong>📞 Телефон:</strong> {patient.phone}</p>}
|
||||||
{patient.email && <p><strong>✉️ Email:</strong> {patient.email}</p>}
|
{patient.email && <p><strong>✉️ Email:</strong> {patient.email}</p>}
|
||||||
</Card>
|
</Card>
|
||||||
@ -20,6 +46,7 @@ const PatientListCard = ({ patient }) => {
|
|||||||
|
|
||||||
PatientListCard.propTypes = {
|
PatientListCard.propTypes = {
|
||||||
patient: PropTypes.shape({
|
patient: PropTypes.shape({
|
||||||
|
id: PropTypes.number.isRequired,
|
||||||
last_name: PropTypes.string.isRequired,
|
last_name: PropTypes.string.isRequired,
|
||||||
first_name: PropTypes.string.isRequired,
|
first_name: PropTypes.string.isRequired,
|
||||||
patronymic: PropTypes.string,
|
patronymic: PropTypes.string,
|
||||||
@ -30,6 +57,8 @@ PatientListCard.propTypes = {
|
|||||||
diagnosis: PropTypes.string,
|
diagnosis: PropTypes.string,
|
||||||
correction: PropTypes.string,
|
correction: PropTypes.string,
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
handleEditPatient: PropTypes.func.isRequired,
|
||||||
|
handleDeletePatient: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PatientListCard;
|
export default PatientListCard;
|
||||||
|
|||||||
@ -26,9 +26,9 @@ const MainLayout = () => {
|
|||||||
const menuItems = [
|
const menuItems = [
|
||||||
getItem("Главная", "/", <HomeOutlined/>),
|
getItem("Главная", "/", <HomeOutlined/>),
|
||||||
getItem("Приёмы", "/appointments", <CalendarOutlined/>),
|
getItem("Приёмы", "/appointments", <CalendarOutlined/>),
|
||||||
|
getItem("Выдачи линз", "/dispensing", <DatabaseOutlined/>),
|
||||||
getItem("Линзы", "/lenses", <FolderViewOutlined/>),
|
getItem("Линзы", "/lenses", <FolderViewOutlined/>),
|
||||||
getItem("Пациенты", "/patients", <TeamOutlined/>),
|
getItem("Пациенты", "/patients", <TeamOutlined/>),
|
||||||
getItem("Выдачи линз", "/dispensing", <DatabaseOutlined/>),
|
|
||||||
getItem("Рассылки", "/mailing", <MessageOutlined/>),
|
getItem("Рассылки", "/mailing", <MessageOutlined/>),
|
||||||
{type: "divider"},
|
{type: "divider"},
|
||||||
getItem("Мой профиль", "profile", <UserOutlined/>, [
|
getItem("Мой профиль", "profile", <UserOutlined/>, [
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import {Input, Select, List, FloatButton, Row, Col, message, Spin} from "antd";
|
import {Input, Select, List, FloatButton, Row, Col, Spin} from "antd";
|
||||||
import {LoadingOutlined, PlusOutlined} from "@ant-design/icons";
|
import {LoadingOutlined, PlusOutlined} from "@ant-design/icons";
|
||||||
import {useAuth} from "../AuthContext.jsx";
|
import {useAuth} from "../AuthContext.jsx";
|
||||||
import getAllPatients from "../api/patients/GetAllPatients.jsx";
|
import getAllPatients from "../api/patients/GetAllPatients.jsx";
|
||||||
import PatientListCard from "../components/PatientListCard.jsx";
|
import PatientListCard from "../components/PatientListCard.jsx";
|
||||||
import PatientModal from "../components/PatientModal.jsx";
|
import PatientModal from "../components/PatientModal.jsx";
|
||||||
import updatePatient from "../api/patients/UpdatePatient.jsx";
|
import updatePatient from "../api/patients/UpdatePatient.jsx";
|
||||||
import addPatient from "../api/patients/AddPatient.jsx"; // Подключаем модальное окно
|
import addPatient from "../api/patients/AddPatient.jsx";
|
||||||
|
import deletePatient from "../api/patients/DeletePatient.jsx"; // Подключаем модальное окно
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
@ -65,11 +66,22 @@ const PatientsPage = () => {
|
|||||||
setIsModalVisible(true);
|
setIsModalVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDeletePatient = async (patient_id) => {
|
||||||
|
if (!user || !user.token) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await deletePatient(user.token, patient_id);
|
||||||
|
await fetchPatients();
|
||||||
|
} catch (err) {
|
||||||
|
setError(err.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
setIsModalVisible(false);
|
setIsModalVisible(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async (newPatient) => {
|
const handleModalPatientSubmit = async (newPatient) => {
|
||||||
if (selectedPatient) {
|
if (selectedPatient) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -83,7 +95,6 @@ const PatientsPage = () => {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!selectedPatient) {
|
if (!selectedPatient) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -98,6 +109,7 @@ const PatientsPage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIsModalVisible(false);
|
setIsModalVisible(false);
|
||||||
|
await fetchPatients();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (<div style={{padding: 20}}>
|
return (<div style={{padding: 20}}>
|
||||||
@ -127,22 +139,20 @@ const PatientsPage = () => {
|
|||||||
<List
|
<List
|
||||||
grid={{gutter: 16, column: 1}}
|
grid={{gutter: 16, column: 1}}
|
||||||
dataSource={filteredPatients}
|
dataSource={filteredPatients}
|
||||||
renderItem={(patient) => (<List.Item
|
renderItem={(patient) => (
|
||||||
onClick={() => {
|
<List.Item>
|
||||||
handleEditPatient(patient);
|
<PatientListCard
|
||||||
}}
|
patient={patient}
|
||||||
>
|
handleEditPatient={handleEditPatient}
|
||||||
<PatientListCard patient={patient}/>
|
handleDeletePatient={handleDeletePatient}
|
||||||
</List.Item>)}
|
/>
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
pagination={{
|
pagination={{
|
||||||
current,
|
current,
|
||||||
pageSize,
|
pageSize,
|
||||||
showSizeChanger: true,
|
showSizeChanger: true,
|
||||||
pageSizeOptions: ["5", "10", "20", "50"],
|
pageSizeOptions: ["5", "10", "20", "50"],
|
||||||
onChange: (page, newPageSize) => {
|
|
||||||
setCurrent(page);
|
|
||||||
setPageSize(newPageSize);
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -157,7 +167,7 @@ const PatientsPage = () => {
|
|||||||
<PatientModal
|
<PatientModal
|
||||||
visible={isModalVisible}
|
visible={isModalVisible}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleModalPatientSubmit}
|
||||||
patient={selectedPatient}
|
patient={selectedPatient}
|
||||||
/>
|
/>
|
||||||
</div>);
|
</div>);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user