Creating an appointment reminder app with Node SDK

Creating the application

To function, your application needs to have the ability to validate input data and send texts. It also needs to display different pages depending on whether a user is scheduling a message or has already submitted the message details. This is where routing comes in. Routing is your application's traffic control system, guiding users along their journey by shunting them to appropriate pages. To make your project well organized, let's put your application's routing and business logic in routes.js.

The completed code to be copied into routes.js is displayed on the right panel. We'll describe the different sections of code below.

Opening code

The routes.js file begins with this code:
Copy
Copied
const express = require("express");
const router = express.Router();
const { DateTime } = require("luxon");
const sessionStorage = require("sessionstorage-for-nodejs");
const { SinchClient } = require("@sinch/sdk-core");
const dotenv = require("dotenv");
dotenv.config();

const sinchClient = new SinchClient({
  projectId: process.env.PROJECT_ID,
  keyId: process.env.KEY_ID,
  keySecret: process.env.KEY_SECRET,
  region: process.env.SMS_REGION,
});
This acts as the setup for routes.js. It loads in the environment variables, which include your Sinch credentials, from the .env file and uses them to initialise an SDK client object, called SinchClient. This is going to play a key role in your application.

The remind_patient function

Now we'll review the remind_patient function, whose job is to send the SMS:
Copy
Copied
async function remind_patient(to, message, send_at) {
  let response = await sinchClient.sms.batches.send({
    sendSMSRequestBody: {
      to: [to],
      from: process.env.FROM_NUMBER,
      body: message,
      send_at: send_at,
    },
  });
  console.log(JSON.stringify(response));
}
This function is the keystone of your application. It uses the SinchClient instance you just created to call the SDK send method. What makes this method powerful is the send_at parameter. Because the Sinch SMS REST API has message scheduling built in, it's a one-stop shop for any application that requires sending SMS messages at particular times. This reduces the amount of dependencies you need. Even better, it means you don't need your app to be running all the time!

In addition to send_at, the send method has a number of other parameters, including message expiry and delivery reports. These are available on the REST API reference.

Route paths

We're now going to review the route paths. You can think of route paths as railway tracks in a shunting yard. Each track is the URL of a particular page. By switching users onto appropriate tracks, the application can control which page they see at a given point on their user journey.

The landing page routes

The first route path redirects from the root URL. This means that users can simply type http://localhost:3000/ and they will be taken to the appointment scheduling form at http://localhost:3000/appointment. The second route path displays the message scheduling form:
Copy
Copied
router.get("/", function (req, res) {
  res.redirect("/appointment");
});

router.get("/appointment", function (req, res) {
  res.render("patient_details", { message: sessionStorage.getItem("message") });
  sessionStorage.removeItem("message");
});

The buisness logic route

The third route path contains the meat of of your application's business logic:

Copy
Copied
router.post("/appointment", async function(req, res, next){
    let appointment_datetime= DateTime.fromISO(req.body.appointment_date)
    let [hours, minutes] = req.body.appointment_time.split(":")
    appointment_datetime=appointment_datetime.set({hour: hours, minutes: minutes}).setZone('system')
    let now=DateTime.now()
    let reminder_datetime=appointment_datetime.setZone('utc').minus({hours: 2, minutes: 5})
    sessionStorage.setItem('appointment_datetime', appointment_datetime.toLocaleString(DateTime.DATETIME_MED))
    
    
    if(appointment_datetime.minus({hours: 2, minutes: 5})<now){
        req.flash('message', 'Appointment must be at least 2:05 hours from now');
        sessionStorage.setItem('message', req.flash('message'))
        res.redirect('/appointment')
        return;
    }

let country_code=process.env.COUNTRY_CODE_US;
if(process.env.SMS_REGION=='eu'){
    country_code=process.env.COUNTRY_CODE_EU
}

let to = country_code + req.body.phone;
sessionStorage.setItem('phone', req.body.phone)

    const message="Hi "+req.body.patient+", you have a Sinch Hospital appointment with Dr "+req.body.doctor+" scheduled for "+appointment_datetime.toLocaleString(DateTime.DATETIME_MED);
    console.log(message)
    sessionStorage.setItem('patient', req.body.patient);
    sessionStorage.setItem('doctor', req.body.doctor);
    remind_patient(to, message, reminder_datetime)
    res.redirect('/success')
})
This is a post method. It receives form data from the front end and sends an SMS message by calling remind_patient. Once a confirmation message is sent, the user is redirected to the success.html page. The route path also contains validation, to make sure any appointment is booked at least a couple of hours into the future. This also stops users from accidently booking an appointment in the past. The Sinch SDK requires phone numbers to have a country code, so the code checks the SMS region and adds a US/EU country code to the phone number.

The success route

Now we'll review the success route path:
Copy
Copied
router.get("/success", function (req, res) {
  res.render("success", {
    patient: sessionStorage.getItem("patient"),
    doctor: sessionStorage.getItem("doctor"),
    phone: sessionStorage.getItem("phone"),
    appointment_datetime: sessionStorage.getItem("appointment_datetime"),
  });
});
This renders the success page. It is what the previous route path redirects to when an appointment reminder is successfully submitted. It uses sessionStorage to pull information such as patient name and phone number to display a success message.

Final code

Finally you need to add the following line of code.

Copy
Copied
module.exports=router;
This makes routes.js available to your application by exporting the router. This allows it to be mounted on the application server in app.js.

Congratulations! That's the core of your application completed.



We'd love to hear from you!
Rate this content:
Still have a question?
 
Ask the community.