Blaise
Blaise

Reputation: 89

Rails 6 : Simple calendar + boot strap modal + simple form for

I am building a calendar with the "Simple calendar" gem. I want the user to be able to block some time slots, within a modal. For a better UX, it should pre-fill the date with the selected date. I have tried to put <%= date %> as a value, but it looks like the modal only loads the first date that shows, and doesn't increment then, so it always pre-fill the date with the first day, no matter which day I choose. Any suggestion?

<%= month_calendar events: @bookings+@blocked_times do |date, events| %>
  <%= date %>
  <button id="button" type="button" data-toggle="modal" data-target="#exampleModal" data-selected-date="25-07-2021" >
    <i class="far fa-edit"></i>
  </button>
  <!-- Modal -->
  <%= simple_form_for(@blocked_time, method: :new, url: partner_blocked_times_path(@partner)) do |f| %>
  <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">Block slot</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
        <div class="modal-body">
         <%= f.hidden_field :partner_id, value: params[:id]%>
         <div class= "date-picker">
          <%= f.input :start_time,as: :string %>
        </div>
        <div class= "date-picker">
          <%= f.input :end_time, as: :string%>
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <%= f.button :submit, class: 'btn btn-primary' %>
      </div>
      <% end %>
    </div>
  </div>
</div>

Upvotes: 1

Views: 764

Answers (2)

alexandre-rousseau
alexandre-rousseau

Reputation: 2850

You can do it with Javascript.

Simply define each button with a data-date attribute

<button id="button" type="button" class="new_event_button" data-toggle="modal" data-target="#exampleModal" data-date="<%= date %>">
   <i class="fas fa-calendar-times" data-date="<%= date %>"></i>
</button>

then catch click event and change form according to this value

const startDate = document.getElementById('blocked_time_start_time')
const endDate = document.getElementById('blocked_time_end_time')

var buttons = document.querySelectorAll('button.new_event_button');

Array.from(buttons).forEach(function (button) {
    button.addEventListener('click', function(event) {
      var date =  event.target.getAttribute('data-date');

      startDate.value = date;
      endDate.value = date;
    });
});

Upvotes: 1

Lam Phan
Lam Phan

Reputation: 3811

simple_calendar allow you to set start_date as the first date of ranges of dates will be rendered on calendar, of course the events (BookedTime) should match with that ranges of dates so you have to query bookedtimes from the selected date.

beside that you also need to create a new BlockedTime for each day with start_time and end_time is that day

# model, i assume that your model name Booking
class Booking < ApplicationRecord
  # ...

  def self.calendar(partner_id, start_time)
   @bookings = @partner.bookings # need to filter from start_time
   @blocked_times = BlockedTime.where(partner_id: @partner.id)
                     .where("start_time >= ?", start_time) 
   @bookings+@blocked_times
  end
end
# view
<%= month_calendar(start_date: selected_date,
events: Booking.calendar(partner_id, selected_date)) do |date, events| %>
  <%= date %>
  ...
  <% new_blocked_time = BlockedTime.new(start_time: date, end_time: date) %>
  <%= simple_form_for(new_blocked_time ...
  ...

you could also create a custom-calendars.

Upvotes: 0

Related Questions