https://d226lax1qjow5r.cloudfront.net/blog/blogposts/office-hours-reservation-using-node-js-and-the-vonage-messages-api/office-hours-reservation.png

Réservation d'heures de bureau à l'aide de Node.js et de l'API Messages de Vonage

Publié le August 16, 2022

Temps de lecture : 8 minutes

Introduction

Dans ce tutoriel, nous allons créer une application web qui permet aux étudiants de réserver des plages horaires d'heures de bureau avec leurs professeurs. Une fois la réservation d'une heure de bureau effectuée, l'étudiant recevra un message texte confirmant la réservation à l'aide de l'API Messages de Vonage.

Nous le construirons en utilisant Node.js, Express, SQLite et l'API Messages de Vonage. Le dépôt dépôt GitHub pour ce projet est également disponible.

Création d'une application Web

Page d'accueil

Nous devrons créer trois modèles HTML qui serviront de formulaire de saisie (la page d'accueil), de page d'erreur et de page de confirmation. Après avoir créé ces modèles, nous passerons au " moteur " qui pilote cette application web en Node.js. Pour commencer, nous allons créer une page d'accueil où un utilisateur pourra saisir des informations telles que son nom, son numéro de téléphone, la date de son choix, sa préférence horaire, ainsi que ses notes ou commentaires à l'aide d'un formulaire web basique. Ce formulaire sera envoyé à notre application web pour être traité.

Commençons par créer un fichier index.html qui inclut le titre de notre page, importe notre style CSS et un formulaire web de base pour recueillir des informations sur les étudiants. Il devrait ressembler à ceci :

<html>
  <head>
    <title>Office Hours Reservation</title>
    <link type="text/css" rel="stylesheet" href="/assets/indexstyles.css" />
    <link
      rel="stylesheet"
      href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"
    />
    <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
    <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
  </head>

  <body>
    <h1>Office Hours Reservation Form</h1>
    <div id="statusdiv">Current Status</div>
    <form
      id="scheduleform"
      name="scheduleform"
      method="post"
      action="/schedule"
    >
      <div id="FormInfo">
        <div class="FormTextBox">
          <div id="alignRight">Select Date for Reservation:</div>
          <div>
            <script>
              $(function () {
                $("#datepicker").datepicker();
              });
            </script>
            <input
              type="text"
              name="AppointmentDate"
              value="7/15/2022"
              id="datepicker"
            />
          </div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextBox">
          <div id="alignRight">Select Professor:</div>
          <div>
            <select name="ProfessorName">
              <option value="Professor Nimoy">Professor Nimoy</option>
              <option value="Dr. Rory">Dr. Rory</option>
              <option value="Professor Amanda">Professor Amanda</option>
              <option value="Professor Dwane">Professor Dwane</option>
              <option value="Dr. Zach">Dr. Zach</option>
            </select>
          </div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextAreaBox">
          <div>Choose Appointment Time:</div>
          <div>
            <label>
              <input type="radio" name="AppointmentTime" value="8" /> 8:00 AM
            </label>
            <label>
              <input type="radio" name="AppointmentTime" value="9" /> 9:00 AM
            </label>
            <label>
              <input type="radio" name="AppointmentTime" value="10" /> 10:00 AM
            </label>
            <label>
              <input type="radio" name="AppointmentTime" value="11" /> 11:00 AM
            </label>
          </div>
        </div>
        <!--FormTextAreaBox-->
        <div class="FormTextBox">
          <div id="alignRight">Student First Name:</div>
          <div>
            <input
              type="text"
              name="studentfirstname"
              id="studentfirstname_id"
            />
          </div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextBox">
          <div id="alignRight">Student Last Name:</div>
          <div>
            <input type="text" name="studentlastname" id="studentlastname_id" />
          </div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextBox">
          <div id="alignRight">Student Phone Number:</div>
          <div>
            <input
              type="text"
              name="studentphonenumber"
              id="studentphonenumber_id"
            />
          </div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextAreaBox">
          <div>Comments, Questions, Notes...</div>
          <div>
            <textarea
              name="studentnotes"
              id="studentnotes_id"
              style="width: 300px; height: 100px"
            >
            </textarea>
          </div>
        </div>
        <!--FormTextAreaBox-->
        <div style="text-align: center">
          <button type="submit" name="booknowbutton" class="BigButton">
            Book Now
          </button>
        </div>
      </div>
      <!--FormInfo-->
    </form>
  </body>
</html>

Dans notre exemple, nous incluons un champ de saisie pour la date de réservation, un groupe radio pour l'heure de réservation, une liste déroulante pour choisir les options du professeur, ainsi que le nom de l'étudiant, son téléphone portable et un champ de commentaires.

Enfin, créez un bouton de soumission appelé "Réserver maintenant" pour soumettre le contenu du formulaire. Nous publions ce formulaire sur notre serveur web à l'adresse suivante : URL : /postscheduleque nous aborderons plus loin dans ce tutoriel.

Page d'erreur

Si l'utilisateur saisit des données invalides ou si une erreur se produit lors du traitement de la demande, nous afficherons une page d'erreur HTML informant l'utilisateur de ce qui n'a pas fonctionné. Il s'agit d'une simple page HTML qui sera traitée par Node.js et affichera des variables spécifiques côté serveur (via Nunjucks) que nous avons définies en fonction du problème rencontré. Voici un exemple de ce à quoi ressemble notre page error.html ressemble à notre page :

<html>
  <head>
    <title>There is an Error processing your request</title>

    <link type="text/css" rel="stylesheet" href="/assets/errorstyles.css" />
    <link
      rel="stylesheet"
      href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"
    />
    <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
    <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
  </head>

  <body>
    <h1>There was an Error processing your request</h1>
    <div
      id="statusdiv"
    >
      Please correct the following:
      <ul>
        {{ErrorMessage}}
      </ul>
    </div>
    <form
      id="scheduleform"
      name="scheduleform"
      method="post"
      action="/schedule"
    >
      <div id="FormInfo">
        <div class="FormTextBox">
          <div id="alignRight">Date for Reservation:</div>
          <div class="readonlydata">{{AppointmentDate}}</div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextBox">
          <div id="alignRight">Appointment Time:</div>
          <div class="readonlydata">{{AppointmentTime}}</div>
        </div>
        <!--FormTextAreaBox-->
        <div class="FormTextBox">
          <div id="alignRight">Professor:</div>
          <div class="readonlydata">{{ProfessorName}}</div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextBox">
          <div id="alignRight">Student Name:</div>
          <div class="readonlydata">{{StudentName}}</div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextBox">
          <div id="alignRight">Student Phone Number:</div>
          <div class="readonlydata">{{StudentPhoneNumber}}</div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextAreaBox">
          <div>Comments, Questions, Notes...</div>
          <div class="readonlydata">{{StudentNotes}}</div>
        </div>
        <!--FormTextAreaBox-->
        <div id="returnButton">
          <a href="/" class="BigButton"> Return to Reservation Form </a>
        </div>
      </div>
      <!--FormInfo-->
    </form>
  </body>
</html>

Notre page d'erreur rendue ressemblera à ceci :

Error pageError page

Les variables entre doubles crochets, par exemple : {{AppointmentDate}}sont les variables côté serveur qui sont répercutées par Node.js. Nous discuterons de cette configuration plus loin dans ce tutoriel. Enfin, nous allons créer un bouton de retour. Ce bouton renverra l'utilisateur à la page d'accueil en cas d'erreur dans le traitement de sa demande de réservation.

Page de confirmation

Maintenant que nous disposons d'une réponse d'erreur, nous devons également mettre en place une réponse de confirmation. Cette page ne s'affichera que si la demande aboutit. De même, cette page affichera toutes les informations saisies par l'utilisateur. Pour commencer, nous allons créer un fichier confirmation.html et le configurer de la même manière que notre fichier error.html avec des variables côté serveur (Nunjucks). Voici un exemple de ce à quoi ressemble notre page confirmation.html ressemble à notre page :

<html>
  <head>
    <title>Your Reservation has been confirmed</title>
    <link
      type="text/css"
      rel="stylesheet"
      href="/assets/confirmationstyles.css"
    />
    <link
      rel="stylesheet"
      href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"
    />
    <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
    <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js"></script>
  </head>
  <body>
    <h1>Your Reservation has been confirmed</h1>
    <form
      id="scheduleform"
      name="scheduleform"
      method="post"
      action="/schedule"
    >
      <div id="FormInfo">
        <div class="FormTextBox">
          <div id="alignRight">Date for Reservation:</div>
          <div class="readonlydata">{{AppointmentDate}}</div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextBox">
          <div id="alignRight">Appointment Time:</div>
          <div class="readonlydata">{{AppointmentTime}}</div>
        </div>
        <!--FormTextAreaBox-->
        <div class="FormTextBox">
          <div id="alignRight">Professor:</div>
          <div class="readonlydata">{{ProfessorName}}</div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextBox">
          <div id="alignRight">Student Name:</div>
          <div class="readonlydata">{{StudentName}}</div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextBox">
          <div id="alignRight">Student Phone Number:</div>
          <div class="readonlydata">{{StudentPhoneNumber}}</div>
        </div>
        <!--FormTextBox-->
        <div class="FormTextAreaBox">
          <div>Comments, Questions, Notes...</div>
          <div class="readonlydata">{{StudentNotes}}</div>
        </div>
        <!--FormTextAreaBox-->
        <div id="returnButton">
          <a href="/" class="BigButton"> Return to Reservation Form </a>
        </div>
      </div>
      <!--FormInfo-->
    </form>
  </body>
</html>

Notre page de confirmation ressemblera à ceci :

Confirmation pageConfirmation page

Veuillez noter que nos variables côté serveur seront dérivées du formulaire soumis par l'étudiant, et qu'elles sont les suivantes : AppointmentDate, AppointmentTime, ProfessorName, StudentName, StudentPhoneNumber, et StudentNotes. Enfin, nous allons créer un bouton de retour. Ce bouton renverra l'utilisateur à la page d'accueil s'il souhaite créer une autre demande de réservation.

Backend

Option mécanique : Dotenv

Avant de commencer la mise en œuvre de notre backend, nous devons créer un fichier appelé .env. Ce fichier est extrêmement important car il stocke notre secret API et notre clé API privés. Ces variables nous permettent d'envoyer notre texte de confirmation à l'aide de l'API Messages de Vonage. Commencez par créer un nouveau fichier appelé .env et le placer dans le répertoire racine de votre projet. Maintenant, ajoutez les variables suivantes avec les informations spécifiques de votre Account Vonage : VONAGE_API_KEY, VONAGE_API_SECRET, et FROM_PHONE_NUMBER.

VONAGE_API_KEY= VONAGE_API_SECRET= FROM_PHONE_NUMBER=

Configurer Node.js en tant que serveur d'applications Web

Pour compléter notre application web, nous allons ajouter des fonctionnalités à nos fichiers HTML en utilisant Node.js, Express et SQLite. Pour plus de simplicité, nous placerons toutes les fonctionnalités de notre application web dans un seul fichier appelé index.js. Une fois Node.js installé avec succès sur notre système, nous devrons ajouter quelques paquets supplémentaires à la configuration : Express, Nunjucks, Fetch et SQLite.

npm install express 

npm install nunjucks 

npm install node-fetch 

npm install sqlite3

npm install dotenv 

npm install @vonage/server-sdk

Nous configurons notre fichier index.js pour utiliser les bibliothèques nouvellement installées et donner à notre application la possibilité de servir des pages web sur le port 3000. Le début de notre fichier index.js ressemble à ceci :

require("dotenv").config();
const express = require("express");
const nunjucks = require("nunjucks");
const webserver = express();
const Vonage = require("@vonage/server-sdk");
const SMS = require("@vonage/server-sdk/lib/Messages/SMS");

const fetch = (...args) =>
  import("node-fetch").then(({ default: fetch }) => fetch(...args));

webserver.use("/assets", express.static("assets"));

nunjucks.configure("html", { autoescape: false, express: webserver });

webserver.use(express.json());

webserver.use(express.urlencoded({ extended: true }));

// Global database
const sqlite3 = require("sqlite3").verbose();
const db = new sqlite3.Database("reservations.db");

const vonage = new Vonage({
  apiKey: process.env.VONAGE_API_KEY,
  apiSecret: process.env.VONAGE_API_SECRET,
});

webserver.listen(3000);

Quelques remarques sur le code :

  • Nous appelons le serveur web de l'instance Express

  • Nous plaçons nos trois fichiers HTML (index.html, error.html, confirmation.html) dans un sous-répertoire appelé HTML que Nunjucks est configuré pour consulter.

  • Nous avons configuré SQLite pour qu'il utilise une base de données appelée reservations.db qui se trouvera dans le répertoire racine de cette application web.

  • Nous cachons les variables Clé API et Secret API qui nous ont été données par l'API de Messages API de Vonage dans un fichier .env mais vous devrez remplacer ces variables par vos propres informations d'identification sécurisées.

Nous configurons le serveur web pour qu'il écoute les requêtes web sur le port 3000. Cela signifie que pour exécuter cette application, vous devrez spécifier ce port, par exemple http://localhost:3000.

Utiliser Node.js comme serveur d'applications Web

Nous configurons notre index.js pour qu'il fournisse trois fonctions :

  • Configurer la base de données pour stocker les demandes de réservation (reservations.db)

  • Afficher une page d'accueil où un étudiant peut soumettre une demande de rendez-vous (index.html)

  • Traiter la demande de réservation de l'étudiant envoyée à /schedule et, après examen de la demande, répondre par un succès (confirmation.html) ou une erreur (error.html)

SetUpDatabase();

DisplayHomePage();

PostSchedule();

Mise en place de la base de données

Dans ce projet, nous utilisons SQLite comme base de données pour stocker nos informations. Cependant, vous pouvez utiliser n'importe quelle base de données qui fonctionne avec Node.js.

function SetUpDatabase() {
  db.serialize(() => {
    db.run(
      "CREATE TABLE if not exists Appointments (appointmentdate text,    appointmenttime text, professorname text, studentfirstname text, studentlastname text, studentphonenumber text, studentnotes text)"
    );
  });
}

Quelques remarques sur cette fonction :

  • Cette opération permet de vérifier si une table de rendez-vous existe dans la base de données ; si la table n'existe pas, elle est créée. reservations.db Si la table n'existe pas, elle la créera.

  • En fonction du système de base de données que vous décidez d'utiliser avec Node.js, vous devrez modifier la date et l'heure du rendez-vous pour qu'elles soient compatibles avec les fonctions de date de ce moteur.

Mise en place de la page d'accueil

Notre fonction DisplayHomePage() se contente d'écouter la requête à la racine du répertoire ('/') et de rendre notre fichier index.html qui se trouve dans le répertoire HTML. Vous vous souviendrez que nous avons déjà configuré le fichier index.html comme étant le formulaire de réservation des heures de bureau.

function DisplayHomePage() {
  // Displaying Homepage after reading an HTML file locally

  webserver.get("/", function (req, res) {
    res.render("index.html");
  });
}

Configuration de la fonction Post Schedule

PostSchedule() est le cheval de bataille de notre application web. Ce processus écoutera le gestionnaire /schedule et effectuera un contrôle d'erreur de base des données saisies par l'utilisateur. Si les données de soumission passent notre processus rudimentaire de vérification des erreurs, nous enregistrerons ces informations dans notre table de rendez-vous dans la base de données reservations.db de la base de données. Nous encapsulons ensuite ces informations dans un objet JSON que nous envoyons à l'API Messages de Vonage pour l'envoi d'un message de confirmation.

function PostSchedule() {
  // POST /new Route Handler
  webserver.post("/schedule", function (req, res) {
    // Student info/variables collected from HTML form

    let professorname = req.body.ProfessorName;
    let appointmentdate = req.body.AppointmentDate;
    let appointmenttime = req.body.AppointmentTime;
    let studentfirstname = req.body.studentfirstname;
    let studentlastname = req.body.studentlastname;
    let studentphonenumber = req.body.studentphonenumber;
    let studentnotes = req.body.studentnotes;

    // Text message info sent to Student
    let message =
      "Dear " +
      studentfirstname +
      " " +
      studentlastname +
      "," +
      " you have successfully booked your appointment! Here are your additional notes: " +
      studentnotes;

    let ValidationCheck = true; // Assume success, prove otherwise
    let ErrorMessage = "";

    if (appointmentdate == "") {
      ValidationCheck = false;
      ErrorMessage = ErrorMessage + "<li>Enter an appointment date</li>";
    } else if (appointmenttime == "" || !appointmenttime) {
      ValidationCheck = false;
      ErrorMessage = ErrorMessage + "<li>Enter an appointment time</li>";
    } else if (professorname == "") {
      ValidationCheck = false;
      ErrorMessage = ErrorMessage + "<li>Select a Professor</li>";
    } else if (studentfirstname == "") {
      ValidationCheck = false;
      ErrorMessage = ErrorMessage + "<li>Enter a Student first name</li>";
    } else if (studentlastname == "") {
      ValidationCheck = false;
      ErrorMessage = ErrorMessage + "<li>Enter a Student last name</li>";
    } else if (studentphonenumber == "") {
      ValidationCheck = false;
      ErrorMessage = ErrorMessage + "<li>Enter a mobile phone number</li>";
    }

    if (ValidationCheck == false) {
      res.render("error.html", {
        ProfessorName: professorname,
        StudentName: studentfirstname + " " + studentlastname,
        AppointmentDate: appointmentdate,
        AppointmentTime: appointmenttime,
        StudentNotes: studentnotes,
        StudentPhoneNumber: studentphonenumber,
        ErrorMessage: ErrorMessage,
      });
    } else {

Quelques remarques sur ce code :

  • Notre instance Express nommée serveur web est à l'écoute d'un message envoyé à /schedule et ne s'exécute que si cette condition est remplie

  • Nous avons créé les variables Node.js suivantes pour les paires nom/valeur correspondantes du formulaire de demande HTML :

professorname = req.body.ProfessorName
  appointmentdate = req.body.AppointmentDate
  appointmenttime = req.body.AppointmentTime
  studentfirstname = req.body.studentfirstname
  studentlastname = req.body.studentlastname
  studentphonenumber = req.body.studentphonenumber
  studentnotes = req.body.studentnotes
  • Notre variable booléenne ValidationCheck teste la présence de données sous forme de chaîne vide et prend la valeur false en cas d'échec. Vous souhaiterez effectuer des contrôles d'erreur supplémentaires pour d'autres scénarios de données erronées, tels que des dates et heures de rendez-vous non valides

  • Si une erreur est rencontrée, nous rendons la page error.html qui inclut la définition de la variable Nunjucks {{ErrorMessage}} avec une description du problème

  • En cas de ValidationCheck (en retournant : true), nous continuerons à ajouter les données du rendez-vous à la table des rendez-vous et à envoyer le texte de confirmation à l'aide de l'API de messagerie de Vonage.

Une fois la validation d'entrée réussie, nous encapsulons maintenant le message dans un objet JSON que nous enverrons à Vonage. Nous avons créé l'instance de la classe client Vonage, l'avons initialisée avec la clé et le secret API de Vonage que vous avez précédemment ajoutés à votre fichier .env, et les variables nécessaires sont le numéro de téléphone, le numéro de téléphone du message, le texte du message, ainsi que notre clé et notre secret API.

else {

    vonage.messages.send(
      new SMS(message, studentphonenumber, process.env.FROM_PHONE_NUMBER),
      (err, data) => {
        if (err) {
          console.error(err);
        } else {
          console.log(data.message_uuid);
        }
      }
    );

    // Build SQL string --> insert string to add record to appointments table
    let sqlstring =
      "INSERT INTO Appointments (appointmentdate, appointmenttime, professorname, studentfirstname, studentlastname, studentphonenumber, studentnotes) " +
      "VALUES (?, ?, ?, ?, ?, ?, ?)";

    // Execute SQL string into database (Using paramaterized queries to prevent SQL injection)
    db.run(
      sqlstring,
      appointmentdate,
      appointmenttime,
      professorname,
      studentfirstname,
      studentlastname,
      studentphonenumber,
      studentnotes
    );
    
    // For testing purposes query all records in appointments table and display to console
    // The last record shown should be the record we just inserted
    db.each(
      "SELECT appointmentdate, appointmenttime, professorname, studentfirstname, studentlastname info FROM Appointments",
      (err, row) => {
        console.log(
          row.appointmentdate +
            ": " +
            row.appointmenttime +
            ":" +
            row.professorname
        );
      }
    );

    res.render("confirmation.html", {
      ProfessorName: professorname,
      StudentName: studentfirstname + " " + studentlastname,
      AppointmentDate: appointmentdate,
      AppointmentTime: appointmenttime + ":00 AM",
      StudentNotes: studentnotes,
      StudentPhoneNumber: studentphonenumber,
    });
}

Nous construisons ensuite notre instruction d'insertion SQL en utilisant les variables que nous avons définies dans le formulaire de soumission HTML, et nous exécutons cette instruction à l'aide de la fonction db.run et nous exécutons cette instruction à l'aide de la fonction Enfin, nous effectuons le rendu de la page confirmation.html pour que les variables Nunjucks soient affichées.

Prochaines étapes

La participation de la communauté est toujours la bienvenue. N'hésitez pas à nous rejoindre sur GitHub et sur Communauté Vonage Slack ou envoyez-nous un message sur sur Twitter.

Partager:

https://a.storyblok.com/f/270183/400x520/992948a3b3/zoe-mithaug.png
Zoe MithaugStagiaire en relations avec les développeurs

Zoe Mithaug est stagiaire en relations avec les développeurs chez Vonage. Elle est étudiante en quatrième année de licence à l'Université de Floride.

Elle est passionnée par la programmation, le développement de logiciels, le développement de jeux vidéo, l'animation et la conception numérique.