[31]jQuery日付ピッカー<< [ホームに戻る] >> [33]予約確認ページ
「app\controllers\rooms_controller.rb」ファイルを編集します。
1.記述追加 app\controllers\rooms_controller.rb(71行目)
# 予約 開始日のAJAX def preload today = Date.today reservations = @room.reservations.where("start_date >= ? OR end_date >= ?", today, today) render json: reservations end # 予約 終了日のAJAX def preview start_date = Date.parse(params[:start_date]) end_date = Date.parse(params[:end_date]) output = { conflict: is_conflict(start_date, end_date, @room) } render json: output end
2.記述追加 app\controllers\rooms_controller.rb(105行目)
# 予約 プライベートメソッド def is_conflict(start_date, end_date, room) check = room.reservations.where("? < start_date AND end_date < ?", start_date, end_date) check.size > 0? true : false end
app\controllers\rooms_controller.rb
class RoomsController < ApplicationController protect_from_forgery except: [:upload_photo] before_action :set_room, except: [:index, :new, :create] before_action :authenticate_user!, except: [:show] before_action :is_authorised, only: [:listing, :pricing, :description, :photo_upload, :amenities, :location, :update] def index @rooms = current_user.rooms end def new @room = current_user.rooms.build end def create @room = current_user.rooms.build(room_params) if @room.save redirect_to listing_room_path(@room), notice: "保存しました。" else flash[:alert] = "問題が発生しました。" render :new end end def show @photos = @room.photos end def listing end def pricing end def description end def photo_upload end def amenities end def location end def update new_params = room_params new_params = room_params.merge(active: true) if is_ready_room if @room.update(new_params) flash[:notice] = "保存しました。" else flash[:alert] = "問題が発生しました。" end redirect_back(fallback_location: request.referer) end def upload_photo @room.photos.attach(params[:file]) render json: { success: true } end def delete_photo @image = ActiveStorage::Attachment.find(params[:photo_id]) @image.purge redirect_to photo_upload_room_path(@room) end # 予約 開始日のAJAX def preload today = Date.today reservations = @room.reservations.where("start_date >= ? OR end_date >= ?", today, today) render json: reservations end # 予約 終了日のAJAX def preview start_date = Date.parse(params[:start_date]) end_date = Date.parse(params[:end_date]) output = { conflict: is_conflict(start_date, end_date, @room) } render json: output end private def set_room @room = Room.find(params[:id]) end def room_params params.require(:room).permit(:home_type, :room_type, :accommodate, :bed_room, :bath_room, :listing_name, :summary, :address, :is_tv, :is_kitchen, :is_air, :is_heating, :is_internet, :price, :active, :description) end def is_authorised redirect_to root_path, alert: "権限がありません。" unless current_user.id == @room.user_id end def is_ready_room !@room.active && !@room.price.blank? && !@room.listing_name.blank? && !@room.photos.blank? && !@room.address.blank? end # 予約 プライベートメソッド def is_conflict(start_date, end_date, room) check = room.reservations.where("? < start_date AND end_date < ?", start_date, end_date) check.size > 0? true : false end end
記述追加 config\routes.rb
「get 'preload'」の記述追加(25行目)と「get 'preview'」の記述追加(26行目)
Rails.application.routes.draw do # ルートを app\views\pages\home.html.erb に設定 root 'pages#home' devise_for :users, path: '', path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'}, controllers: {registrations: 'registrations'} get 'pages/home' get '/dashboard', to: 'users#dashboard' get '/users/:id', to: 'users#show', as: 'user' post '/users/edit', to: 'users#update' 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 # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html end
記述更新 app\views\reservations\_form.html.erb
コードをコピーして内容を置き換えてください。
<div class="card"> <header class="card-header"> <p class="card-header-title"> <span><i class="fas fa-chess-king" style="color: #ffb400"></i></span> <span class="pull-right">1泊 <%= number_to_currency(@room.price) %></span> </p> </header> <div class="card-content"> <div class="content"> <%= form_for([@room, @room.reservations.new]) do |f| %> <div class="field is-horizontal"> <div class="field-body"> <div class="field"> <p class="control is-expanded has-icons-left"> <%= f.text_field :start_date, readonly: true, placeholder: "イン", class: "input is-primary is-rounded" %> <span class="icon is-small is-left"> <i class="far fa-calendar-alt"></i> </span> </p> </div> <div class="field"> <p class="control is-expanded has-icons-left has-icons-right"> <%= f.text_field :end_date, readonly: true, placeholder: "アウト", class: "input is-primary is-rounded" %> <span class="icon is-small is-left"> <i class="far fa-calendar-alt"></i> </span> </p> </div> </div> </div> <h4 class="message-alert text-center"><span id="message"></span></h4> <div id="preview" style="display: none"> <table class="reservation-table"> <tbody> <tr> <td>宿泊費用</td> <td class="text-right", style="white-space: nowrap"><%= number_to_currency(@room.price) %></td> </tr> <tr> <td>宿泊日数</td> <td class="text-right"><span id="reservation_nights"></span>泊</td> </tr> <tr> <td class="total">合計金額</td> <td class="text-right", style="white-space: nowrap"><span id="reservation_total"></span>円</td> </tr> </tbody> </table> </div> <%= f.submit "予約する", class: "button is-danger is-fullwidth m-t-10 m-b-10" %> <% end %> </div> </div> </div> <script> function checkDate(date) { dmy = date.getDate() + "-" + (date.getMonth() + 1) + "-" + date.getFullYear(); return [$.inArray(dmy, unavailableDates) == -1]; } $(function() { unavailableDates = []; $.ajax({ url: '<%= preload_room_path(@room) %>', dateTyp: 'json', success: function(data) { $.each(data, function(arrID, arrValue) { for(var d = new Date(arrValue.start_date); d <= new Date(arrValue.end_date); d.setDate(d.getDate() + 1)) { unavailableDates.push($.datepicker.formatDate('d-m-yy', d)); } }); $('#reservation_start_date').datepicker({ dateFormat: 'dd-mm-yy', //今日から3ヶ月先まで予約可能 minDate: 0, maxDate: '3m', beforeShowDay: checkDate, onSelect: function(selected) { $('#reservation_end_date').datepicker("option", "minDate", selected); $('#reservation_end_date').attr("disabled", false); var start_date = $('#reservation_start_date').datepicker('getDate'); var end_date = $('#reservation_end_date').datepicker('getDate'); //2日選択すると1泊になる var nights = (end_date - start_date)/1000/60/60/24; var input = { 'start_date': start_date, 'end_date': end_date } $.ajax({ url: '<%= preview_room_path(@room) %>', data: input, success: function(data) { if(data.conflict) { $('#message').text("この日付はご利用できません。"); $('#preview').hide(); $('#btn_book').attr('disabled', true); } else { $('#message').text(""); $('#preview').show(); $('#btn_book').attr('disabled', false); var total = nights * <%= @room.price %> $('#reservation_nights').text(nights); $('#reservation_total').text(total); } } }); } }); $('#reservation_end_date').datepicker({ dateFormat: 'dd-mm-yy', //今日から3ヶ月先まで予約可能 minDate: 0, maxDate: '3m', beforeShowDay: checkDate, onSelect: function(selected) { $('#reservation_start_date').datepicker("option", "maxDate", selected); var start_date = $('#reservation_start_date').datepicker('getDate'); var end_date = $('#reservation_end_date').datepicker('getDate'); var nights = (end_date - start_date)/1000/60/60/24; var input = { 'start_date': start_date, 'end_date': end_date } $.ajax({ url: '<%= preview_room_path(@room) %>', data: input, success: function(data) { if(data.conflict) { $('#message').text("この日付ではご予約できません。"); $('#preview').hide(); $('#btn_book').attr('disabled', true); } else { $('#message').text(""); $('#preview').show(); $('#btn_book').attr('disabled', false); var total = nights * <%= @room.price %> $('#reservation_nights').text(nights); $('#reservation_total').text(total); } } }); } }); } }); }); </script>
ブラウザ確認
ログインしないと予約カレンダーが出ないようになっています。
実際に予約できるか確認してください。
http://localhost:3000/rooms/1
↓↓クリックして頂けると励みになります。