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 inroutes.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
Theroutes.js
file begins with this code: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,
});
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: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));
}
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 typehttp://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: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:
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')
})
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: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"),
});
});
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.
module.exports=router;
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.