見出し画像

第9話 来店希望日の選択

こんにちは!Kenです。

前回は予約メニュー選択Flex Messageの作成を行い、それを返信できるようにしました。

希望メニューのボタンを押すと、postbackイベントが返って来ますのでその処理を書いていきます。

lineBot関数内の変更

lineBot関数内で、イベントタイプによって実行関数の振り分けを行ってましたね。その振り分けを行っているswitch構文を次のように変更します。

switch(ev.type){
           case 'follow':
               promises.push(greeting_follow(ev));
               break;
           
           case 'message':
               promises.push(handleMessageEvent(ev));
               break;
           
           case 'postback':
               promises.push(handlePostbackEvent(ev));
               break;
       }

実際にevへ返って来ているイベントオブジェクトは以下のようになってます。

ev:{
type: 'postback',
replyToken: 'xxxxxxxxxxxxxxxxx',
source: { userId: 'yyyyyyyyyyyyyyyy', type: 'user' },
timestamp: 1601177107159,
mode: 'active',
postback: { data: 'menu&0' }
}

これは「カット」を選択した場合のイベントオブジェクトとなります。

ev.type = 'postback'、ev.postback.data = 'menu&0'であることがわかるかと思います。

handlePostbackEvent関数の実装

ではpostbackイベントを処理する関数を実装していきましょう。

本来はメニューは複数選択でき、最後に「選択終了」を押すと、次の処理に進むようにしたいのですが、今回はメニューは1つのみ選択可能とし、選択メニューが返って来たら選択終了を押さなくとも次の処理に進むようにします。

const handlePostbackEvent = async (ev) => {
   const profile = await client.getProfile(ev.source.userId);
   const data = ev.postback.data;
   const splitData = data.split('&');
   
   if(splitData[0] === 'menu'){
       const orderedMenu = splitData[1];
       askDate(ev,orderedMenu);
   }
}

まず、'menu&0'を'&'で分割してあげることによって、splitDataに[ 'menu' , '0']という配列を代入してあげてます。

そして、配列の先頭が'menu'の時、次のメッセージを送る関数askDateを実行しています。引数にはevと選択したメニューがカットであることを表す'0'を渡してます。

askDate関数の実装

では、次に投げるメッセージは来店希望日としましょう。

Flex Message Simulatorで次のような簡単なメッセージを作成してください。

画像1

今回はbodyとfooterのみ使います。前回に比べたらこのくらい楽勝ですね。

■body: text
■footer: button

また、footerに配置したボタンを押した際のActionは次のようにしてください。

■type: datetimepicker
■label: 希望日を選択する
■data: date(とりあえず。後で少しいじります)
■mode: date

ここで覚えておいて欲しいのはtypeとmodeです。次を参照してください。

これは日時選択アクションに分類されるもので、modeには3つの選択肢から選ぶことができます。

・date: 日付を選択する
・time: 時刻を選択する
・datetime: 日付と時刻を選択する

時刻も同時に選択できても良いかもしれませんが、時刻選択が若干使いにくそうなのと、選択可能な時刻を予め計算して提示してあげないと、お客様は何回も日時選択にトライすることになりそうだったので、ここでは日付のみの選択(date)としました。

では、ここまでできたらJSONをコピーしてプログラムに貼り付けましょう。

const askDate = (ev,orderedMenu) => {
   return client.replyMessage(ev.replyToken,{
       "type":"flex",
       "altText":"予約日選択",
       "contents":
       {
           "type": "bubble",
           "body": {
             "type": "box",
             "layout": "vertical",
             "contents": [
               {
                 "type": "text",
                 "text": "来店希望日を選んでください。",
                 "size": "md",
                 "align": "center"
               }
             ]
           },
           "footer": {
             "type": "box",
             "layout": "vertical",
             "contents": [
               {
                 "type": "button",
                 "action": {
                   "type": "datetimepicker",
                   "label": "希望日を選択する",
                   "data": `date&${orderedMenu}`,
                   "mode": "date"
                 }
               }
             ]
           }
         }
   });
}

先ほど、Flex Messageを作った際にはdataはdateとしましたが、その部分を少し改造してます。

"data": `date&${orderedMenu}`

askDateに引数として渡してあげた変数orderedMenuをdateに&で繋げてあげているのがわかります。

予約はいくつかの問答を繰り返します。そのため、postback.dataに以前何を選んだのかを記録していく必要があります。そのため、過去に選んだ選択を&で数珠つなぎのように追加していきます。

グローバル変数とかに入れればいいじゃん!って思われるかもしれませんが、私も最初それで進めていて大失敗したのです(泣)。なぜそれがダメなのかを知りたい方は個別に連絡ください。

ちなみにこのアプリで作成する予約の問答フローは以下となります。

■「予約する」のメッセージ送信
■メニューの選択
■来店希望日の選択
■希望時間帯の選択
■最終確認「はい」で予約確定

さて、ここまで出来たらherokuへデプロイして確認してみましょう。

画像2

何かメニューをタップすると、

画像3

日付選択が出ました!日付を選んでも当然何も起こりませんが。

本日は、この辺にしておきましょう。

次回は、時間選択から進めます。

最後までお読みいただき、ありがとうございました。

少しでも参考になりましたら「スキ」をいただけると幸いです。

MENTA でLINEBOT開発サポートをしております。お気軽にご相談ください。

この記事が気に入ったらサポートをしてみませんか?