
Construire un planificateur de rendez-vous en utilisant Node, Firebase et Vonage
Temps de lecture : 13 minutes
Introduction
Dans ce tutoriel, nous allons construire une application web de prise de rendez-vous en utilisant Node.js, Express, Firebase, et l' Vonage Messages API. Le dépôt GitHub pour ce projet est également disponible, n'hésitez pas à le cloner ici.
Configuration de Firebase
Pour commencer, créons un nouveau projet à partir de la console console Firebase.
Cliquez sur
add a new projectDonnez un nom significatif à votre projet, par exemple
vonage appointment schedulerVérifiez si vous aimez l'identifiant unique de votre projet (il est utilisé dans l'URL de votre base de données en temps réel, dans les sous-domaines de Firebase Hosting, etc. Il ne peut pas être modifié après la création du projet)
Cliquez sur le bouton pour continuer
Console view with a text field to enter project and name and edit the project id
Sélectionnez si vous souhaitez activer l'analyse. Nous ne le ferons pas dans ce tutoriel
Cliquez sur le bouton pour créer le projet
Attendre la création du projet
Project being created
Une fois que le projet est prêt, cliquez pour continuer. Vous accéderez à la vue de la console de votre projet
Définissez le type de facturation en cliquant sur l'icône de l'engrenage, puis sur Usage et facturation, ensuite sur l'onglet Détails et paramètres et modifiez le plan pour utiliser Blaze. Ce plan de paiement à l'utilisation est nécessaire lors de l'utilisation d'une API tierce.
Installer Firebase Tools CLI
Depuis votre terminal, installez les outils Firebase avec NPM si vous ne les avez pas déjà en tapant : npm install -g firebase-tools. Ensuite, tapez firebase login. Cela ouvrira une fenêtre dans votre navigateur qui vous authentifiera automatiquement (si vous êtes déjà connecté) ou vous demandera vos identifiants. Une fois que vous avez terminé, vous avez maintenant installé le CLI Firebase.
Créer et paramétrer une base de données en temps réel
Il est maintenant temps de créer l'instance de la base de données NoSQL qui contiendra les informations relatives aux créneaux de rendez-vous. Notre application comprendra une vue où l'utilisateur pourra prendre ou annuler des rendez-vous. Lorsque la personne qui interagit avec la vue choisit une date et une heure de rendez-vous, ce créneau sera ajouté ou supprimé de la base de données Firebase RealTime.
Dans le menu de la console Firebase, cliquez sur "Realtime Database" (base de données en temps réel) sous "Build" (construction).
Button to create the database
Cliquez sur "Créer une base de données"
Sélectionnez l'emplacement de la base de données en temps réel où vos données seront stockées et cliquez sur
nextSélectionnez si vous souhaitez utiliser la base de données en mode verrouillée ou en mode test. Pour cet exemple, j'utilise le mode test.
Cliquez sur
enable
Database created
Importer le fichier JSON de la base de données
Importons une base de données d'exemple qui contient déjà quelques emplacements attribués et à partir de laquelle vous pourrez ajouter et supprimer de futurs emplacements. Vous pouvez créer un fichier appelé myAppointments.json contenant le JSON de l'extrait ci-dessous, puis importer ce fichier depuis la console.
myAppointments.json
{
"myAppointments": {
"0": {
"date": "2021-06-01T09:00",
"userId": "1234abcd"
},
"new_activity_7kh3a3a3z": {
"date": "2023-06-01T08:50",
"userId": "_7kh3a3a3z"
},
"new_activity_etxen95x3": {
"date": "2021-06-01T08:40",
"userId": "_etxen95x3"
}
}
}
Import Database
Ajouter les règles de la base de données
Les règles de base de données en temps réel de Firebase déterminent qui peut accéder à votre base de données, comment vos index sont construits et comment vos données sont structurées.
Dans la console Firebase, sur la vue de la base de données en temps réel, vous pouvez voir "Règles", cliquez sur cet onglet. Vous serez dirigé vers un écran qui vous permettra d'éditer vos règles.
Copiez et collez les règles de l'extrait de code ci-dessous dans votre console afin de définir la collection
myAppointmentspour qu'elle soit indexée par le champdatechamp.Cliquez sur
Publish
{
"rules": {
".read": "now < 1643842800000", // 2022-2-3
".write": "now < 1643842800000", // 2022-2-3
"myAppointments": {
".indexOn": ["date"]
}
}
}
Edit Firebase Database Rules
Créer la structure du projet
À la fin de ce tutoriel, voici à peu près à quoi ressemblera la structure de votre projet. Dans les étapes suivantes, nous allons créer les fichiers qui vont construire le contenu, l'apparence, les fonctionnalités et gérer les services que nous allons utiliser.
Project Structure
Mise en place
Créez le dossier du projet et
cddans celui-ci :mkdir appointment-scheduler && cd appointment-schedulerInitialiser NPM :
npm init. Cette commande vous invite à ajouter des informations sur le projetInstaller les dépendances :
npm install @vonage/server-sdk dotenv uuid express firebase-admin firebase-functionsType
firebase init. Puisque nous avons déjà créé un projet dans le tableau de bord, vous pouvez sélectionnerUse an existing projectce qui vous invitera à choisir le projet souhaité. Vous pouvez voir mon exemple avec l'identifiant de mon projetvonage-appointment-schedulerci-dessous. J'ai également choisi d'utiliser laRealtime Databasefonctionnalité
Créer le contenu HTML
Saviez-vous que l'élément de saisie HTML dispose de nombreuses options de type pour la sélection de la date et de l'heure ? Par exemple, nous avons : date, datetime-local, time. Pour ce tutoriel, nous utiliserons <input type="datetime-local">. Cette approche n'est peut-être pas aussi robuste que l'utilisation de la bibliothèque de dates et d'heures, car il peut y avoir des incohérences, mais elle fonctionne pour les besoins de ce tutoriel. L'utilisateur pourra réserver des créneaux horaires toutes les 5 minutes se terminant par 0 ou 5, par exemple 18:00 est réservable mais 18:01 ne l'est pas.
Créez le fichier
public/index.htmlqui contient le contenu de la vue permettant de sélectionner un nouveau rendez-vous ou de l'annuler en ajoutant l'extrait de code suivant
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Appointment Scheduler</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="styles/styles.css" />
</head>
<body>
<main>
<h1>Appointment Scheduler</h1>
<!-- datepicker from html. Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local -->
<form action="/appointment" method="POST">
<div>
<label for="slot">Choose your slot: </label>
<input
id="slot"
type="datetime-local"
name="slotdate"
min="2021-06-01T08:30"
max="2023-10-30T16:30"
step="300"
required
/>
<span class="validity"></span>
</div>
<div>
<label for="phonenumber">Your phone number:</label>
<input type="tel" id="phonenumber" name="phonenumber" required />
<span class="validity"></span>
</div>
<div>
<input type="submit" value="Book slot!" />
</div>
</form>
<form action="/cancelAppointment" method="POST">
<div>
<input type="text" name="code" placeholder="code" />
<input type="submit" value="Remove slot!" />
</div>
</form>
</main>
</body>
</html>
Ajouter un style CSS
Pour cette application web de démonstration, nous ajouterons quelques éléments de style pour centrer le contenu sur la page et afficher un ✖ rouge si la saisie n'est pas valide et un ✓ si elle l'est.
Créer le
public/styles.cssfichierCollez le code CSS ci-dessous
body {
margin: auto;
width: 50%;
padding: 10px;
}
div {
margin-bottom: 10px;
display: flex;
align-items: center;
}
label {
display: inline-block;
width: 300px;
}
input:invalid+span:after {
content: '✖';
color: red;
padding-left: 5px;
}
input:valid+span:after {
content: '✓';
color: green;
padding-left: 5px;
} Créer le fichier des variables d'environnement
Créez le formulaire
.envet l'alimenter avec les informations suivantes
Les
FIREBASE_DATABASE_URLse trouve dans la console FirebaseLes
VONAGE_API_KEYet leVONAGE_API_SECRETpeuvent être trouvés dans le tableau de bord VonageLe message
VONAGE_FROM_NUMBERcontient le numéro, le nom ou la marque qui apparaîtra comme l'expéditeur du messageLe
VONAGE_TO_NUMBERest le numéro qui recevra les SMS
Créer le fichier JavaScriptserver.js
Nous allons créer l'élément server.js pour indiquer à Express comment traiter les requêtes postées par l'interface utilisateur. Je vais vous montrer pas à pas comment nous allons le construire. Vous pouvez trouver le fichier serveur complet ici.
Notre application web utilisera express et lira les fichiers statiques que nous avons précédemment créés dans le dossier public dans le dossier
Pour ajouter les dépendances et les fichiers d'importation, ajoutez l'extrait de code ci-dessous à votre fichier
script/server.js
// script/server.js
require('dotenv').config();
const express = require('express');
const app = require('express')();
const port = 3000; //setting the port to listen to as 3000
const admin = require('firebase-admin');
const Vonage = require('@vonage/server-sdk');
const SMS = require('@vonage/server-sdk/lib/Messages/SMS';
const { v4: uuidv4 } = require('uuid');
app.use(express.static('public'));
app.use(express.json());
app.use(express.urlencoded({ extended: true })); Ajouter le Service Account
Un compte de service Firebase peut être utilisé pour authentifier diverses fonctionnalités de Firebase ; pour notre projet, nous utiliserons le SDK Admin Firebase pour accéder à l'URL de notre base de données.
Dans la console Firebase, cliquez sur l'engrenage et sélectionnez l'onglet Compte de service
Cliquez sur le bouton pour
generate keyAjoutez le fichier généré à la racine de votre projet et renommez-le en
serviceAccountKey.jsonCopiez et collez l'extrait de configuration Admin SDK dans votre projet, comme vous pouvez le voir dans l'étape suivante de ce tutoriel, pour initialiser Firebase. Nous utilisons
${process.env.FIREBASE_DATABASE_URLpour lire l'URL du fichier.envmais il s'agit de la même URL de base de données que celle trouvée dans la configuration du SDK d'administration de Firebase.
Admin SDK configuration
Initialiser Firebase
Nous utilisons initializeApp pour créer et initialiser une instance d'application Firebase qui utilisera l'instance de base de données Firebase /myAppointments instance de base de données Firebase que nous avons précédemment créée et alimentée à partir de la console Firebase.
Ajoutez l'extrait de code ci-dessous à votre
server.jspour initialiser Firebase.
const serviceAccount = require('../serviceAccountKey.json');
// Initializes firebase
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: `${process.env.FIREBASE_DATABASE_URL}`,
});
// A Reference represents a specific location in your Database and can be
// used for reading or writing data to that Database location.
ref = admin.database().ref('/myAppointments'); Initialiser l'objet API Vonage
Nous créons l'instance de la classe client Vonage, en l'initialisant avec la clé et le secret de l'API Vonage que vous avez précédemment ajoutés à votre fichier .env fichier
Ajoutez l'extrait de code ci-dessous à votre
server.jspour ajouter Vonage.
const vonage = new Vonage({
apiKey: process.env.VONAGE_API_KEY,
apiSecret: process.env.VONAGE_API_SECRET,
}); Création de la fonction getDateTime()
Le type d'entrée HTML datetime-local est formaté comme suit YYYY-MM-DDTh:mm. Nous allons donc écrire une fonction pour séparer la date de l'heure en la séparant par le caractère T. Par exemple, dans l'exemple 2018-06-12T19:30nous aurions 2018-06-12 pour la date et 19:30 pour l'heure.
Ajoutez l'extrait de code ci-dessous à votre
server.jspour ajouter la fonctiongetDateTime()fonction
const getDateTime = (slot) => {
return slot.split('T');
};
Créer le/appointment point final
Il est temps de créer le point de terminaison /appointment pour gérer les requêtes POST pour la création d'un rendez-vous. Ce point de terminaison vérifiera si le créneau est disponible, ajoutera le créneau à la base de données Firebase et, enfin, enverra un SMS de confirmation au téléphone de l'utilisateur à l'aide de l'API Messages de Vonage.
Ajoutez l'extrait de code ci-dessous à votre
server.jspour créer le point de terminaison/appointmentpoint final.
app.post('/appointment', async (request, response) => {
let phonenumber = request.body.phonenumber;
let slot = request.body.slotdate;
let [date, time] = getDateTime(slot);
// Checks if a slot is available
checkIfAvailable = async (slot) => {};
// Adds to Database
addToDatabase = () => {};
// Sends an SMS back to the user's phone using the Vonage Messages API
sendSMStoUser = async (code) => {};
});
Vous avez peut-être remarqué qu'une grande partie des fonctionnalités du gestionnaire de requêtes n'a pas encore été implémentée, nous allons donc développer les stubs pour les fonctionnalités requises.
Vérifier la disponibilité des créneaux
Cette fonction valide la disponibilité d'un créneau en vérifiant s'il existe déjà dans la base de données. Nous interrogeons ref.orderByChild('date'). Les requêtes sont autorisées à commander une clé à la fois. Nous avons préalablement défini notre index via l'option .indexOn sur les règles Firebase pour une meilleure performance. Ensuite, nous utilisons .once('value') pour écouter exactement un événement de la valeur, puis il s'arrête d'écouter.
Ajoutez l'extrait de code ci-dessous à votre
server.jspour créer lacheckIfAvailable()fonction
// Checks if a slot is available
checkIfAvailable = async (slot) => {
let snapshot = await ref.orderByChild('date').once('value');
let available = true;
snapshot.forEach((data) => {
let dataval = data.val();
for (let key in dataval) {
let datapoint = dataval[key];
if (slot === datapoint) {
available = false;
}
}
});
return available;
};
Ajouter le créneau à la base de données
La fonction suivante addToDatabase() ajoute le créneau et un code à la base de données Firebase. Ce code est nécessaire pour annuler le rendez-vous.
// Adds the slot to the database
addToDatabase = () => {
let code = uuidv4();
ref.child(code).set({
date: slot,
userId: code,
});
return code;
};
Envoyer un SMS avec les informations relatives au rendez-vous
Enfin, une fois le créneau réservé, un SMS de confirmation est envoyé à l'utilisateur avec le message suivant Meeting booked at ${time} on date: ${date}. Please save this code: ${code} in case you'd like to cancel your appointment. comme vous pouvez le voir dans la fonction sendSMStoUser().
Ajoutez l'extrait de code ci-dessous à votre
server.jspour créer lasendSMStoUser()fonction
// Sends an SMS back to the user's phone using the Vonage Messages API
sendSMStoUser = async (code) => {
const to = phonenumber;
const text = `Meeting booked at ${time} on date: ${date}. Please save this code: ${code} in case you'd like to cancel your appointment.`;
const result = await new Promise((resolve, reject) => {
vonage.messages.send(
new SMS(text, process.env.VONAGE_TO_NUMBER, "Vonage"),
(err, data) => {
if (err) {
console.error(err);
} else {
console.log(data.message_uuid);
}
}
);
});
};
Finaliser la logique d'entreprise
Le morceau de code ci-dessous est chargé d'appeler les fonctions d'aide créées précédemment. Si le créneau est disponible, l'utilisateur verra son créneau ajouté à la base de données et le SMS lui sera renvoyé. Dans le cas contraire, il lui sera demandé de choisir un autre créneau horaire.
let available = await checkIfAvailable(slot);
if (available) {
let code = addToDatabase();
await sendSMStoUser(code);
response.send(`This slot is available, booking it for you now: ${slot}`);
} else {
// Sends user error
response.send(
`Sorry, you'll need to choose a different slot.${slot} is already busy.`
);
} Annuler le rendez-vous/cancelAppointment
Créons le point de terminaison /cancelAppointment qui gère les requêtes POST pour l'annulation d'un rendez-vous à partir de la base de données en utilisant un code fourni par l'utilisateur qu'il a reçu lors de la prise de rendez-vous.
app.post('/cancelAppointment', async (request, response) => {
let code = request.body.code;
// Removes slot from the database
removeSlotFromDB = (code) => {
ref.child(code).remove();
};
removeSlotFromDB(code);
response.send(`This slot has been removed.`);
});
Écouter le port
Enfin, l'application écoutera sur le port spécifié ; si elle est exécutée localement, elle sera accessible sur https://localhost:${port}. Dans cette URL, vous pouvez interagir avec l'interface utilisateur de cette application de démonstration et vérifier les emplacements ajoutés/supprimés sur la page web de la console Firebase.
app.listen(port, () => {
console.log(`I run on port ${port}`);
});
Testez-le
Dans votre fichier
package.jsonajoutez le script de démarrage"start": "node script/server.js"juste en dessous de"test": "echo \"Error: no test specified\" && exit 1",. Il devrait ressembler à ceci :
Installer toutes les dépendances
npm installLancer la commande NPM pour exécuter le projet
npm run startNaviguez jusqu'à
http://localhost:3000Ajouter et supprimer des créneaux de rendez-vous et les voir ajoutés et supprimés de la base de données Firebase Realtime.
Example adding a slot and it being shown on the Firebase Realtime database
Conclusion et prochaines étapes
Aujourd'hui, vous avez vu comment construire une application web de démonstration de prise de rendez-vous. Vous pouvez maintenant aller de l'avant et ajouter un style plus fantaisiste et d'autres fonctionnalités. Vous pouvez utiliser ce que vous avez appris ici pour créer de nombreux planificateurs de rendez-vous, que ce soit pour une salle de sport ou pour un créneau de vaccination - laissez libre cours à votre créativité !
Contactez-nous sur Twitter et rejoignez notre communauté sur Slack.