El7a2ni
El7a2ni is a software solution for clinics, doctors, and patients alike to streamline and automate the interactions between patients and medical doctors. This encompasses everything from trying to schedule meetings with doctors, conducting on-premise or online meetings, getting prescriptions, and accessing medical history.
The need to modernize healthcare interactions gave rise to El7a2ni. Traditional approaches frequently require a lot of paperwork, which causes delays and inefficiencies. The goal of this project is to provide a seamless digital solution by streamlining and improving communication between doctors and patients.
- Website can't upload multiple files together
- The data takes time to be fetched from backend and MongoDB
- The project needs in the near future to be deployed through AWS Services or alike.
- To create a zoom video call you need to login with a specific account. This will change after zoom approves our app
*Frontend (Client-Side): React, Bootstrap, SweetAlert2
*Backend (Server-Side): Node.js, Express, MongoDB
- Clone the link of repository from github.
- install node.js
- cd to the repo location
npm install
cd backend
thennpm install
cd frontend
thennpm install
We use Postman for testing our clinic application. Follow these steps to run the tests:
- Ensure that the clinic application is running locally or on a specified server.
- Open Postman the navigate to My WorkSpace. Click on "New"
- Click on "New"
- Description: Verifies that users can successfully register for an account.
- Steps:
- Send a POST request to the /api/patient/registerPatient endpoint with valid user information.
- click on "Body", then Text , the choose JSON . Then write your data in json format
- Check that the response status is 201 (Created).
- In mongoDB , browse the collections then go to 'Patients' collection and 'Users' collection
- You will find a new document with the data you entered in postman in both collections.
- Description: Verifies that users can successfully login for an account.
- Steps:
- Send a POST request to the /api/user/login endpoint with valid user information.
- click on "Body", then Text , then choose JSON . Then write your data in json format. follow this example when writing data: { "username" : "your_username", "password" : "your_password" }
- Check that the response status is 200.
- Postman will print the following :
- the "_id" in your document.
- the "role" in your document.
- the "token" in your document.
- the "username" in your document. 5.If you wrote a wrong password , postman will print "Invalid Password"
- Use port 4000 for the backend
- You can use the same methodolgy used in the test cases examples above for testing every endpoint in the system. You may find the routes in API references section.
Important Note: Ensure that the clinic application server is running and accessible before running the tests.
The code style is enforced using eslint
and prettier
. The code style is enforced using pre-commit
hooks and pre-commit github action
.
-
ADMIN
a) can add/remove another admin b) can remove doctor/patient c) can accept/reject doctor's request to join platform d) add/update/delete health package
-
GUEST
a) submit request to join as a doctor b) upload and submit required documents upon regitration c) register as a patient
-
PATIENT
a) upload/remove document such as PDF for medical history b) filter appointments c) view/link family member d) filter a doctor by speciality/name e) view/subscribe health package status f) reschedule/cancel an appointment g) chat with doctor/patient h) view/filter/download prescription i) view upcoming/past appointments list
-
DOCTOR
a) edit/update Email,Affliation, or Hourly Rate b) view uploaded health records c) filter appointments d) view upcoming/past appointments list e) reschedule/cancel appointment f) schedule follow-up for patient g) start/end video call with patient/doctor h) add/update medice dosage i) add new health record for patient
*Frontend
-
import { useEffect, useState } from "react"; import Swal from "sweetalert2"; import HealthRecordDetails from "../components/HealthRecordDetails"; const ViewpatientHealthRecord = () =>{ const [healthRecord , setHealthRecord] = useState(null) useEffect(() => { const fetchHealthRecord = async () =>{ const response = await fetch('api/healthRecord/getHealthRecordOfPatient') if(response.ok){ const json = await response.json() console.log("patients are ",json) setHealthRecord(json) } else { const errorMessage = await response.text(); Swal.fire({ icon: 'error', title: 'Error', text: "No health record found", }); } } fetchHealthRecord() },[]) return ( <div className="container justify-content-center col-md-7 "> <h2 className="mb-4"> <hr className="linearound"></hr> Your HealthRecord <hr className="linearound"></hr> </h2> {healthRecord && <HealthRecordDetails healthRecord={healthRecord} />} </div> ); } export default ViewpatientHealthRecord;
-
import {useState,useEffect} from "react"; import PatientDetails from "../components/PatientDetails"; import Swal from 'sweetalert2'; const ViewAndRemovePatients = ()=> { const [patients, setPatients] = useState([]); const [selectedPatient,setSelectedPatient] = useState(null) console.log("in method") useEffect(() => { fetchResults(); }, []); const fetchResults = async () => { try{ const response = await fetch('api/patient/getPatients',{ method: 'GET', headers: { 'Content-Type':'application/json', }, }); if (response.ok){ const results = await response.json(); setPatients(results) console.log(patients) } else { const errorMessage = await response.text(); Swal.fire({ icon: 'error', title: 'Error', text: 'Could not fetch results. Please try again later.', }); throw new Error(errorMessage) } } catch (error){ setSelectedPatient(null) } }; const handleRemovePatient = async (patientId) => { try { const response = await fetch(`/api/patient/deletePatient/${patientId}`, { method: 'DELETE', }); if (response.ok) { fetchResults(); setSelectedPatient(null); Swal.fire({ icon: 'success', title: 'Success', text: 'The patient has been removed successfully.', }); } else { const errorMessage = await response.text(); Swal.fire({ icon: 'error', title: 'Error', text: errorMessage, }); throw new Error(errorMessage); } } catch (error) { console.error(error); } }; return ( <div className="container mt-4"> <div className="row"> <h2 className="mb-4"> <hr className="linearound"></hr> System patients <hr className="linearound"></hr> </h2> <div className="col-md-5"> <ul className="list-group"> {patients.map((patient) => ( <li key={patient._id} className="list-group-item"> <button className="btn btn-link btn-lg" onClick={() => setSelectedPatient(patient)} style={{ textDecoration: "none", color:'#1B3236' }} > {patient.name} </button> </li> ))} </ul> </div> <div className="col-md-5 mt-5"> {selectedPatient && ( <> <div style={{ marginLeft: '10px' }}> {/* Add margin to the bottom */} <PatientDetails patient={selectedPatient} /> </div> <button className="custom-btn wider-button" style={{ marginLeft: '30px', marginTop:'5px', width:'150px' }} onClick={() => handleRemovePatient(selectedPatient._id)}>Remove</button> </> )} </div> </div> </div> ); }; export default ViewAndRemovePatients
*Backend
-
const getDoctorRequests = asyncHandler(async (req, res) => { try { const DoctorRequests = await DoctorRegistrationModel.find({}).sort({createdAt: -1}) res.status(200).json(DoctorRequests) } catch (error){ res.status(400) throw new Error(error.message) } })
-
const rejectContract = asyncHandler(async (req,res) => { try { const contract = await EmploymentContract.findOne({doctor:req.user.id}); if (!contract) { res.status(404) throw new Error("Contract not found") } contract.status = "REJECTED" await contract.save() res.status(200).json(contract) } catch (error) { res.status(400) throw new Error(error.message) } })
After finishing the Installation process you need to create an .env file in the backend folder.
- Open new terminal.
cd backend
node server.js
“wait until MongoDB connected”.- Open new terminal.
cd frontend
npm start
“wait until your browser open automatically”.
Then you will be able to become one of the four primary users of our website (User, Admin, Doctor, Patient, and ). You can make an account and login to the website by using the sign up page to create an account, After that, you will be able to utilize our features, log in, and change your password.
We welcome and appreciate contributions from the community to enhance El7a2ni and make it more robust. Whether it's fixing bugs, adding new features, or improving documentation, your contributions are valuable to us.
https://www.youtube.com/@NetNinja
https://www.w3schools.com/html/default.asp
https://www.youtube.com/playlist
list=PL4cUxeGkcC9iJ_KkrkBZWZRHVwnzLIoUE
The project is licensed under the Apache License 2.0.
Zoom has video call service has been used in this
- Admin:
GET api/admin/getAdmin/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. You need to be an admin |
GET api/admin/getAlladmins
Parameter | Type | Description |
---|---|---|
None |
None |
Required. You need to be an admin |
POST api/admin/addAdmin
Parameter | Type | Description |
---|---|---|
None |
None |
Required. You need to be an admin |
DELETE api/admin/deleteAdmin
Parameter | Type | Description |
---|---|---|
id |
String |
Required. You need to be an admin |
- Doctor:
GET api/doctor/searchByNameAndOrSpeciality/:name/:speciality
Parameter | Type | Description |
---|---|---|
name |
String |
Required. You need to be an patient |
speciality |
String |
Required. You need to be a patient |
POST api/doctor/createDoctor
Parameter | Type | Description |
---|---|---|
none |
none |
Create doctor |
GET api/doctor/viewDoctor
Parameter | Type | Description |
---|---|---|
id |
string |
Required the doctor's ID |
GET api/doctor/filterBySpecialityAndDate/:speciality/:date
Parameter | Type | Description |
---|---|---|
speciality |
string |
Required Doctor speciality |
date |
date |
Required docotr name |
DELETE api/doctor/removeDoctor/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required the doctor's ID |
GET api/doctor/getDoctors
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/doctor/getDoctors
Parameter | Type | Description |
---|---|---|
none |
none |
Required. You need to be a doctor |
GET api/doctor/getSessionPrice
Parameter | Type | Description |
---|---|---|
none |
none |
Required. You need to be a patient |
POST api/doctor/getSessionPrice
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/doctor/getPatientDoctors
Parameter | Type | Description |
---|---|---|
none |
none |
Required. You need to be a patient |
GET api/doctor/getAmount
Parameter | Type | Description |
---|---|---|
none |
none |
Required. You need to be a Doctor |
GET api/doctor/searchDoctorsToChatClinic/:name/:specialty
Parameter | Type | Description |
---|---|---|
name |
string |
Doctor name |
speciality |
string |
Doctor Speciality |
GET api/doctor/searchDoctorsToChat/:name/:specialty
Parameter | Type | Description |
---|---|---|
name |
string |
Doctor name |
speciality |
string |
Doctor Speciality |
- File:
POST api/file/addSingleFile
Parameter | Type | Description |
---|---|---|
none |
none |
POST api/file/addSingleFileGuest/:username
Parameter | Type | Description |
---|---|---|
username |
String |
Guest Username |
GET api/file/getSingleFiles
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/file/getFileById/:id
Parameter | Type | Description |
---|---|---|
id |
String |
File ID |
POST api/file/addMultipleFiles
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/file/getMultipleFiles
Parameter | Type | Description |
---|---|---|
none |
none |
DELETE api/file/deleteSingleFile/:id
Parameter | Type | Description |
---|---|---|
id |
String |
File ID |
DELETE api/file/deleteAllSingleFiles
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/file/uploads/:filename
Parameter | Type | Description |
---|---|---|
filename |
String |
File Name |
- Health Package Patient:
POST api/healthPackage/subscribeToPackage
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/healthPackage/getSubscribedPackage
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/healthPackage/getSubscribedPackageStatus
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/healthPackage/getPatientPackages
Parameter | Type | Description |
---|---|---|
none |
none |
DELETE api/healthPackage/cancelSubscription/:familyMemberID
Parameter | Type | Description |
---|---|---|
id |
String |
Family Member ID |
- Health Record:
POST api/healthPackage/createHealthRecord
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/healthPackage/getHealthRecordOfPatient
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/healthPackage/getHealthRecordOfPatients
Parameter | Type | Description |
---|---|---|
none |
none |
POST api/healthPackage/AddHealthRecord/:patientid
Parameter | Type | Description |
---|---|---|
id |
String |
Patient ID |
- Patient:
GET api/patient/getPatients
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/patient/getPatient/:id
Parameter | Type | Description |
---|---|---|
id |
String |
Patient ID |
POST api/patient/registerPatient
Parameter | Type | Description |
---|---|---|
none |
none |
DELETE api/patient/deletePatient/:id
Parameter | Type | Description |
---|---|---|
id |
String |
Patient ID |
PUT api/patient/updatePatient/:id
Parameter | Type | Description |
---|---|---|
id |
String |
Patient ID |
GET api/patient/getPatientsOfADoctor
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/patient/getAmount
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/patient/getInfoHealthPatient/:id
Parameter | Type | Description |
---|---|---|
id |
String |
Patient ID |
GET api/patient/searchByName/:name
Parameter | Type | Description |
---|---|---|
name |
String |
Patient name |
GET api/patient/payForSubscription/:familyMemberID/:packageID/:paymentMethod
Parameter | Type | Description |
---|---|---|
id |
String |
Family member ID |
id |
String |
Package ID |
paymentMethod |
String |
Payment Method |
POST api/patient/subscribeToPackage/:sessionID
Parameter | Type | Description |
---|---|---|
id |
String |
Session ID |
- Prescription:
GET api/prescription/getPrescriptionsbyPatient
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/prescription/getPrescriptionbyId/:id
Parameter | Type | Description |
---|---|---|
id |
String |
Prescription ID |
POST api/prescription/addPrescription
Parameter | Type | Description |
---|---|---|
none |
none |
GET api/prescription/filterByDoctor/:doctorId
Parameter | Type | Description |
---|---|---|
id |
String |
Doctor ID |
GET api/prescription/filterByDate/:createdAt
Parameter | Type | Description |
---|---|---|
date |
date |
The date prescriptions were created at |
GET api/prescription/filterbyStatus/:status
Parameter | Type | Description |
---|---|---|
status |
String |
The status of prescriptions |
- Doctor Registration:
POST api/doctorRegistration/doctorRegistrationRequest
Parameter | Type | Description |
---|---|---|
None |
None |
Body:
- doctor (object): The doctor object containing registration details.
GET api/doctorRegistration/getDoctorRequests
Parameter | Type | Description |
---|---|---|
None |
None |
You need to be an admin |
POST api/doctorRegistration/acceptDoctorRequests/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Doctor Request ID |
DELETE api/doctorRegistration/rejectDoctorRequests/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Doctor Request ID |
- Employment Contract:
POST api/employmentContracts/createContracts
Parameter | Type | Description |
---|---|---|
none |
none |
You need to be an admin |
Body:
- employmentContract (object): The employment contract details.
GET api/employmentContracts/getContracts
Parameter | Type | Description |
---|---|---|
none |
none |
You need to be an admin |
GET api/employmentContracts/getDoctorContract
Parameter | Type | Description |
---|---|---|
none |
none |
You need to be a doctor |
PUT api/employmentContracts/acceptContract
Parameter | Type | Description |
---|---|---|
none |
none |
You need to be a doctor |
PUT api/employmentContracts/rejectContract
Parameter | Type | Description |
---|---|---|
none |
none |
You need to be a doctor |
- Chat:
POST api/chat/accessChat
Parameter | Type | Description |
---|---|---|
none |
none |
You need to be a doctor or patient |
Body:
- userId (string): ID of the requested user.
GET api/chat/fetchChats
Parameter | Type | Description |
---|---|---|
none |
none |
You need to be a doctor or patient |
POST api/chat/accesChatFromPharmacy
Parameter | Type | Description |
---|---|---|
none |
none |
Body:
- userId (string): ID of the requested user.
- pharmacistUsername (string): Username of the pharmacist requesting the chat.
- pharmacyChatId (string): ID of the chat in the pharmacy's database.
Note: This route does not use the protect middleware because it is accessed by pharmacy users.
- Health Package:
POST api/healthPackage/addPackage
Parameter | Type | Description |
---|---|---|
none |
none |
You need to be an admin |
Body:
- healthPackage (object): contains details about health package
GET api/healthPackage/getPackage/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Health Package ID |
GET api/healthPackage/getPackages
Parameter | Type | Description |
---|---|---|
none |
none |
PUT api/healthPackage/updatePackage/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Health Package ID |
Body:
- packageName (string): updated name of the package
- yearlySubscription (float): updated yearly subscription price
- doctorSessionDiscount (float): updated appointment discount
- medicineDiscount (float): updated medicine discount
- familyDiscount (float): updated health package discount for family members
DELETE api/healthPackage/deletePackage/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Health Package ID |
GET api/healthPackage/getPackagesWithDiscount
Parameter | Type | Description |
---|---|---|
none |
none |
You need to be a patient |
Description:
-
Gets all packages and adds discountedYearlySubscription attribute, but returns empty string if no discount.
-
Notification
GET api/notification/getUserNotifications
Parameter | Type | Description |
---|---|---|
none |
none |
DELETE api/notification/deleteNotificationById/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Notification ID |
- User:
POST api/user/login
Parameter | Type | Description |
---|---|---|
none |
none |
Body:
- username (string)
- password (string)
POST api/user/logout
Parameter | Type | Description |
---|---|---|
none |
none |
POST api/user/generateOTP
Parameter | Type | Description |
---|---|---|
none |
none |
Body:
- email (string): E-mail of the user that is requesting the OTP
POST api/user/resetPassword
Parameter | Type | Description |
---|---|---|
none |
none |
Body:
- email (string): E-mail of the user that is requesting the password reset.
- newPassword (string): Must contain at least one number, one capital letter and one small letter.
POST api/user/changePassword
Parameter | Type | Description |
---|---|---|
none |
none |
Body:
- currentPassword (string): Current password of the user.
- newPassword (string): Must contain at least one number, one capital letter and one small letter.
- confirmPassword (string): Must be equal to newPassword.
GET api/user/getUser
Parameter | Type | Description |
---|---|---|
none |
none |
- Appointment:
POST/api/appointment/createAppointment
Parameter | Type | Description |
---|---|---|
None | None | Required. Doctor role |
GET/api/appointment/getUpcomingPatientsOfDoctor
Parameter | Type | Description |
---|---|---|
None | None | Required. Doctor role |
GET/api/appointment/getAppointment/:patientid/:doctorid
Parameter | Type | Description |
---|---|---|
patientid |
string |
Required. patient ID |
doctorid |
string |
Required. Doctor ID |
GET/api/appointment/getAppointmentsByDateAndStatus/:appointmentDate/:status
Parameter | Type | Description |
---|---|---|
appointmentDate |
Date |
Required. appointment |
status |
String |
Required. status |
GET/api/appointment/getAppointments
Parameter | Type | Description |
---|---|---|
None | None | Required. Doctor role |
GET/api/appointment/viewAvailableAppointmentsOfDoctor/:doctorId
Parameter | Type | Description |
---|---|---|
doctorId |
String |
Required. Patient role |
PUT/api/appointment/reserveAppointment/:paymentMethod
Parameter | Type | Description |
---|---|---|
paymentMethod |
String |
Required. Patient role , paymentMethod |
POST/api/appointment/success/:sessionID
Parameter | Type | Description |
---|---|---|
sessionID |
String |
Required. Patient role ,sessionID |
GET/api/appointment/upcomingPastAppointmentsOfDoctor
Parameter | Type | Description |
---|---|---|
None | None | Required. Doctor role |
GET/api/appointment/upcomingPastAppointmentsOfPatient
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient role |
GET/api/appointment/filterAppointmentsByDateOrStatus/:date/:status
Parameter | Type | Description |
---|---|---|
date |
Date |
Required. date , patient doctor role |
status |
String |
Required. status , patient doctor role |
POST/api/appointment/scheduleFollowUp/:patientId
Parameter | Type | Description |
---|---|---|
patientId |
String |
Required. Doctor role ,patientId |
PUT/api/appointment/updateStatusToPending/:id/:whichMember
Parameter | Type | Description |
---|---|---|
id |
String |
Required. id , patient role |
whichMember |
String |
Required. whichMember , patient role |
PUT/api/appointment/updateStatusToFree/:id
Parameter | Type | Description |
---|---|---|
id |
String |
Required. id , Doctor role |
PUT/api/appointment/acceptFollowUp/:followUpId
Parameter | Type | Description |
---|---|---|
followUpId |
String |
Required. id , Doctor role |
-Family Member:
GET/api/familyMember/getFamilyMembers
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient role |
POST/api/familyMember/addFamilyMember
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient role |
POST/api/familyMember/linkFamilyMember
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient role |
POST/api/familyMember/getSubscribedPackagesForFamilyMembers
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient role |
- Message:
GET/api/message/allMessages/:chatId
Parameter | Type | Description |
---|---|---|
chatId |
String |
Required. Patient Doctor role |
POST/api/message/sendMessage
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient Doctor role |
POST/api/message/sendMessageFromPharmacy
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient Paharmacist role |
- Video Call:
POST/api/videoCall/addVideoCall
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient Doctor role |
GET/api/videoCall/getVideoCall
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient Doctor role |
DELETE/api/videoCall/deleteVideoCall
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient Doctor role |
PUT/api/videoCall/setSocketID
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient Doctor role |
PUT/api/videoCall/authZoomAPI
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient Doctor role |
POST/api/videoCall/createMeeting
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient Doctor role |
GET/api/videoCall/getMeetings
Parameter | Type | Description |
---|---|---|
None | None | Required. Patient Doctor role |