いわりょのBlog

IT関連で学んだことを書いていきます。

お店の営業カレンダー&予約状況を表示するFullCalendar導入 Googleカレンダー同期編

実現するもの

HPによくある定休日が色付けされていたり、予約時間が書かれているカレンダーです。
Googleカレンダーと連携しているので、Google側で予定が追加されたり、削除されたりするとHPのカレンダーもすぐにその情報が反映されます。どのように反映されるかも設定できます。
便利なので作ってみました。思ったよりハードルは低かったです。

条件

rails 5.1.7
ruby 2.6.3
Turbolinksは削除してます

必要なgemインストール

gem 'jquery-rails', 4.3.1'
gem 'fullcalendar-rails'
gem 'momentjs-rails'
bundle install

application.jsを編集

app/assets/javascript/application.js

//= require jquery
//= require moment
//= require fullcalendar

calender.jsを作成して、編集

$ touch app/assets/javascripts/calender.js
app/assets/javascript/calender.js

$(document).ready(function(){
  $('#calendar').fullCalendar({
  });
});

application.cssを編集

application.css

*= require fullcalendar

テンプレートに追加

xxx.html.erb

<div id="calendar"></div>

これでデフォルトのカレンダーが表示されます。

Googleカレンダーと同期

必要な作業は、

こんなもんです。

最初にfullcalenderのドキュメントからgcal.jsを取得します。
events from Google Calendar - Docs v3 | FullCalendar

カレンダーを使用するテンプレートに追加します。
個別にjsを追加している場合は以下のように

<%= javascript_include_tag "gcal.js" %>

GoogleカレンダーAPIキーはこちらを参考にしてください。↓
www.1-firststep.com
取得したAPIキーはどこかにメモ。

次はカレンダーを作成します。
Googleカレンダーを開いて、
右上の歯車マーク→設定→カレンダーの作成→新しいカレンダーを作成を選択していきます。

f:id:Ryo10Leo:20200107005507p:plain

こんな画面が出るので作りたいカレンダーを作成します。

そうすると、設定画面の左側に作成したカレンダーがあることが確認できます。

f:id:Ryo10Leo:20200107005950p:plain

カレンダーの公開設定をしていきます。
左側の作成したカレンダーをクリックして、カレンダーの設定を選びます。
下の方にスクロールすると、「アクセス権限」の項目があるので、そちらの「一般公開して誰でも利用できるようにする」にチェック。

f:id:Ryo10Leo:20200107010554p:plain

他にも予定の詳細を表示するかのオプションもありますが、それはカレンダーや個人によるので好きな設定で、、、

設定が終わったら、さらに下にスクロール。
そうすると「カレンダー統合」という項目があるのでそこに書いてある「カレンダー ID」をメモ。

あとは以下のようにcalender.jsに取得したAPIキーと作成したカレンダーのそれぞれのカレンダーIDを書き込めば同期は完了です!

calender.js

$(document).ready(function(){
            $('#calendar').fullCalendar({
                             
                googleCalendarApiKey: 'APIのキー',
                eventSources: [
                {            
                    googleCalendarId: '休日カレンダーのid',
                     (省略)
                },
                {              
                    googleCalendarId: '予約カレンダーのid,
                    (省略)
               }
                ]
            });
        });
});

カレンダーごとのイベントの色指定などはドキュメントを参考にすると、すぐに設定できます。↓
Documentation | FullCalendar

自分好みにアレンジ

デフォルトでカレンダーは、prevボタンやnextボタンがあって、全部の月が見れるんですけど
個人的に2ヶ月分の営業カレンダーが表示されていれば十分かなと思ったので、いらないボタンを消して、2ヶ月分表示してデザインも無理やりcssで変えました。

xxx.html.erb

    <div class="calender-wrapper effect-fade-up">
        <div id="calendar">
            <div class="tabs"></div>
            <div class="tabs"></div>
            <div class="calender-text"><span class="brown"></span>はお休み、<span class="blue"></span>はご予約です。予定は予告なく変更される場合がございます。</div>
        </div>
    </div>

二つのtabs要素をカレンダーにします。

calender.css

.calender-wrapper{
    margin: 0% 4%;
    margin-top: 15px;
}
.tabs{
    width:45%;
}
#calendar{
    position: relative;
    display: flex;
    justify-content: space-between;
    padding: 4%;
}
.fc-state-default {
    text-shadow: 0 0px 0px !important;
    box-shadow: 0 0px 0 !important;
}
.fc-icon {
    font-family: "YuGothic","Yu Gothic Medium";
}
.fc .fc-button-group > :first-child {
    margin-right: 5px;
}
.fc-prev-button,
.fc-next-button{
    color: white !important;
    background: #33691e !important;
}
.fc-today-button {
    color: #FFF;
    background: #5e4037;
}
.fc-state-default.fc-corner-left {
    border-top-left-radius: 0px !important;
    border-bottom-left-radius: 0px !important;
}
.fc-state-default.fc-corner-right {
    border-top-right-radius:  0px !important;
    border-bottom-right-radius:  0px !important;
}
.fc-unthemed th{
    color: #FFF;
    background: #33691e;
}
.calender-text{
    position: absolute;
    bottom: -2%;
    font-size: 0.8125rem;
}
.calender-text .brown {
    padding: 2px 8px;
    background: #3e2723;
    opacity: .3;
    border-radius: 2px;
}
.calender-text .blue {
    padding: 2px 8px;
    background: #3a87ad;
    border-radius: 2px;
}

デベロッパーツールでデザインを変えたい要素のクラスを覗き込みながら、!importantで無理やりデザイン変えてます笑
あとは二つのカレンダーを横並びにしたりしてます。

calender.js

    var m = moment();
    $(document).ready(function(){
        var cals = $('#calendar .tabs');
        cals.each(function(){
            $(this).fullCalendar({
                defaultDate: m,
                header: {left:'',center:'title',right:''},
                googleCalendarApiKey: 'API_key',
                contentHeight: 350,
                firstDay: 1,
                timeFormat: 'H:mm',
                eventSources: [
                    {
                        googleCalendarId: 'calender_id_1'
                    },
                    {
                        googleCalendarId: 'calender_id_2',
                        rendering: 'background',
                        color:     '#5e4037'
                    }
                ]
            });
            m = m.add(1, 'month');
        });
    });
});

詳しい解説は省略しますが、何をしているかというと二つのtabs要素を順番に設定を反映させて表示させています。

設定では、表示させる月を設定したり、いらないボタンを消したり、高さを調節したり、フォーマット、月曜日を一番左に表示させたりなどしています。

それでできたのが以下のカレンダーです。
f:id:Ryo10Leo:20200107014015p:plain

デザインが一番時間がかかりました、、、(特にCSS)

スマホ画面用のカレンダーも作っているので余力があれば公開します。

実際calender.jsのAPIキーとカレンダーIDを記述するときに環境変数を使っているので以下の記事のようにやっています。
ryo10leo.hatenablog.com