Open In App

Hospital Management System using MEAN Stack

Last Updated : 08 May, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

The Hospital Management App is an important application that ensures seamless coordination to revolutionize healthcare administration. In this article, we will be creating a Hospital Management Website using the MEAN stack – i.e. MongoDB, Express, Angular, and Node.js, with step by step process for easy understanding.

Project Preview:

Output-Preview

Final Output of Hospital Management Application

Prerequisite:

Approach for creating Backend:

  • Design MongoDB models for `Appointment`, `Doctor`, and `Patient` in separate files (`Appointment.js`, `Doctor.js`, `Patient.js`).
  • In your `server.js` file, connect to MongoDB using Mongoose.
  • Create separate routes for appointments, doctors, and patients (`appointments.js`, `doctors.js`, `patients.js`).
  • Implement CRUD (Create, Read, Update, Delete) operations for each resource.

Steps to Setup Backend with Node and Express

Step 1: Creating an express app

npm init -y

Step 2: Installing the required packages

npm install express mongoose

Folder Structure(Backend)

Backend-Folder-Structure

Backend Folder Structure

Dependencies

"dependencies": {
"cors": "^2.8.5",
"express": "^4.19.2",
"mongoose": "^8.3.0"
}

Step 3: Below is the code for the backend.

JavaScript
// server.js

const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const patientRoutes = require("./routes/patientRoutes");
const doctorRoutes = require("./routes/doctorRoutes");
const appointmentRoutes = require("./routes/appointmentRoutes");

const app = express();
const PORT = process.env.PORT || 4000;

// Middleware
app.use(cors());
app.use(express.json());

MONGO_URI = "YOUR_MONGO_URI";

// Connect to MongoDB
mongoose.connect(MONGO_URI).then(() => {
    console.log("Connected to MongoDB!");
});

// Routes
app.use("/api/patient", patientRoutes);
app.use("/api/doctor", doctorRoutes);
app.use("/api/appointment", appointmentRoutes);

// Start server
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});
JavaScript
// models/Appointment.js

const mongoose = require("mongoose");

const appointmentSchema = new mongoose.Schema({
    patient: { type: String, required: true },
    doctor: { type: String, required: true },
    appointmentDate: { type: Date, required: true },
});
const Appointment = mongoose.model("Appointment", appointmentSchema);

module.exports = Appointment;
JavaScript
// models/Doctor.js

const mongoose = require("mongoose");

const doctorSchema = new mongoose.Schema({
    name: { type: String, required: true },
    speciality: { type: String, required: true },
});
const Doctor = mongoose.model("Doctor", doctorSchema);

module.exports = Doctor;
JavaScript
// models/Patient.js

const mongoose = require("mongoose");

const patientSchema = new mongoose.Schema({
    name: { type: String, required: true },
    age: { type: String, required: true },
    gender: { type: String, required: true },
});
const Patient = mongoose.model("Patient", patientSchema);

module.exports = Patient;
JavaScript
// routes/appointmentRoutes.js

const express = require("express");
const router = express.Router();
const Appointment = require("../models/Appointment");

// Get all appointments
router.get("/get", async (req, res) => {
    try {
        const appointments = await Appointment.find();
        res.status(200).json(appointments);
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});

// Add a new appointment
router.post("/add", async (req, res) => {
    console.log(req.body);
    const appointment = new Appointment({
        patient: req.body.patient,
        doctor: req.body.doctor,
        appointmentDate: req.body.appointmentDate,
    });
    try {
        const newAppointment = await appointment.save();
        console.log(newAppointment);
        res.status(201).json(newAppointment);
    } catch (error) {
        res.status(400).json({ message: error.message });
    }
});

// Delete an appointment by ID
router.delete("/delete/:id", async (req, res) => {
    try {
        await Appointment.findByIdAndDelete(req.params.id);
        res.json({ message: "Appointment deleted" });
    } catch (error) {
        console.error("Error deleting appointment:", error);
        res.status(500).json({ message: error.message });
    }
});

// Update a appointment by ID
router.put("/update/:id", async (req, res) => {
    const appointmentId = req.params.id;
    const { patient, doctor, appointmentDate } = req.body;

    try {
        // Find the appointment by ID in the database
        const appointment = await Appointment
            .findById(appointmentId);
        if (!appointment) {
            return res.status(404)
                .json({ message: "Appointment not found" });
        }

        // Update the appointment properties
        appointment.patient = patient;
        appointment.doctor = doctor;
        appointment.appointmentDate = appointmentDate;

        // Save the updated appointment
        await appointment.save();
        console.log(appointment);

        // You can send the updated appointment details in the response
        res.json(appointment);
    } catch (error) {
        console.error("Error updating appointment details:", error);
        res.status(500).json({ message: "Internal Server Error" });
    }
});

module.exports = router;
JavaScript
// routes/doctorRoutes.js

const express = require("express");
const router = express.Router();
const Doctor = require("../models/Doctor");

// Get all doctors
router.get("/get", async (req, res) => {
    try {
        const doctors = await Doctor.find();
        res.status(200).json(doctors);
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});

// Add a new doctor
router.post("/add", async (req, res) => {
    const doctor = new Doctor({
        name: req.body.name,
        speciality: req.body.speciality,
    });
    try {
        const newDoctor = await doctor.save();
        console.log(newDoctor);
        res.status(201).json(newDoctor);
    } catch (error) {
        res.status(400).json({ message: error.message });
    }
});

// Delete a doctor by ID
router.delete("/delete/:id", async (req, res) => {
    try {
        await Doctor.findByIdAndDelete(req.params.id);
        res.json({ message: "Doctor deleted" });
    } catch (error) {
        console.error("Error deleting doctor:", error);
        res.status(500).json({ message: error.message });
    }
});

// Update a doctor by ID
router.put("/update/:id", async (req, res) => {
    const doctorId = req.params.id;
    const { name, speciality } = req.body;

    try {
        // Find the doctor by ID in the database
        const doctor = await Doctor.findById(doctorId);
        if (!doctor) {
            return res.status(404).json({ message: "Doctor not found" });
        }

        // Update the doctor properties
        doctor.name = name;
        doctor.speciality = speciality;

        // Save the updated doctor
        await doctor.save();
        console.log(doctor);

        // You can send the updated doctor details in the response
        res.json(doctor);
    } catch (error) {
        console.error("Error updating doctor details:", error);
        res.status(500).json({ message: "Internal Server Error" });
    }
});

module.exports = router;
JavaScript
// routes/patientRoutes.js

const express = require("express");
const router = express.Router();
const Patient = require("../models/Patient");

// Get all patients
router.get("/get", async (req, res) => {
    try {
        const patients = await Patient.find();
        res.status(200).json(patients);
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});

// Add a new patient
router.post("/add", async (req, res) => {
    const patient = new Patient({
        name: req.body.name,
        age: req.body.age,
        gender: req.body.gender,
    });
    try {
        const newPatient = await patient.save();
        console.log(newPatient);
        res.status(201).json(newPatient);
    } catch (error) {
        res.status(400).json({ message: error.message });
    }
});

// Delete a patient by ID
router.delete("/delete/:id", async (req, res) => {
    try {
        await Patient.findByIdAndDelete(req.params.id);
        res.json({ message: "Patient deleted" });
    } catch (error) {
        console.error("Error deleting patient:", error);
        res.status(500).json({ message: error.message });
    }
});

// Update a patient by ID
router.put("/update/:id", async (req, res) => {
    const patientId = req.params.id;
    const { name, age, gender } = req.body;

    try {
        // Find the patient by ID in the database
        const patient = await Patient.findById(patientId);
        if (!patient) {
            return res.status(404).json({ message: "Patient not found" });
        }

        // Update the patient properties
        patient.name = name;
        patient.age = age;
        patient.gender = gender;

        // Save the updated patient
        await patient.save();
        console.log(patient);

        // You can send the updated patient details in the response
        res.json(patient);
    } catch (error) {
        console.error("Error updating patient details:", error);
        res.status(500).json({ message: "Internal Server Error" });
    }
});

module.exports = router;

Step 4: Start the backend server

node server.js

Approach for Creating Frontend

  • Create components for `appointments`, `doctors`, `patients` within `src/components` using ‘ng generate component’ command.
  • Add routings to app.routing.ts file for route navigation.
  • Create a app-routing.module.ts file for adding your routes.
  • Design styles for each component to enhance the visual appeal.

Steps to Setup Frontend with Angular

Step 1: Create Angular Project:

ng new frontend

NOTE: While creating the project, choose ‘Sass (SCSS)’ when asked ‘Which stylesheet format would you like to use?’.

Step 2: Switch to the project directory.

cd frontend

Step 3: Installing the required packages:

npm install tailwindcss @tailwindcss/forms ngx-toastr

Folder Structure(Frontend)

Frontend-Folder-Structure

Frontend Folder Structure

The updated dependencies in package.json for frontend will look like:

"dependencies": {
"@angular/animations": "^17.3.0",
"@angular/common": "^17.3.0",
"@angular/compiler": "^17.3.0",
"@angular/core": "^17.3.0",
"@angular/forms": "^17.3.0",
"@angular/platform-browser": "^17.3.0",
"@angular/platform-browser-dynamic": "^17.3.0",
"@angular/router": "^17.3.0",
"@tailwindcss/forms": "^0.5.7",
"ngx-toastr": "^18.0.0",
"rxjs": "~7.8.0",
"tailwindcss": "^3.4.3",
"zone.js": "~0.14.3"
}

Step 4: Create the Tailwind Configuration file (`tailwind.config.js`) using below command:

npx tailwindcss init

Step 5: Create a Angular Service named `api` using below command.

ng generate service api

Step 6: Add app-routing as a top-level module, load and configure the router and routes inside it.

ng generate module app-routing --flat

Step 7: Update the following files.

CSS
/* styles.scss */

@tailwind base;
@tailwind components;
@tailwind utilities;

@import "ngx-toastr/toastr";

.required:after {
    content: " *";
    color: red;
}
JavaScript
// tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
    content: ["./src/**/*.{html,js}"],
    theme: {
        extend: {},
    },
    plugins: [require('@tailwindcss/forms')],
};
JavaScript
// app.config.ts

import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideToastr } from 'ngx-toastr';

export const appConfig: ApplicationConfig = {
    providers: [
        provideRouter(routes),
        provideHttpClient(),
        provideAnimations(),
        provideToastr(),
    ],
};
JavaScript
// src/app/api.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
    providedIn: 'root',
})
export class ApiService {
    constructor(private http: HttpClient) { }

    getPatients(): Observable<any> {
        return this.http.get<any>
        ('http://localhost:4000/api/patient/get');
    }

    addPatient(data: any): Observable<any> {
        return this.http.post<any> 
        ('http://localhost:4000/api/patient/add', data);
    }

    updatePatient(id: string, data: any): Observable<any> {
        return this.http.put<any>(
            'http://localhost:4000/api/patient/update/' + id,
            data
        );
    }

    deletePatient(id: string): Observable<any> {
        return this.http.delete<any>(
            'http://localhost:4000/api/patient/delete/' + id
        );
    }

    getDoctors(): Observable<any> {
        return this.http.get<any>('http://localhost:4000/api/doctor/get');
    }

    addDoctor(data: any): Observable<any> {
        return this.http.post<any>('http://localhost:4000/api/doctor/add', data);
    }

    updateDoctor(id: string, data: any): Observable<any> {
        return this.http.put<any>(
            'http://localhost:4000/api/doctor/update/' + id,
            data
        );
    }

    deleteDoctor(id: string): Observable<any> {
        return this.http.delete<any>(
            'http://localhost:4000/api/doctor/delete/' + id
        );
    }

    getAppointments(): Observable<any> {
        return this.http.get<any>
        ('http://localhost:4000/api/appointment/get');
    }

    addAppointment(data: any): Observable<any> {
        return this.http.post<any>(
            'http://localhost:4000/api/appointment/add',
            data
        );
    }

    updateAppointment(id: string, data: any): Observable<any> {
        return this.http.put<any>(
            'http://localhost:4000/api/appointment/update/' + id,
            data
        );
    }

    deleteAppointment(id: string): Observable<any> {
        return this.http.delete<any>(
            'http://localhost:4000/api/appointment/delete/' + id
        );
    }
}
JavaScript
//app-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { routes } from './app.routes';

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule],
})
export class AppRoutingModule { }

Step 8: Create a Angular Components named `appointments`, `doctors` and `patients` inside `src/components` folder using below command.

ng generate component components/appointments
ng generate component components/doctors
ng generate component components/patients

Step 9: Below is the code for frontend.

HTML
<!-- app.component.html -->

<div class="block">
    <h2 class="text-center text-3xl font-semibold
     leading-7 text-green-600 mt-2">
        GFG's Hospital Management Website
    </h2>
</div>

<div class="text-sm font-medium text-center
 text-gray-500 border-b border-gray-300">
    <ul class="flex flex-wrap -mb-px">
        <li class="me-2">
            <button class="nav-item inline-block 
            p-4 text-blue-600 border-b-2 border-blue-600
             rounded-t-lg active"
                id="nav-appointments" 
                (click)="navClick('appointments')">
                Appointments
            </button>
        </li>
        <li class="me-2">
            <button id="nav-doctors" 
            (click)="navClick('doctors')"
                class="nav-item inline-block p-4 
                border-b-2 border-transparent rounded-t-lg 
                hover:text-gray-600 hover:border-gray-300">
                Doctors
            </button>
        </li>
        <li class="me-2">
            <button id="nav-patients" 
            (click)="navClick('patients')"
                class="nav-item inline-block p-4 border-b-2
                 border-transparent rounded-t-lg hover:text-gray-600
                  hover:border-gray-300">
                Patients
            </button>
        </li>
    </ul>
</div>
<router-outlet></router-outlet>
HTML
<!-- components/appointments.component.html -->

<div class="w-full flex justify-center 
items-center h-screen overflow-y-hidden">
    <div class="flex justify-center items-start flex-1 pt-12">
      <div
        class="max-w-lg w-full h-auto p-6 bg-white
         border border-gray-200 rounded-lg shadow ml-2 mt-2"
      >
        <h2
          class="text-center text-2xl font-semibold 
          leading-7 text-blue-600 mb-2"
        >
          Add New Appointment
        </h2>
        <form class="max-w-md mx-auto">
          <div class="block mb-5">
            <label
              for="patient"
              class="block mb-2 text-sm font-medium 
              text-gray-600 required"
              >Patient</label
            >
            <select
              [(ngModel)]="patient"
              name="patient"
              id="patient"
              class="bg-gray-50 border border-gray-300 
              text-gray-900 text-sm rounded-lg focus:ring-blue-500
               focus:border-blue-500 block w-full p-2.5"
            >
              <option value="Select" selected>Select</option>
              <option *ngFor="let patient of PatientsArray">
                {{ patient.name }}, ({{ patient.age }}) - {{ patient.gender }}
              </option>
            </select>
          </div>
          <div class="block mb-5">
            <label
              for="doctor"
              class="block mb-2 text-sm font-medium text-gray-600 required"
              >Doctor</label
            >
            <select
              [(ngModel)]="doctor"
              name="doctor"
              id="doctor"
              class="bg-gray-50 border border-gray-300 text-gray-900 
              text-sm rounded-lg focus:ring-blue-500 
              focus:border-blue-500 block w-full p-2.5"
            >
              <option value="Select" selected>Select</option>
              <option *ngFor="let doctor of DoctorsArray">
                {{ doctor.name }} - {{ doctor.speciality }}
              </option>
            </select>
          </div>
          <div class="block mb-5">
            <label
              for="appointmentDate"
              class="block mb-2 text-sm font-medium
               text-gray-600 required"
              >Appointment Date</label
            >
            <input
              type="date"
              [(ngModel)]="appointmentDate"
              name="appointmentDate"
              id="appointmentDate"
              class="bg-gray-50 border border-gray-300 
              text-gray-900 text-sm rounded-lg focus:ring-blue-500
               focus:border-blue-500 block w-full p-2.5"
              required
            />
          </div>
          <div class="block">
            <button
              *ngIf="!isEditing"
              type="submit"
              class="w-full block text-white bg-blue-700 hover:bg-blue-800
               focus:ring-4 focus:ring-blue-300 font-medium 
               rounded-lg text-sm px-5 py-2.5 me-2"
              (click)="onAddClick()"
            >
              Add
            </button>
            <button
              *ngIf="isEditing"
              type="submit"
              class="w-full block text-white bg-blue-700
               hover:bg-blue-800 focus:ring-4 focus:ring-blue-300
                font-medium rounded-lg text-sm px-5 py-2.5 me-2"
              (click)="onUpdateClick()"
            >
              Update
            </button>
          </div>
        </form>
      </div>
      <div class="flex-none mx-4"></div>
      <div class="flex-none w-96">
        <h2
          class="text-center text-2xl font-semibold
           leading-7 text-blue-600 my-2"
        >
          Appointments ({{ AppointmentsArray.length }})
        </h2>
        <div class="h-screen overflow-y-auto">
          <div *ngFor="let appointment of AppointmentsArray">
            <div class="h-auto my-2">
              <div
                class="bg-white border border-gray-200 rounded-lg
                 shadow md:max-w-xl hover:bg-gray-100"
              >
                <div class="flex flex-col items-center md:flex-row">
                  <div class="flex flex-col justify-between p-4 leading-normal">
                    <p class="font-normal text-gray-700">
                      <b>Patient:</b> {{ appointment.patient }}
                    </p>
                    <p class="font-normal text-gray-700">
                      <b>Doctor:</b> {{ appointment.doctor }}
                    </p>
                    <p class="font-normal text-gray-700">
                      <b>Date:</b>
                      {{ appointment.appointmentDate | date : "fullDate" }}
                    </p>
                  </div>
                </div>
                <div class="flex items-center justify-center gap-x-3 mb-2">
                  <button
                    type="button"
                    class="rounded-md bg-yellow-500 px-5 py-2 text-sm 
                    font-semibold text-white shadow-sm hover:bg-yellow-400 
                    focus-visible:outline focus-visible:outline-2 
                    focus-visible:outline-offset-2 focus-visible:outline-yellow-600"
                    (click)="onEditAppointment(appointment._id)"
                  >
                    Edit
                  </button>
                  <button
                    type="button"
                    class="rounded-md bg-red-600 px-3 py-2 text-sm
                     font-semibold text-white shadow-sm hover:bg-red-500
                      focus-visible:outline focus-visible:outline-2
                       focus-visible:outline-offset-2 focus-visible:outline-red-600"
                    (click)="onDeleteAppointment(appointment._id)"
                  >
                    Delete
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  
HTML
<!--components/doctors.component.html -->

<div class="w-full flex justify-center items-center
     h-screen overflow-y-hidden">
    <div class="flex justify-center 
        items-start flex-1 pt-12">
      <div
        class="max-w-lg w-full h-auto p-6 bg-white
         border border-gray-200 rounded-lg shadow ml-2 mt-2"
      >
        <h2
          class="text-center text-2xl font-semibold 
          leading-7 text-blue-600 mb-2"
        >
          Add New Doctor
        </h2>
        <form class="max-w-md mx-auto">
          <div class="block mb-5">
            <label
              for="name"
              class="block mb-2 text-sm font-medium text-gray-600 required"
              >Name</label
            >
            <input
              type="text"
              [(ngModel)]="name"
              name="name"
              id="name"
              class="bg-gray-50 border border-gray-300 text-gray-900
               text-sm rounded-lg focus:ring-blue-500 
               focus:border-blue-500 block w-full p-2.5"
              placeholder="Doctor's Name"
              required
            />
          </div>
          <div class="block mb-5">
            <label
              for="speciality"
              class="block mb-2 text-sm font-medium text-gray-600 required"
              >Speciality</label
            >
            <select
              [(ngModel)]="speciality"
              name="speciality"
              id="speciality"
              class="bg-gray-50 border border-gray-300 
              text-gray-900 text-sm rounded-lg focus:ring-blue-500
               focus:border-blue-500 block w-full p-2.5"
            >
              <option value="Select" selected>Select</option>
              <option value="Anesthesiologist">Anesthesiologist</option>
              <option value="Cardiologist">Cardiologist</option>
              <option value="Dermatologist">Dermatologist</option>
              <option value="Gastroenterologist">Gastroenterologist</option>
              <option value="Neurologist">Neurologist</option>
              <option value="Ophthalmologist">Ophthalmologist</option>
            </select>
          </div>
          <div class="block">
            <button
              *ngIf="!isEditing"
              type="submit"
              class="w-full block text-white bg-blue-700 hover:bg-blue-800
               focus:ring-4 focus:ring-blue-300 
               font-medium rounded-lg text-sm px-5 py-2.5 me-2"
              (click)="onAddClick()"
            >
              Add
            </button>
            <button
              *ngIf="isEditing"
              type="submit"
              class="w-full block text-white bg-blue-700 hover:bg-blue-800
               focus:ring-4 focus:ring-blue-300 font-medium
                rounded-lg text-sm px-5 py-2.5 me-2"
              (click)="onUpdateClick()"
            >
              Update
            </button>
          </div>
        </form>
      </div>
      <div class="flex-none mx-4"></div>
      <div class="flex-none w-96">
        <h2
          class="text-center text-2xl font-semibold
           leading-7 text-blue-600 my-2"
        >
          Doctors ({{ DoctorsArray.length }})
        </h2>
        <div class="h-screen overflow-y-auto">
          <div *ngFor="let doctor of DoctorsArray">
            <div class="h-auto my-2">
              <div
                class="bg-white border border-gray-200 rounded-lg
                 shadow md:max-w-xl hover:bg-gray-100"
              >
                <div class="flex flex-col items-center md:flex-row">
                  <div class="mx-2">
                    <svg width="60" height="60" viewBox="0 0 122.47 122.88">
                      <title>Doctor</title>
                      <path
                        d="M84.58,103.47a4.09,4.09,0,1,1-4.08,4.09,
                        4.08,4.08,0,0,1,4.08-4.09Zm3.61-60.62a3.89,
                        3.89,0,0,1,2.2,1.48c1.08,1.39,1.38,3.64,1.08,
                        6a15.16,15.16,0,0,1-2.21,6.2c-1.31,2-3,3.29-5,
                        3.16-.14,6.51-3.33,9.5-7.49,13.41l-1.59,
                        1.51-.54.51.13.09a14.67,14.67,0,0,1-1.58,
                        1.1,17.71,17.71,0,0,1-4.61,2.47,20.48,20.48,
                        0,0,1-6.84,1.12,21.4,21.4,0,0,1-7.11-1.1l-1-.36a16.18,
                        16.18,0,0,1-3.74-1.66l-.5-.31a21.59,21.59,0,0,1-2.26,
                        4.77L62.65,92.05,77.23,79.9A22.93,22.93,0,0,1,75,75.38c6.43,
                        4.57,7.82,14.11,7.61,21.81,0,1-.06,1.26-.08,
                        1.59a8.91,8.91,0,0,0-4.36,15,8.49,8.49,0,0,0,
                        11.77.7,8.9,8.9,0,0,0,3.42-7,7.94,7.94,0,0,
                        0-1.08-4c-1.5-2.6-3.13-3.36-5.62-4.6-.17-.09,
                        0-.47,0-1.53a47.43,47.43,0,0,0-1.46-14.08,21,
                        21,0,0,0,3.4,1.41c8.9,2.1,19.84,3,23.76,5.2a16,
                        16,0,0,1,5,4.26c3.47,4.58,3.76,17.76,5,23.36-.31,
                        3.28-2.16,5.16-5.82,5.44H5.82C2.17,122.6.31,120.71,
                        0,117.44c1.26-5.6,1.56-18.79,5-23.36a15.58,15.58,0,
                        0,1,5.05-4.26c5.57-3.1,19.22-3.94,28.3-6.46a33.06,
                        33.06,0,0,0-1.58,8c-1,.77-3.64,1.67-4.47,2.66a38.55,
                        38.55,0,0,0-3.86,5.53,2,2,0,0,0-.27,1c0,
                        .28.29.57.17.81l-.19.37c-2.6,5-4.29,10.61-3.49,
                        13A3.64,3.64,0,0,0,27.3,117a12.43,12.43,0,0,0,
                        3.15.41c.31,0,.63,0,.94,0a3.07,3.07,0,0,0,.52.39,
                        4.12,4.12,0,0,0,.67.32,2.58,2.58,0,0,0,.91.17A2.51,
                        2.51,0,0,0,36,115.75a2.54,2.54,0,0,0-.23-1,2.58,2.58,
                        0,0,0-2.38-1.61c-.92,0-2.23.46-2.23,1.38v0l0,.06-.64,
                        0a9.17,9.17,0,0,1-2.33-.28c-.45-.12-.71-.29-.77-.48-.58-1.68,
                        1-6.33,3.29-10.83l.29-.55a2,2,0,0,0,1-.88,34,34,0,0,
                        1,3.41-4.92,7.09,7.09,0,0,1,3.38-1.72H39a10.53,10.53,
                        0,0,1,1.72,1.55,30.64,30.64,0,0,1,3.6,5c.23.41.79.5,1,
                        .89,2.65,4.28,4.14,9.19,3.78,11.06-.08.44-.44.7-1,
                        .88a10.49,10.49,0,0,1-2.62.37,1.74,1.74,0,0,
                        0-.1-.19v0c0-.92-1.32-1.35-2.24-1.38a2.58,2.58,
                        0,0,0-2.38,1.61,2.71,2.71,0,0,0-.23,1,2.51,2.51,0,0,
                        0,2.51,2.51,2.63,2.63,0,0,0,.92-.17,4,4,0,0,0,.66-.32,
                        3.27,3.27,0,0,0,.36-.25h.36A12.22,12.22,0,0,0,49,117a3.88,
                        3.88,0,0,0,2.9-3.05c.44-2.44-1.33-7.82-3.94-12.7a2,2,0,0,
                        0,.16-.81,2.13,2.13,0,0,0-.28-1,36,36,0,0,
                        0-4.1-5.7c-.83-.93-2.66-1.2-2.85-2.44-.5-3.23.9-7.23,
                        3-10.71a15.15,15.15,0,0,0,1.46-2.19l.32-.44a8.32,8.32,
                        0,0,1,3.41-2.08q-.73-.55-1.47-1.2L46.07,
                        73.3l-.1-.09c-4-3.48-7.41-6.43-8-13.56-2.78-.24-4
                        .75-2.88-5.72-6a15.2,15.2,0,0,1-.65-5.14,7.82,7.82,
                        0,0,1,1.51-4.56,4.31,4.31,0,0,1,.63-.65l-.14-.09c-
                        .64-8,1.23-21.82-7.43-24.44C42.51-1.55,60.51-5.27,
                        75.6,7.13,91.28,8,98.85,30.64,88.19,42.85Zm-46-5a14,
                        14,0,0,0-.2,7.6,1.67,1.67,0,0,1-2.67,
                        1.77c-2-1.7-3.21-1.86-3.73-1.24a4.7,4.7,
                        0,0,0-.75,2.6,11.77,11.77,0,0,0,.51,4c.68,
                        2.23,2,4.06,3.58,3.6a1.51,1.51,0,0,1,.48-.08,
                        1.67,1.67,0,0,1,1.71,1.63c.17,7,3.24,9.67,7,
                        12.9l.1.08,1.6,1.4a16.87,16.87,0,0,0,5.82,3.46,
                        17.29,17.29,0,0,0,4.44.87,25,25,0,0,0,3.35-.16,23.69,
                        23.69,0,0,0,4.45-.91,15,15,0,0,0,4.91-3.23l1.
                        62-1.54c4-3.74,6.92-6.5,6.36-13.21a1.67,1.67,
                        0,0,1,2.59-1.53c1.13.75,2.25,0,3.08-1.24a11.63,
                        11.63,0,0,0,1.69-4.78,5.27,5.27,0,0,0-.41-3.52c-
                        .4-.52-1.47-.31-3.53,1.26a1.67,1.67,0,0,1-2.73-1.55c1
                        .46-8.54.73-13.82-1.14-17.34-1.63-3-4.23-4.85-7-6.
                        32-6.15,4.7-10.49,5.23-14.81,5.77-3.57.44-7.12.88-
                        11.83,4.13a11.37,11.37,0,0,0-4.47,5.58Z"
                      />
                    </svg>
                  </div>
                  <div class="flex flex-col justify-between p-4 leading-normal">
                    <h5
                      class="mb-2 text-2xl font-bold tracking-tight text-gray-900"
                    >
                      {{ doctor.name }}
                    </h5>
                    <p class="font-normal text-gray-700">
                      {{ doctor.speciality }}
                    </p>
                  </div>
                </div>
                <div class="flex items-center justify-center gap-x-3 mb-2">
                  <button
                    type="button"
                    class="rounded-md bg-yellow-500 px-5 py-2 text-sm 
                    font-semibold text-white shadow-sm hover:bg-yellow-400
                     focus-visible:outline focus-visible:outline-2 
                     focus-visible:outline-offset-2 focus-visible:outline-yellow-600"
                    (click)="onEditDoctor(doctor._id)"
                  >
                    Edit
                  </button>
                  <button
                    type="button"
                    class="rounded-md bg-red-600 px-3 py-2 text-sm 
                    font-semibold text-white shadow-sm hover:bg-red-500
                     focus-visible:outline focus-visible:outline-2 
                     focus-visible:outline-offset-2 focus-visible:outline-red-600"
                    (click)="onDeleteDoctor(doctor._id)"
                  >
                    Delete
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  
HTML
<!--components/patients.component.html -->

<div class="w-full flex justify-center items-center
 h-screen overflow-y-hidden">
  <div class="flex justify-center items-start flex-1 pt-12">
    <div
      class="max-w-lg w-full h-auto p-6 bg-white border
       border-gray-200 rounded-lg shadow ml-2 mt-2"
    >
      <h2
        class="text-center text-2xl font-semibold
         leading-7 text-blue-600 mb-2"
      >
        Add New Patient
      </h2>
      <form class="max-w-md mx-auto">
        <div class="block mb-5">
          <label
            for="name"
            class="block mb-2 text-sm font-medium
             text-gray-600 required"
            >Name</label
          >
          <input
            type="text"
            [(ngModel)]="name"
            name="name"
            id="name"
            class="bg-gray-50 border border-gray-300 
            text-gray-900 text-sm rounded-lg focus:ring-blue-500 
            focus:border-blue-500 block w-full p-2.5"
            placeholder="Patient's Name"
            required
          />
        </div>
        <div class="block mb-5">
          <label
            for="age"
            class="block mb-2 text-sm font-medium 
            text-gray-600 required"
            >Age</label
          >
          <input
            type="number"
            [(ngModel)]="age"
            name="age"
            id="age"
            class="bg-gray-50 border border-gray-300
             text-gray-900 text-sm rounded-lg focus:ring-blue-500
              focus:border-blue-500 block w-full p-2.5"
            placeholder="Patient's Age"
            required
          />
        </div>
        <div class="block mb-5">
          <label
            for="gender"
            class="block mb-2 text-sm font-medium text-gray-600 required"
            >Gender</label
          >
          <select
            [(ngModel)]="gender"
            name="gender"
            id="gender"
            class="bg-gray-50 border border-gray-300 text-gray-900
             text-sm rounded-lg focus:ring-blue-500
              focus:border-blue-500 block w-full p-2.5"
          >
            <option value="Select" selected>Select</option>
            <option value="Male">Male</option>
            <option value="Female">Female</option>
            <option value="Other">Other</option>
            <option value="Prefer not to say">Prefer not to say</option>
          </select>
        </div>
        <div class="block">
          <button
            *ngIf="!isEditing"
            type="submit"
            class="w-full block text-white bg-blue-700
             hover:bg-blue-800 focus:ring-4 focus:ring-blue-300
              font-medium rounded-lg text-sm px-5 py-2.5 me-2"
            (click)="onAddClick()"
          >
            Add
          </button>
          <button
            *ngIf="isEditing"
            type="submit"
            class="w-full block text-white bg-blue-700 
            hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 
            font-medium rounded-lg text-sm px-5 py-2.5 me-2"
            (click)="onUpdateClick()"
          >
            Update
          </button>
        </div>
      </form>
    </div>
    <div class="flex-none mx-4"></div>
    <div class="flex-none w-96">
      <h2
        class="text-center text-2xl font-semibold 
        leading-7 text-blue-600 my-2"
      >
        Patients ({{ PatientsArray.length }})
      </h2>
      <div class="h-screen overflow-y-auto">
        <div *ngFor="let patient of PatientsArray">
          <div class="h-auto my-2">
            <div
              class="bg-white border border-gray-200 
              rounded-lg shadow md:max-w-xl hover:bg-gray-100"
            >
              <div class="flex flex-col items-center md:flex-row">
                <div class="flex flex-col justify-between p-4 leading-normal">
                  <p class="font-normal text-gray-700 text-lg">
                    Name: {{ patient.name }}
                  </p>

                  <p class="font-normal text-gray-700 text-lg">
                    Age: {{ patient.age }}
                  </p>
                  <p class="font-normal text-gray-700 text-lg">
                    Gender: {{ patient.gender }}
                  </p>
                </div>
              </div>
              <div class="flex items-center justify-center gap-x-3 mb-2">
                <button
                  type="button"
                  class="rounded-md bg-yellow-500 px-5 py-2 
                  text-sm font-semibold text-white shadow-sm 
                  hover:bg-yellow-400 focus-visible:outline 
                  focus-visible:outline-2 focus-visible:outline-offset-2
                   focus-visible:outline-yellow-600"
                  (click)="onEditPatient(patient._id)"
                >
                  Edit
                </button>
                <button
                  type="button"
                  class="rounded-md bg-red-600 px-3 py-2 
                  text-sm font-semibold text-white shadow-sm 
                  hover:bg-red-500 focus-visible:outline 
                  focus-visible:outline-2 focus-visible:outline-offset-2 
                  focus-visible:outline-red-600"
                  (click)="onDeletePatient(patient._id)"
                >
                  Delete
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
JavaScript
// app.routes.ts

import { Routes } from '@angular/router';
import { AppointmentsComponent } from './components/appointments/appointments.component';
import { DoctorsComponent } from './components/doctors/doctors.component';
import { PatientsComponent } from './components/patients/patients.component';

export const routes: Routes = [
    {
        path: '',
        redirectTo: 'appointments',
        pathMatch: 'full',
    },
    {
        path: 'appointments',
        component: AppointmentsComponent,
    },
    {
        path: 'doctors',
        component: DoctorsComponent,
    },
    {
        path: 'patients',
        component: PatientsComponent,
    },
];
JavaScript
// app.config.ts

import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideToastr } from 'ngx-toastr';

export const appConfig: ApplicationConfig = {
    providers: [
        provideRouter(routes),
        provideHttpClient(),
        provideAnimations(),
        provideToastr(),
    ],
};
JavaScript
// app.component.ts

import { Component } from '@angular/core';
import { RouterOutlet, Router } from '@angular/router';

@Component({
    selector: 'app-root',
    standalone: true,
    imports: [RouterOutlet],
    templateUrl: './app.component.html',
    styleUrl: './app.component.css',
})
export class AppComponent {
    constructor(private router: Router) { }

    navClick(divId: string): void {
        const navItems = document
            .getElementsByClassName('nav-item');
        for (let i = 0; i < navItems.length; i++) {
            if (navItems[i].id === 'nav-' + divId) {
                navItems[i].className =
                    'nav-item inline-block p-4 text-blue-600
                     border-b-2 border-blue-600 rounded-t-lg active';
            } else {
                navItems[i].className =
                    'nav-item inline-block p-4 border-b-2 
                    border-transparent rounded-t-lg 
                    hover:text-gray-600 hover:border-gray-300';
            }
        }
        this.router.navigate(['/' + divId]);
    }
}
JavaScript
// components/appointments.component.ts

import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';
import { ApiService } from 'src/app/api.service';

@Component({
    selector: 'app-appointments',
    standalone: true,
    imports: [CommonModule, FormsModule],
    templateUrl: './appointments.component.html',
    styleUrl: './appointments.component.css',
})
export class AppointmentsComponent {
    patient: string = 'Select';
    doctor: string = 'Select';
    appointmentDate: string = '';
    isEditing: boolean = false;
    editAppointmentId: string = '';
    DoctorsArray: any[] = [];
    PatientsArray: any[] = [];
    AppointmentsArray: any[] = [];

    constructor(private apiService: ApiService, 
        private toastr: ToastrService) { }

    ngOnInit(): void {
        this.apiService.getPatients().subscribe((res) => {
            this.PatientsArray = res;
        });
        this.apiService.getDoctors().subscribe((res) => {
            this.DoctorsArray = res;
        });
        this.apiService.getAppointments().subscribe((res) => {
            this.AppointmentsArray = res;
        });
    }

    clear(): void {
        this.patient = 'Select';
        this.doctor = 'Select';
        this.appointmentDate = '';
    }

    onEditAppointment(id: string): void {
        const index = this.AppointmentsArray.findIndex(
            (appointment) => appointment._id === id
        );
        const appointment = this.AppointmentsArray[index];
        this.patient = appointment['patient'];
        this.doctor = appointment['doctor'];
        this.appointmentDate = new Date
            (appointment['appointmentDate']).toISOString().slice(0, 10);
        this.isEditing = true;
        this.editAppointmentId = id;
    }

    onDeleteAppointment(id: string): void {
        this.apiService.deleteAppointment(id).subscribe((res) => {
            this.AppointmentsArray = this.AppointmentsArray.filter(
                (appointment) => appointment._id !== id
            );
            this.toastr.success('Appointment deleted successfully!', 'Success!');
        });
    }

    onAddClick(): void {
        const data = {
            patient: this.patient,
            doctor: this.doctor,
            appointmentDate: this.appointmentDate,
        };

        this.apiService.addAppointment(data).subscribe((res) => {
            this.AppointmentsArray.push(res);
            this.clear();
            this.toastr.success('New Appointment added successfully', 'Success!');
        });
    }

    onUpdateClick(): void {
        const data = {
            patient: this.patient,
            doctor: this.doctor,
            appointmentDate: this.appointmentDate,
        };

        this.apiService
            .updateAppointment(this.editAppointmentId, data)
            .subscribe((res) => {
                this.AppointmentsArray = this.AppointmentsArray.filter(
                    (appointment) => appointment._id !== this.editAppointmentId
                );
                this.AppointmentsArray.push(res);
                this.editAppointmentId = '';
                this.isEditing = false;
                this.toastr.success(
                    'Appointment details updated successfully',
                    'Success!'
                );
                this.clear();
            });
    }
}
JavaScript
//components/doctors.component.ts

import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';
import { ApiService } from 'src/app/api.service';

@Component({
    selector: 'app-doctors',
    standalone: true,
    imports: [CommonModule, FormsModule],
    templateUrl: './doctors.component.html',
    styleUrl: './doctors.component.css',
})
export class DoctorsComponent implements OnInit {
    name: string = '';
    speciality: string = 'Select';
    isEditing: boolean = false;
    editDoctorId: string = '';
    DoctorsArray: any[] = [];

    constructor(private apiService: ApiService, 
        private toastr: ToastrService) { }

    ngOnInit(): void {
        this.apiService.getDoctors().subscribe((res) => {
            this.DoctorsArray = res;
        });
    }

    clear(): void {
        this.name = '';
        this.speciality = 'Select';
    }

    onEditDoctor(id: string): void {
        const index = this.DoctorsArray
        .findIndex((doctor) => doctor._id === id);
        const doctor = this.DoctorsArray[index];
        this.name = doctor['name'];
        this.speciality = doctor['speciality'];
        this.isEditing = true;
        this.editDoctorId = id;
    }

    onDeleteDoctor(id: string): void {
        this.apiService.deleteDoctor(id).subscribe((res) => {
            this.DoctorsArray = this.DoctorsArray.filter(
                (doctor) => doctor._id !== id
            );
            this.toastr.success('Doctor deleted successfully!', 'Success!');
        });
    }

    onAddClick(): void {
        const data = {
            name: this.name,
            speciality: this.speciality,
        };
        console.log(data);
        this.apiService.addDoctor(data).subscribe((res) => {
            this.DoctorsArray.push(res);
            this.clear();
            this.toastr.success('New Doctor added successfully', 'Success!');
        });
    }

    onUpdateClick(): void {
        const data = {
            name: this.name,
            speciality: this.speciality,
        };
        console.log(data);
        this.apiService.updateDoctor(this.editDoctorId, data)
            .subscribe((res) => {
            this.DoctorsArray = this.DoctorsArray.filter(
                (doctor) => doctor._id !== this.editDoctorId
            );
            this.DoctorsArray.push(res);
            this.editDoctorId = '';
            this.isEditing = false;
            this.toastr.success('Doctor details updated successfully', 'Success!');
            this.clear();
        });
    }
}
JavaScript
// components/patients.component.ts

import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';
import { ApiService } from 'src/app/api.service';

@Component({
    selector: 'app-patients',
    standalone: true,
    imports: [CommonModule, FormsModule],
    templateUrl: './patients.component.html',
    styleUrl: './patients.component.css',
})
export class PatientsComponent implements OnInit {
    name: string = '';
    age: string = '';
    gender: string = 'Select';
    isEditing: boolean = false;
    editPatientId: string = '';
    PatientsArray: any[] = [];

    constructor(private apiService: ApiService, 
        private toastr: ToastrService) { }

    ngOnInit(): void {
        this.apiService.getPatients().subscribe((res) => {
            this.PatientsArray = res;
        });
    }

    clear(): void {
        this.name = '';
        this.age = '';
        this.gender = 'Select';
    }

    onEditPatient(id: string): void {
        const index = this.PatientsArray
        .findIndex((patient) => patient._id === id);
        const patient = this.PatientsArray[index];
        this.name = patient['name'];
        this.age = patient['age'];
        this.gender = patient['gender'];
        this.isEditing = true;
        this.editPatientId = id;
    }

    onDeletePatient(id: string): void {
        this.apiService.deletePatient(id).subscribe((res) => {
            this.PatientsArray = this.PatientsArray.filter(
                (patient) => patient._id !== id
            );
            this.toastr.success('Patient deleted successfully!', 'Success!');
        });
    }

    onAddClick(): void {
        const data = {
            name: this.name,
            age: this.age,
            gender: this.gender,
        };
        this.apiService.addPatient(data).subscribe((res) => {
            this.PatientsArray.push(res);
            this.clear();
            this.toastr.success('New Patient added successfully', 'Success!');
        });
    }

    onUpdateClick(): void {
        const data = {
            name: this.name,
            age: this.age,
            gender: this.gender,
        };

        console.log(data);
        this.apiService.updatePatient(this.editPatientId, data)
        .subscribe((res) => {
            this.PatientsArray = this.PatientsArray.filter(
                (patient) => patient._id !== this.editPatientId
            );
            this.PatientsArray.push(res);
            this.editPatientId = '';
            this.isEditing = false;
            this.toastr.success('Patient details updated successfully', 'Success!');
            this.clear();
        });
    }
}

Step 10: Start the frontend angular application.

ng serve --open

Output

MongoDB Database storing the application data:

MongoDB-Preview

MongoDB Results



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads