Easy Appointment Scheduler Web App Using net

Learn how to build an interactive doctor appointment scheduling web application. The system includes a public interface that patients can use to select one of the available appointment slots displayed using a JavaScript calendar component. The private doctor's interface lets them define the slots and manage appointments. The application frontend is build using HTML and vanilla JavaScript. The backend API is created using ASP.NET Core (.NET 6), Entity Framework, and SQL Server (LocalDB).

  • Download source project (Visual Studio, ASP.NET Core, Entity Framework, SQL Server) - 85.7 KB

ASP.NET Core (.NET 6) Doctor Appointment Scheduling UI

Appointment Scheduling User Interface

Patient UI

The doctor appointment scheduling project includes a special UI for patients who can see free appointment slots:

Patient UI for scheduling an appointment

Patients see a simplified calendar with a week view. On the left side, the application displays a date picker calendar that displays three months. This helps with fast navigation between the weeks. Days which have a free appointment slot use a bold font. This way, patients can quickly see what the first available day is and can choose the date and time for their appointment.

The main purpose of the patient UI is to let them choose a free appointment slot. Appointments of other patients are hidden, as well as slots from the past. The slots are read-only and can't be moved. As soon as a patient selects a slot, the color changes to orange, which indicates a "waiting" status (see more on appointment slot status below). The appointment request needs to be confirmed.

Doctor UI

Doctors use separate area to manage the appointments - create, move and edit appointment slots.

Doctor Appointment Scheduling UI

The doctor UI is more advanced - it displays all appointment slots and doctors have full control over them. They can edit the appointment details, confirm the requests sent by patients, move slots to a different time using drag and drop, create custom slots and delete them.

All appointment slots need to be defined in advance - we will discuss logic in more detail in the next section.

Essential Components

  • ASP.NET Core (.NET 6), Entity Framework and SQL Server (LocalDB) are used for the REST API. The application is written in C#.
  • DayPilot JavaScript Scheduling Library (open-source), HTML5 and vanilla JavaScript are used to create the user interface.

Although you can use DayPilot calendar components in Angular, React, and Vue, this time we will use simple JavaScript without any framework.

For an introduction to using the JavaScript calendar components from DayPilot, please see the HTML5/JavaScript Event Calendar [code.daypilot.org] tutorial.

How It Works

There are two main approaches to handling doctor appointments with a public interface.

  1. You can define working hours that show the available time. Patients can create new appointments within these working hours. This way, the application needs to apply additional rules, like appointment start and duration. The appointment database records are created when a patient requests a meeting.
  2. You can define individual slots in advance and the patients can only select one of the existing slots. No additional rules are required because the doctor has full control over the slots. The database records are created when generating the slots. When patients request a meeting, they only change the slot status.

In this project, we will use approach #2 with predefined slots.

This workflow requires that the slots are defined in advance. This application uses a semi-automatic system which lets you generate the slots for a certain range (instead of adding them one by one).

Day, Week and Month Calendar View in ASP.NET Core

The main scheduling interface is created using JavaScript calendar components from DayPilot.

It's a traditional day/week/month view that you know from Google Calendar or Outlook.

In this application, we extend the functionality of a calendar application with scheduling features:

  • The events/appointment have status which determines the slot color.
  • Slot management part that lets you create or delete slots in blocks.

ASP.NET Core Doctor Appointment Scheduler Day/Week/Month View

The frontend part of the doctor section is defined in Doctor.cshml ASP.NET Core view.

The view loads the DayPilot scheduling JavaScript library:

          <          script                              src          ="          ~/lib/daypilot/daypilot-all.min.js"          >          <          /          script          >        

And includes placeholders for the calendar views (day, week, and mont). This is where the calendar components will be displayed. When switching the views, we will hide and show the components as needed.

          <          div                              id          ="          day"          >          <          /div          >          <          div                              id          ="          week"          >          <          /div          >          <          div                              id          ="          month"          >          <          /div          >        

Now we need to initialize the calendar components. Each component has its own instance - the day and week view use the DayPilot.Calendar class, the month view uses the DayPilot.Month class.

You can see that the configuration is very simple - we rely on the defaults. However, it is necessary to add the events handlers which define the behavior.

Day view:

          const          day =          new          DayPilot.Calendar("          day", {     viewType:          "          Day",     visible:          false,     eventDeleteHandling:          "          Update",     onTimeRangeSelected: (args) => {         app.createAppointmentSlot(args);     },     onEventMoved: (args) => {         app.moveAppointmentSlot(args);     },     onEventResized: (args) => {         app.moveAppointmentSlot(args);     },     onEventDeleted: (args) => {         app.deleteAppointmentSlot(args);     },     onBeforeEventRender: (args) => {         app.renderAppointmentSlot(args);     },     onEventClick: (args) => {         app.editAppointmentSlot(args);     } }); day.init();

Week view:

          const          week =          new          DayPilot.Calendar("          week", {     viewType:          "          Week",     eventDeleteHandling:          "          Update",     onTimeRangeSelected: (args) => {         app.createAppointmentSlot(args);     },     onEventMoved: (args) => {         app.moveAppointmentSlot(args);     },     onEventResized: (args) => {         app.moveAppointmentSlot(args);     },     onEventDeleted: (args) => {         app.deleteAppointmentSlot(args);     },     onBeforeEventRender: (args) => {         app.renderAppointmentSlot(args);     },     onEventClick: (args) => {         app.editAppointmentSlot(args);     } }); week.init();

Month view:

          const          month =          new          DayPilot.Month("          month", {     visible:          false,     eventDeleteHandling:          "          Update",     eventMoveHandling:          "          Disabled",     eventResizeHandling:          "          Disabled",     cellHeight:          150,     onCellHeaderClick: args => {         nav.selectMode =          "          Day";         nav.select(args.start);     },     onEventDelete: args => {         app.deleteAppointmentSlot(args);     },     onBeforeEventRender: args => {         app.renderAppointmentSlot(args);                    const          locale = DayPilot.Locale.find(month.locale);          const          start =          new          DayPilot.Date(args.data.start).toString(locale.timePattern);          const          name = DayPilot.Util.escapeHtml(args.data.patientName ||          "          ");         args.data.html =          `          <span class='month-time'>${start}</span> ${name}`;     },     onTimeRangeSelected:          async          (args) => {          const          params = {             start: args.start.toString(),             end: args.end.toString(),             weekends:          true          };          args.control.clearSelection();          const          {data} =          await          DayPilot.Http.post("          /api/appointments/create", params);         app.loadEvents();     },     onEventClick: (args) => {         app.editAppointmentSlot(args);     } }); month.init();

In addition to the calendar views, we also add a date picker which will let doctors change the date easily:

The placeholder is an empty <div> element:

          <          div                              id          ="          nav"          >          <          /div          >        

And we need to initialize the date picker using DayPilot.Navigator class:

          const          nav =          new          DayPilot.Navigator("          nav", {     selectMode:          "          Week",     showMonths:          3,     skipMonths:          3,     onTimeRangeSelected: (args) => {         app.loadEvents(args.day);     } }); nav.init();

The app.loadEvents() method is important, as it loads the appointment slots from the server. It checks the current view type (using nav.selectMode) and loads the data.

          const          app = {          async          loadEvents(date) {          const          start = nav.visibleStart();          const          end = nav.visibleEnd();          const          {data} =          await          DayPilot.Http.get(`          /api/appointments?start=${start}&end=${end}`);          const          options = {             visible:          true,             events:          data          };          if          (date) {             options.startDate = date;         }          day.hide();         week.hide();         month.hide();          const          active = app.active();         active.update(options);          nav.update({             events:          data          });     },      };

Note that it loads the appointment data for the full date range visible in the date picker (which is three months). This way, the date picker can highlight days with appointments. This data is reused for the currently-visible calendar component (the calendar date range is always a subset of the full range visible in the date picker).

The server-side part is a standard ASP.NET Core API controller generated from the Entity Framework model classes. The controller methods are extended in some cases when we need to perform a specific action (other than a basic create, update, delete, select operation) or when extra parameters are needed.

This is how the GetAppointments() method (GET /api/appointments endpoint) looks:

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Project.Models; using Project.Service;  namespace Project.Controllers {     [Route("          api/[controller]")]     [ApiController]          public          class          AppointmentsController : ControllerBase     {          private          readonly DoctorDbContext _context;          public          AppointmentsController(DoctorDbContext context)         {             _context = context;         }                   [HttpGet]          public          async          Task<ActionResult<IEnumerable<AppointmentSlot>>>                 GetAppointments([FromQuery] DateTime start, [FromQuery] DateTime end)         {          return          await          _context.Appointments.Where(e => !((e.End <= start) ||                                                      (e.Start >= end))).ToListAsync();         }                       } }

Generate Appointment Slots

In each calendar view in the doctor's UI, you can use the "Generate" button to fill the current range with appointment slots:

Generate Appointment Slots Button

The button opens a modal dialog where you can check whether you want to generate appointment slots for weekends as well:

Generate Appointment Slots Modal Dialog

In the monthly view, you can also select an arbitrary range using drag and drop:

Generate Appointment Slots using Drag and Drop

Selecting a date range will generate slots for the specified days:

Automatically-Created Appointment Slots

It will skip times that would conflict with existing appointment slots.

The slot generation logic is implemented on the server side. The PostAppointmentSlots() method of the AppointmentController class uses the Timeline class helper to generate the slots dates. We will not go into details of the Timeline class here, but you can check the implementation in the project source code.

The PostAppointmentSlots() method also selects existing slots for the date range and checks for overlaps before creating the new slot records in the SQL Server database.

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Project.Models; using Project.Service;  namespace Project.Controllers {     [Route("          api/[controller]")]     [ApiController]          public          class          AppointmentsController : ControllerBase     {          private          readonly DoctorDbContext _context;          public          AppointmentsController(DoctorDbContext context)         {             _context = context;         }          [HttpPost("          create")]          public          async          Task<ActionResult<AppointmentSlot>>                       PostAppointmentSlots(AppointmentSlotRange range)         {          var          existing =          await          _context.Appointments.Where(e => !((e.End <= range.Start) ||                                                         (e.Start >= range.End))).ToListAsync();          var          slots = Timeline.GenerateSlots(range.Start, range.End, range.Weekends);             slots.ForEach(slot =>             {          var          overlaps = existing.Any(e => !((e.End <= slot.Start) ||                                             (e.Start >= slot.End)));          if          (overlaps)                 {          return;                 }                 _context.Appointments.Add(slot);             });          await          _context.SaveChangesAsync();          return          NoContent();         }          public          class          AppointmentSlotRange         {          public          DateTime Start { get; set; }          public          DateTime End { get; set; }          public          bool Weekends { get; set; }         }               } }

Appointment Slot Status

Each appointment slot can be marked as "Available", "Waiting", or "Confirmed":

Available:

Appointment Status: Available

Waiting for confirmation:

Appointment Status: Waiting

Confirmed:

Appointment Status: Confirmed

The slot status is stored in the Status property of the AppointmentSlot class. The API controller sends it to the client side as status field of the appointment data object.

using Microsoft.EntityFrameworkCore; using System.Text.Json.Serialization;  namespace Project.Models {          public          class          AppointmentSlot     {          public          int Id { get; set; }          public          DateTime Start { get; set; }          public          DateTime End { get; set; }          public          string? PatientName {  set; get; }          public          string? Text => PatientName;          [JsonPropertyName("          patient")]          public          string? PatientId { set; get; }          public          string Status { get; set; } =          "          free";     } }

The DayPilot JavaScript calendar component provides an onBeforeEventRender event handler that lets you customize the appointment appearance before rendering. We will use it to apply a custom color depending on the slot status:

          const          week =          new          DayPilot.Calendar("          week", {     viewType:          "          Week",     onBeforeEventRender: (args) => {          switch          (args.data.status) {          case          "          free":             args.data.backColor = app.colors.blue;             args.data.barColor = app.colors.blueDarker;             args.data.borderColor =          "          darker";             args.data.fontColor = app.colors.text;             args.data.text =          "          Available";          break;          case          "          waiting":             args.data.backColor = app.colors.orange;             args.data.barColor = app.colors.orangeDarker;             args.data.borderColor =          "          darker";             args.data.fontColor = app.colors.text;             args.data.text = args.data.patientName;          break;          case          "          confirmed":             args.data.backColor = app.colors.green;             args.data.barColor = app.colors.greenDarker;             args.data.borderColor =          "          darker";             args.data.fontColor = app.colors.text;             args.data.text = args.data.patientName;          break;         }     },      });

How to Run the ASP.NET Core Project

Everything is included:

  • The server-side dependencies (Entity Framework) are managed by NuGet. Visual Studio will usually load the NuGet dependencies automatically for you during the first build.
  • The client-side dependencies (DayPilot) are in wwwroot/lib folder.
  • The database requires SQL Server Express LocalDB instance installed. You can modify the database connection string in appsettings.json file if needed. The initial Entity Framework migrations are included (see the Migrations folder) but you need to run Update-Database in the console to apply them.

History

  • 12th January, 2022: Initial release

hoaglandtropir.blogspot.com

Source: https://www.codeproject.com/Articles/5322192/Build-a-Visual-Doctor-Appointment-Scheduling-Syste

0 Response to "Easy Appointment Scheduler Web App Using net"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel