学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

【民泊6.0】フルカレンダー

フルカレンダーをインストールします。


コマンド
一文です。
yarn add @fullcalendar/core@5.3.1 @fullcalendar/daygrid @fullcalendar/interaction@5.3.1 @fullcalendar/list@5.3.1


「app/javascript/packs/application.js」ファイルに以下の記述を追加します。


記述追加 【app/javascript/packs/application.js(21行目)】

window.Calendar = require("@fullcalendar/core").Calendar;
window.DayGridPlugin = require("@fullcalendar/daygrid").default;
window.interactionPlugin = require("@fullcalendar/interaction").default;
window.ListPlugin = require("@fullcalendar/list").default;



【app/javascript/packs/application.js】

// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

require('jquery');
require("jquery-ui/ui/widgets/datepicker");
require("jquery-ui/ui/widgets/slider");

require("raty-js")

window.Noty = require("noty")
window.Dropzone = require("dropzone")
window.BulmaCarousel = require("bulma-extensions/bulma-carousel/dist/js/bulma-carousel")

window.Calendar = require("@fullcalendar/core").Calendar;
window.DayGridPlugin = require("@fullcalendar/daygrid").default;
window.interactionPlugin = require("@fullcalendar/interaction").default;
window.ListPlugin = require("@fullcalendar/list").default;

$(document).on('turbolinks:load', () => {
    $('.toggle').on('click', (e) => {
        e.stopPropagation();
        e.preventDefault();
        $('#' + e.target.getAttribute('aria-controls')).toggleClass('is-hidden');
    })
})

// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

require("trix")
require("@rails/actiontext")



「app\controllers」フォルダに「calendars_controller.rb」ファイルを新規作成します。


app\controllers\calendars_controller.rb(新規作成したファイル)

class CalendarsController < ApplicationController

    before_action :authenticate_user!

    include ApplicationHelper
    
    def host
      @rooms = current_user.rooms
      params[:start_date] ||= Date.current.to_s
      params[:room_id] ||= @rooms[0] ? @rooms[0].id : nil
      if params[:q].present?
        params[:start_date] = params[:q][:start_date]
        params[:room_id] = params[:q][:room_id]
      end
      @search = Reservation.ransack(params[:q])
      if params[:room_id]
        @room = Room.find(params[:room_id])
        start_date = Date.parse(params[:start_date])
        first_of_month = (start_date - 1.months).beginning_of_month # 最初の月の1日から
        end_of_month = (start_date + 1.months).end_of_month # => 3ヶ月後の31まで
        @events = @room.reservations.joins(:user)
                        .select('reservations.*, users.full_name, users.email')
                        .where('(start_date BETWEEN ? AND ?) AND reservations.status <> ?', first_of_month, end_of_month, 2)

      else
        @room = nil
        @events = []
      end
    end
  end
  
  



記述追加 config\routes.rb
24行目に「get '/host_calendar' => "calendars#host"」の記述追加

Rails.application.routes.draw do

  # ルートを app\views\pages\home.html.erb に設定
  root 'pages#home'
  
  mount ActionCable.server => '/cable'

  devise_for :users, 
    path: '', 
    path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'},
    controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'}
    
  get 'pages/home'
  get '/dashboard', to: 'users#dashboard'
  get '/users/:id', to: 'users#show', as: 'user'
  get '/your_trips' => 'reservations#your_trips'
  get '/your_reservations' => 'reservations#your_reservations'
  get 'search' => 'pages#search'
  get 'settings/payment', to: 'users#payment', as: 'settings_payment'
  get 'settings/payout', to: 'users#payout', as: 'settings_payout'
  get '/conversations', to: 'conversations#list', as: "conversations"
  get '/conversations/:id', to: 'conversations#show', as: "conversation_detail"
  get '/notifications' => 'notifications#index'
  get '/host_calendar' => "calendars#host"
  
  post '/users/edit', to: 'users#update'
  post '/settings/payment', to: 'users#update_payment', as: "update_payment"
  post 'messages', to: 'messages#create'

  resources :rooms, except: [:edit] do
    member do
      get 'listing'
      get 'pricing'
      get 'description'
      get 'photo_upload'
      get 'amenities'
      get 'location'
      get 'preload'
      get 'preview'
      delete :delete_photo
      post :upload_photo
    end
    resources :reservations, only: [:create]
  end

  resources :guest_reviews, only: [:create, :destroy]
  resources :host_reviews, only: [:create, :destroy]  

  resources :reservations, only: [:approve, :decline] do
    member do
      post '/approve' => "reservations#approve"
      post '/decline' => "reservations#decline"
    end
  end

  resources :users, only: [:show] do
    member do
      post '/verify_phone_number' => 'users#verify_phone_number'
      patch '/update_phone_number' => 'users#update_phone_number'
    end
  end

  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end



「app\views」フォルダに「calendars」フォルダを新規作成します。
作成した「calendars」フォルダに「host.html.erb」ファイルを新規作成します。



app\views\calendars\host.html.erb(新規作成したファイル)

<% if !@rooms.blank? %>
  <div class="row">
    <%= search_form_for @search, class: 'form-group', remote: true, url: host_calendar_path do |f| %>
      <div class="container">
          <br/>
          <div class="field">
            <div class="control">
              <label>登録しているお部屋</label><br/>
                <%= f.select :room_id, options_for_select(@rooms.collect {|u| [u.listing_name, u.id]}, params[:room_id]), {}, {
                  onchange: "submit(this.form);",
                  class: "select is-primary"
                } %>
            </div>
          </div>
      </div>
      <%= f.hidden_field :start_date, id: "start-date", value: params[:start_date], onchange: "submit(this.form);" %>
    <% end %>
  </div>
<% end %>
<section class="section">
    <div class="container">
<div id="calendar"></div>
</div>
</section>

<!-- moment lib -->
<script src='https://cdn.jsdelivr.net/npm/moment@2.27.0/min/moment.min.js'></script>

<script>
  window.reservations = <%= raw @events.to_json %>
  console.log(reservations);

  function showReservations(data) {
    return data.map(function (e) {

      if (e['start_date'] !== e['end_date']) {
        e['end_date'] = moment(e['end_date']).add(1, 'days').format();
      }
        return {
          title: e.full_name ,
          start: e['start_date'],
          end: e['end_date'],
          allDay: true,  
          
        }
    });
  }  

  $(function() {

    var calendarEl = document.getElementById('calendar');
    var calendar = new Calendar(calendarEl, {
  
      headerToolbar: {
        left: 'prev,next',
        center: 'title',
        right: 'dayGridMonth,listMonth'
      },

        timeZone: 'JST',
        initialDate: $('#start-date').val(),
        locale: 'ja', 
        plugins: [DayGridPlugin, interactionPlugin, ListPlugin],
        initialView: 'dayGridMonth',
        eventColor: 'blue',
        events: showReservations(reservations),

    });
    calendar.render();

  });
  
  $('.fc-prev-button').click(function() {
    var current = new Date($('#start-date').val());
    var prev = new Date(current.getFullYear(), current.getMonth() - 1, 1)
    $('#start-date').val(moment(prev).format('YYYY-MM-DD'))
    $('#start-date').trigger('change')
  });

  $('.fc-next-button').click(function() {
      var current = new Date($('#start-date').val());
      var next = new Date(current.getFullYear(), current.getMonth() + 1, 1)
      $('#start-date').val(moment(next).format('YYYY-MM-DD'))
      $('#start-date').trigger('change')
  });
</script>



「app\views\calendars」フォルダに「host.js.erb」ファイルを新規作成します。


app\views\calendars\host.js.erb(新規作成したファイル)

reservations = <%= raw @events.to_json %>

$('#calendar').fullCalendar('removeEvents');
$('#calendar').fullCalendar('addEventSource', showReservations(reservations));
$('#calendar').fullCalendar('rerenderEvents');



ナビゲーションバーを編集します。


記述追加 「app/views/shared/_navbar.html.erb」
76行目に「<%= link_to "カレンダー", host_calendar_path, class: "navbar-item" %>」の記述を追加します。

<nav class="navbar is-light" role="navigation" aria-label="main navigation">
    <div class="navbar-brand">
        <a class="navbar-item" href="/">
            <h1>テストサイトMinpaku6</h1>
        </a>
        <a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample">
            <span aria-hidden="true"></span>
            <span aria-hidden="true"></span>
            <span aria-hidden="true"></span>
        </a>
    </div>
    
    <div id="navbarBasicExample" class="navbar-menu">
        <div class="navbar-start">
            <div class="navbar-item">
            </div>
        </div>
        <div class="navbar-end">
            <a class="navbar-item"></a>
            <a class="navbar-item"></a>

            <!-- もしログインしていなかったら-->
            <% if (!user_signed_in?) %>
                <div class="navbar-item">
                    <div class="buttons">
                        <%= link_to  "新規ユーザ登録", new_user_registration_path, class: "button is-white" %>
                        <%= link_to  "ログイン", new_user_session_path, class: "button is-white" %>
                    </div>
                </div>

            <!-- ログインしていたら -->
            <% else %>

                <!-- 通知 -->
                <div style="position: relative; top: 15px; left: -35px;">
                    <%= link_to notifications_path do %>
                        <i class="fa fa-bell fa-2x icon-babu"></i>
                        <%if current_user.unread > 0 %>
                            <span class="badge" id="navbar_num_of_unread"><%= current_user.unread %></span>
                        <% end %>
                    <% end %>
                </div>

                <div class="navbar-item has-dropdown is-hoverable" style="margin-right: 100px;">
                    <a class="navbar-item">
                        <figure class="image is-48x48 m-r-5 avatar <%= current_user.status ? "online" : "offline" %>">
                        <div style="margin-top: 0.6rem;">
                        <%= image_tag avatar_url(current_user), class: "is-rounded" %>
                        </div>
                        </figure>                    
                        <%= current_user.full_name %>
                    </a>
                    <div class="navbar-dropdown">
                        <%= link_to  "ユーザ登録情報編集", edit_user_registration_path, class: "navbar-item" %>
                        <a href="" class="navbar-item"></a>
                        <hr class="navbar-divider">
                        <%= link_to  "ログアウト", destroy_user_session_path, method: :delete, class: "navbar-item" %>
                    </div>
                </div>
            <% end %>            
        </div>
    </div>
</nav>

<% if (user_signed_in?) %>
    <nav class="navbar has-shadow" style="z-index: 3;">
        <div class="container">
            <div class="navbar">
                <%= link_to 'ダッシュボード', dashboard_path, class: "navbar-item" %>
                <%= link_to 'メッセージの確認', conversations_path, class: "navbar-item", data: { turbolinks: false} %>
                <div class="navbar-item has-dropdown is-hoverable">
                    <a class="navbar-link">ホスト</a>
                    <div class="navbar-dropdown">
                        <%= link_to  "お部屋を新規登録", new_room_path, class: "navbar-item" %>
                        <%= link_to  "登録したお部屋一覧", rooms_path, class: "navbar-item" %>
                        <%= link_to "カレンダー", host_calendar_path, class: "navbar-item" %>
                        <%= link_to "受注予約の管理", your_reservations_path, class: "navbar-item" %>
                        <%= link_to '振込口座の登録', settings_payout_path, class: "navbar-item" %>
                    </div>
                </div>
                <div class="navbar-item has-dropdown is-hoverable">
                    <a class="navbar-link">ゲスト</a>
                    <div class="navbar-dropdown">
                        <%= link_to "ご予約の確認", your_trips_path, class: "navbar-item" %>
                        
                    </div>
                </div>
            </div>
        </div>
    </nav>
<% end %>

<script>
    $(document).ready(function() {
    // navbar burgerアイコンでクリックイベントを確認する
    $(".navbar-burger").click(function() {
        // 「navbar-burger」と「navbar-menu」の両方で「is-active」クラスを切り替える
        $(".navbar-burger").toggleClass("is-active");
        $(".navbar-menu").toggleClass("is-active");
    });
    });
</script>



ブラウザ確認
http://localhost:3000/host_calendar

予約のカレンダー表示
予約のカレンダー表示


YAE C5 CLINIC(札幌美容クリニック)

関連記事(外部サイト)