From 44c7f031cc5221a45ad578dee1cd342ba3561609 Mon Sep 17 00:00:00 2001 From: andrei Date: Thu, 3 Jul 2025 14:42:54 +0500 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86?= =?UTF-8?q?=D0=B0=20=D1=80=D0=B0=D1=81=D1=81=D1=8B=D0=BB=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлена страница для отправки email рассылок пациентам. --- api/app/application/patients_repository.py | 8 +- api/app/controllers/patients_router.py | 14 ++ api/app/infrastructure/patients_service.py | 7 + .../Pages/MailingPage/MailingPage.jsx | 127 ++++++++++++++++++ .../Pages/MailingPage/useMailingPage.js | 109 +++++++++++++++ 5 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 web-app/src/Components/Pages/MailingPage/MailingPage.jsx create mode 100644 web-app/src/Components/Pages/MailingPage/useMailingPage.js diff --git a/api/app/application/patients_repository.py b/api/app/application/patients_repository.py index 9b82b36..4fe61b1 100644 --- a/api/app/application/patients_repository.py +++ b/api/app/application/patients_repository.py @@ -11,7 +11,8 @@ class PatientsRepository: self.db = db async def get_all(self, skip: int = 0, limit: int = 100, search: str = None, - sort_order: Literal["asc", "desc"] = "asc", all_params: bool = False) -> Tuple[Sequence[Patient], int]: + sort_order: Literal["asc", "desc"] = "asc", all_params: bool = False) -> Tuple[ + Sequence[Patient], int]: stmt = select(Patient) if search: @@ -58,6 +59,11 @@ class PatientsRepository: return patients, total_count + async def get_width_email(self) -> Sequence[Patient]: + stmt = select(Patient).filter(Patient.email != None) + result = await self.db.execute(stmt) + return result.scalars().all() + async def get_by_id(self, patient_id: int) -> Optional[Patient]: stmt = select(Patient).filter_by(id=patient_id) result = await self.db.execute(stmt) diff --git a/api/app/controllers/patients_router.py b/api/app/controllers/patients_router.py index d4507a5..9b46dae 100644 --- a/api/app/controllers/patients_router.py +++ b/api/app/controllers/patients_router.py @@ -47,6 +47,20 @@ async def create_patient( return await patients_service.create_patient(patient) +@router.get( + '/email/', + response_model=list[PatientEntity], + summary="Get all patients with email", + description="Returns all patients with email", +) +async def get_all_patients_with_email( + db: AsyncSession = Depends(get_db), + user=Depends(get_current_user), +): + patients_service = PatientsService(db) + return await patients_service.get_patients_with_email() + + @router.put( "/{patient_id}/", response_model=PatientEntity, diff --git a/api/app/infrastructure/patients_service.py b/api/app/infrastructure/patients_service.py index 9fd8414..69ed212 100644 --- a/api/app/infrastructure/patients_service.py +++ b/api/app/infrastructure/patients_service.py @@ -24,6 +24,13 @@ class PatientsService: total_count ) + async def get_patients_with_email(self) -> list[PatientEntity]: + patients = await self.patient_repository.get_width_email() + return [ + self.model_to_entity(patient) + for patient in patients + ] + async def create_patient(self, patient: PatientEntity) -> PatientEntity: patient_model = self.entity_to_model(patient) diff --git a/web-app/src/Components/Pages/MailingPage/MailingPage.jsx b/web-app/src/Components/Pages/MailingPage/MailingPage.jsx new file mode 100644 index 0000000..84e7af2 --- /dev/null +++ b/web-app/src/Components/Pages/MailingPage/MailingPage.jsx @@ -0,0 +1,127 @@ +import { Button, Card, Input, Table, Typography, Result, Space } from "antd"; +import { MailOutlined, SearchOutlined } from "@ant-design/icons"; +import LoadingIndicator from "../../Widgets/LoadingIndicator/LoadingIndicator.jsx"; +import useMailingPage from "./useMailingPage.js"; + +const { Title, Text } = Typography; +const { TextArea } = Input; + +const MailingPage = () => { + const { + patientsWithEmail, + isLoading, + isError, + selectedPatientIds, + subject, + body, + searchQuery, + containerStyle, + cardStyle, + buttonStyle, + handleSelectPatients, + handleSubjectChange, + handleBodyChange, + handleSearchChange, + handleSendEmail, + isMobile, + } = useMailingPage(); + + if (isError) { + return ( + + ); + } + + const columns = [ + { + title: "Фамилия", + dataIndex: "last_name", + key: "last_name", + sorter: (a, b) => a.last_name.localeCompare(b.last_name), + }, + { + title: "Имя", + dataIndex: "first_name", + key: "first_name", + sorter: (a, b) => a.first_name.localeCompare(b.first_name), + }, + { + title: "Email", + dataIndex: "email", + key: "email", + }, + ]; + + return ( +
+ <MailOutlined /> Рассылки + {isLoading ? ( + + ) : ( + <> + + } + value={searchQuery} + onChange={handleSearchChange} + style={{ marginBottom: 16, width: isMobile ? "100%" : 300 }} + /> + ({ + ...patient, + key: patient.id, + }))} + pagination={{ pageSize: 10 }} + rowKey="id" + size={isMobile ? "small" : "middle"} + /> + + + +
+ Тема письма: + +
+
+ Текст письма: +