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

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 Results



Hospital Management System using MEAN Stack

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:

Final Output of Hospital Management Application

Similar Reads

Prerequisite:

AngularMongoDBExpress JSNode JSMEAN Stack...

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...

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:...