
Node、Firebase、Vonageを使って予約スケジューラーを構築する
所要時間:5 分
はじめに
このチュートリアルでは、Node.js、Express、Firebase、そして Vonage Messages APIを使用します。.このプロジェクトの このプロジェクトの GitHub リポジトリもあります。.
Firebaseのセットアップ
はじめに Firebaseコンソール.
をクリックする。
add a new projectプロジェクトに意味のある名前をつける。
vonage appointment schedulerプロジェクトの一意な識別子ID(リアルタイムデータベースURL、Firebaseホスティングサブドメインなどで使用されます。プロジェクト作成後に変更することはできません。)
ボタンをクリックして続ける
Console view with a text field to enter project and name and edit the project id
アナリティクスを有効にするかどうかを選択します。このチュートリアルでは使用しません。
ボタンをクリックしてプロジェクトを作成する
プロジェクトが作成されるのを待つ
Project being created
プロジェクトの準備ができたら、続けるをクリックします。プロジェクトのコンソールビューが表示されます。
歯車のアイコンをクリックして課金タイプを設定し、次に「使用状況と課金」をクリックし、「詳細と設定」タブをクリックしてBlazeを使用するプランを変更します。この従量課金プランは、サードパーティAPIを使用する場合に必要です。
Firebase Tools CLIをインストールする
ターミナルから、FirebaseツールをNPMでインストールする: npm install -g firebase-tools.次に、firebase login と入力する。ブラウザのウィンドウが開き、自動的に認証されるか(すでにログインしている場合)、認証情報の入力を求められます。これでFirebase CLIのインストールは完了です。
リアルタイム・データベースの作成とセットアップ
次に、アポイントメントスロットの情報を保持するNoSQLデータベースインスタンスを作成します。私たちのアプリにはユーザーが予約を入れたりキャンセルしたりできるビューがあります。ビューを操作する人がアポイントメントの日時を選択すると、そのスロットはFirebase RealTimeデータベースから追加または削除されます。
Firebaseコンソールのメニューから、Buildの下にある "Realtime Database "をクリックします。
Button to create the database
データベースの作成」をクリック
データを保存するリアルタイムデータベースの場所を選択し
nextデータベースを ロックモードかテストモードかを選択します。.この例では、テスト・モードを使用します。
クリック
enable
Database created
データベースJSONファイルのインポート
すでに割り当てられたスロットがあり、これからスロットを追加したり削除したりすることができるデータベースをインポートしてみましょう。以下のスニペットにあるJSONを含む myAppointments.jsonというファイルを作成し、コンソールからこのファイルをインポートします。
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
データベースのルールを追加する
Firebase Realtime Database Rules は、データベースにアクセスできる人、インデックスの作成方法、データの構造化を決定します。
FirebaseコンソールのRealtimeデータベースビューに "Rules "という項目があるので、そのタブをクリックします。ルールの編集画面が表示されます。
以下のコード・スニペットのルールをコピーしてコンソールに貼り付け、コレクションを
myAppointmentsコレクションがdateフィールドによってインデックスされるコレクションを設定するためです。をクリックする。
Publish
{
"rules": {
".read": "now < 1643842800000", // 2022-2-3
".write": "now < 1643842800000", // 2022-2-3
"myAppointments": {
".indexOn": ["date"]
}
}
}
Edit Firebase Database Rules
プロジェクト構造の作成
このチュートリアルが終わるころには、あなたのプロジェクトの構造はおおよそこのようになっているでしょう。次のステップでは、コンテンツ、外観、機能性を構築し、使用するサービスを処理するファイルを作成します。
Project Structure
セットアップ
プロジェクト・フォルダーを作成し
cdを作成する:mkdir appointment-scheduler && cd appointment-schedulerNPMを初期化する:
npm init.このコマンドはプロジェクトに関する情報を追加するよう促します。依存関係をインストールします:
npm install @vonage/server-sdk dotenv uuid express firebase-admin firebase-functionsタイプ
firebase init.ダッシュボードですでにプロジェクトを作成しているので、「Type」を選択します。Use an existing projectを選択すると、必要なプロジェクトを選択するよう促されます。私のプロジェクトIDvonage-appointment-schedulerを選択してください。またRealtime Database機能
HTMLコンテンツを作成する
HTMLのinput要素には、日付や時刻を選択するための多くのタイプオプションがあることをご存知だろうか。例えば date, datetime-local, time.このチュートリアルでは <input type="datetime-local">.この方法は、日付-時間ライブラリを使用する場合と比べて、いくつかの矛盾が発生する可能性があるため、おそらく堅牢ではありませんが、このチュートリアルの目的には機能します。例えば、18:00は予約可能ですが、18:01は予約できません。
を作成します。
public/index.htmlを作成し、以下のコードスニペットを追加することで、新しいアポイントメントを選択したり、キャンセルしたりすることができます。
<!-- 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>
CSSスタイリングの追加
このデモ・ウェブ・アプリでは、コンテンツをページの中央に配置し、入力が無効な場合は赤い✖を、有効な場合は✓を表示するようにスタイルを追加します。
を作成する。
public/styles.cssファイル以下のCSSコードを貼り付けます。
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;
} 環境変数ファイルの作成
を作成し
.envを作成し、以下の情報を入力する。
は
FIREBASE_DATABASE_URLはFirebaseのコンソールその
VONAGE_API_KEYとVONAGE_API_SECRETは ダッシュボードには
VONAGE_FROM_NUMBERには、メッセージの送信者として表示される番号、名前、またはブランドが含まれます。は
VONAGE_TO_NUMBERはSMSメッセージを受信する番号です。
JavaScriptファイルの作成server.js
を作成する。 server.jsを作成し、UIから投稿されたリクエストの処理方法をExpressに伝えます。どのように構築するか、順を追って説明しよう。 サーバーファイル一式はこちら.
ウェブ・アプリはexpressを使い、以前に作成した静的ファイルを publicフォルダから作成した静的ファイルを読み込みます。
依存関係とインポートファイルを追加するには、以下のコード・スニペットを
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 })); サービスアカウントの追加
Firebase サービスアカウントは、Firebase の様々な機能を認証するために使用できます。今回のプロジェクトでは、Firebase Admin SDK を使用して Database URL にアクセスします。
Firebase Consoleから歯車をクリックし、Service Accountタブを選択します。
ボタンをクリックして
generate key生成されたファイルをプロジェクトのルートに追加し、名前を次のように変更する。
serviceAccountKey.jsonこのチュートリアルの次のステップにあるように、Admin SDKの設定スニペットをコピーしてプロジェクトに貼り付け、Firebaseを初期化します。Firebaseを初期化するために
${process.env.FIREBASE_DATABASE_URLファイルから URL を読み取るために.envファイルから URL を読み込むために使用していますが、これは Firebase Admin SDK 設定にあるのと同じデータベース URL です。
Admin SDK configuration
Firebaseの初期化
私たちは initializeAppを使用して Firebase アプリのインスタンスを作成し、初期化します。 /myAppointmentsFirebase データベースインスタンスの作成と初期化に使用します。
以下のコード・スニペットを
server.jsに追加します。
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'); Vonage API オブジェクトの初期化
Vonage クライアント・クラスのインスタンスを作成し、Vonage API Key と Secret で初期化します。 .envファイルに追加した
以下のコード・スニペットを
server.jsに追加します。
const vonage = new Vonage({
apiKey: process.env.VONAGE_API_KEY,
apiSecret: process.env.VONAGE_API_SECRET,
}); getDateTime() 関数の作成
HTML入力タイプ datetime-localは YYYY-MM-DDThh:mm.そこで、日付と時間を文字で分割する関数を書きます。 T.例えば 2018-06-12T19:30では 2018-06-12となります。 19:30となります。
以下のコード・スニペットを
server.jsに追加します。getDateTime()関数
const getDateTime = (slot) => {
return slot.split('T');
};
を作成する。/appointmentエンドポイント
アポイントメントを作成するための /appointmentエンドポイントを作成しましょう。このエンドポイントはスロットが利用可能かどうかをチェックし、Firebaseデータベースにスロットを追加し、最後にVonage Messages APIを使用してユーザーの電話にSMSで確認を返します。
以下のコード・スニペットを
server.jsに追加して/appointmentエンドポイントを作成します。
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) => {};
});
リクエストハンドラ内の機能の多くがまだ実装されていないことにお気づきかもしれない。
スロットの空き状況を確認する
この関数は、スロットがすでにデータベースに存在するかどうかをチェックすることで、スロットが利用可能かどうかを検証します。この関数は ref.orderByChild('date').クエリは一度に1つのキーを指定することができます。パフォーマンスを向上させるために .indexOnでインデックスを定義しています。そして .once('value')を使用して、値のイベントを1回だけリッスンし、その後リッスンを停止します。
以下のコード・スニペットを
server.jsに追加します。checkIfAvailable()関数
// 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;
};
スロットをデータベースに追加する
次の関数 addToDatabase()はFirebaseデータベースにスロットとコードを追加します。このコードは予約をキャンセルするために必要です。
// Adds the slot to the database
addToDatabase = () => {
let code = uuidv4();
ref.child(code).set({
date: slot,
userId: code,
});
return code;
};
予約情報をSMSで送信する
最後に、スロットが予約されると、SMSで確認が送信されます。 Meeting booked at ${time} on date: ${date}. Please save this code: ${code} in case you'd like to cancel your appointment.関数 sendSMStoUser().
以下のコード・スニペットを
server.jsに追加します。sendSMStoUser()関数
// 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);
}
}
);
});
};
ビジネス・ロジックを確定する
以下のコードは、先に作成したヘルパー関数を呼び出す役割を担っています。もしその時間帯が空いていれば、ユーザーはその時間帯をデータベースに追加し、SMSを送り返します。そうでない場合は、別の時間帯を選択するように要求されます。
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.`
);
} 予約のキャンセル/cancelAppointment
を作成しましょう。 /cancelAppointmentエンドポイントを作成しましょう。ユーザーがアポイントメントをスケジューリングしたときに受け取ったコードを使用して、データベースからアポイントメントをキャンセルするためのPOSTリクエストを処理します。
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.`);
});
港を聴く
最後に、アプリは指定されたポートをリッスンする。 https://localhost:${port}.このURLで、このデモアプリケーションのUIを操作し、FirebaseコンソールのWebページで追加/削除されたスロットを確認することができます。
app.listen(port, () => {
console.log(`I run on port ${port}`);
});
試してみる
あなたの
package.jsonファイルに開始スクリプト"start": "node script/server.js"を追加する。"test": "echo \"Error: no test specified\" && exit 1",.以下のようにする:
すべての依存関係をインストールする
npm installNPMコマンドを実行してプロジェクトを実行する
npm run startに移動する。
http://localhost:3000アポイントメントスロットの追加と削除、Firebase Realtime Databaseからの追加と削除の確認
Example adding a slot and it being shown on the Firebase Realtime database
結論と次のステップ
今日、あなたはアポイントメントスケジューラーデモウェブアプリを構築する方法を見ました。ここで学んだことを活かして、スポーツジムや予防接種など様々なアポイントメントスケジューラーを作成することができます。ここで学んだことを活かして、スポーツジムや予防接種など様々なアポイントメントスケジューラーを作成することができます!