E100 ユーザーカレンダー機能の導入

今回は管理画面から登録したスケジュールをユーザーが参照・予約するための機能の実装方法を紹介します。

ユーザーカレンダー機能作成

①npmを用いてカレンダーライブラリ(FullCallendar)を導入する。

カレンダー形式の表示には、FullCallendarライブラリ(https://fullcalendar.io/) Standardを利用します。

 $sail npm install fullcalendar

②npmサーバーがlocalhostで正しく動作するように、server:{} の設定を追記する。

※下記、L5~L9を参照

vite.config.js
  export default defineConfig({
+     server: {
+         hmr: {
+             host: 'localhost',
+         },
+     },
      plugins: [
          laravel({
              input: [
                  'resources/css/app.css',
                  'resources/js/app.js',
              ],
              refresh: true,
          }),
      ],
  });

③npmサーバーを起動する。

css,jsファイルの変更が動的に開発環境に反映されるようになります。

$sail npm run dev

④カレンダー表示用のコントローラーを作成する。

$sail artisan make:controller EventController

下記のように表示されたら成功。

$INFO  Controller [app/Http/Controllers/EventController.php] created successfully.  

⑤カレンダー表示用のViewファイルを作成する。

resources/views/calendar.blade.php を新規作成します。

resources/views/calendar.blade.php
<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            カレンダー
        </h2>
    </x-slot>

    <div class="min-h-screen bg-gray-100">
        <!-- Page Content -->
        <main>
            <div class="py-12">
                <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                    {{-- 完了メッセージ --}}
                    @if (session('message'))
                    <div class="flex items-center bg-blue-500 text-white text-sm font-bold px-4 py-3" role="alert">
                        <svg class="fill-current w-4 h-4 mr-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M12.432 0c1.34 0 2.01.912 2.01 1.957 0 1.305-1.164 2.512-2.679 2.512-1.269 0-2.009-.75-1.974-1.99C9.789 1.436 10.67 0 12.432 0zM8.309 20c-1.058 0-1.833-.652-1.093-3.524l1.214-5.092c.211-.814.246-1.141 0-1.141-.317 0-1.689.562-2.502 1.117l-.528-.88c2.572-2.186 5.531-3.467 6.801-3.467 1.057 0 1.233 1.273.705 3.23l-1.391 5.352c-.246.945-.141 1.271.106 1.271.317 0 1.357-.392 2.379-1.207l.6.814C12.098 19.02 9.365 20 8.309 20z"/></svg>
                        <p>{{ session('message') }}</p>
                    </div>
                    @endif

                    <div id='calendar' class="container-sm"></div>
                </div>
            </div>

            @include('reserve-modal');
        </main>
    </div>
</x-app-layout>

⑥カレンダー表示のコントローラーを追加する。

※下記、L17~L35を参照

app/Http/Controllers/EventController.php
  class EventController extends Controller
  {
+        public function index()
+        {
+            return view('calendar');
+        }
+
+        public function getEvents()
+        {
+            $schedules = Schedule::select(
+                // FullCalendarの形式に合わせる
+                'id',
+                'title as title',
+                'from_date as start',
+                'due_date as end',
+                'staff_name as staff',
+                'reservation_limit as limit'
+            )->get();
+    
+            return $schedules;
+        }
  }

※下記、参照しファイルの冒頭に追加する

resources/views/calendar.blade.php
@include('reserve-modal');

⑦カレンダー表示用のJavascript処理を実装する。

resources/js/calendar.jsを新規作成する。

resources/js/calendar.js
import { Calendar } from "fullcalendar";
import axios from 'axios';

var calendarEl = document.getElementById("calendar");

if (calendarEl)
{
    let calendar = new Calendar(calendarEl, {
        initialView: "dayGridMonth",
        locale: "ja",
        editable: false,	//イベントを編集できないようにする
        contentHeight: 'auto',
        headerToolbar: {
            left: "prev,next today",
            center: "title",
            right: "dayGridMonth,timeGridWeek,listWeek",
        },
        buttonText: {
            today: '今月',
            month: '',
            week: '',
            list: 'リスト'
        },
        eventTimeFormat: { hour: 'numeric', minute: '2-digit' },
        //eventDisplay: "block",
        events: '/events',

        //スケジュールデータの読込み (表示単位)
        // events: function (info, successCallback, failureCallback) {
        //     // Laravelのイベント取得処理の呼び出し
        //     axios
        //         .post("/schedule-get", {
        //             start_date: info.start.valueOf(),
        //             end_date: info.end.valueOf(),
        //         })
        //         .then((response) => {
        //             // 追加したイベントを削除
        //             calendar.removeAllEvents();
        //             // カレンダーに読み込み
        //             successCallback(response.data);
        //         })
        //         .catch(() => {
        //             // バリデーションエラーなど
        //             alert("スケジュール取得に失敗しました");
        //         });
        // },


        // イベントクリック時の処理
        eventClick: function(info) {
            //alert('Event: ' + info.event.title);
            //console.log(info.event.extendedProps);

            //モーダルへのデータセット
            document.getElementById("schedule_id").value = info.event.id;
            document.getElementById("modal-data-title").innerHTML = info.event.title;
            document.getElementById("modal-data-start").innerHTML = info.event.start;
            document.getElementById("modal-data-end").innerHTML   = info.event.end;
            document.getElementById("modal-data-staff").innerHTML = info.event.extendedProps.staff;
            document.getElementById("modal-data-limit").innerHTML = info.event.extendedProps.limit;

            //モーダルを表示
            let modal_button = document.getElementById("user-reserve-modal-button");
            modal_button.click();
        },
    });
    calendar.render();
}

⑧calendar.jsをアプリのjsに組み込む。

resources/js/app.js を開き、importを追加します。

※下記、参照しファイルの冒頭に追加する

resources/js/app.js
+ import './calendar';

確認事項

・登録済みユーザーでログインし、/calendar にアクセスするとカレンダーが表示されるかを確認する。

・管理画面から登録したスケジュールがカレンダーに表示されるかを確認する。

---