Belay Board App Part 4: Calendar
Published: 2023-11-15 00:16:29

## Add bootstrap
```html
<!--/workspaces/Belay-Board/app/views/layouts/application.html.erb-->
<!DOCTYPE html>
<html>
  <head>
    <title>Rails Template</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <%= javascript_importmap_tags %>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  </head>

  <body>
    <%= yield %>
  </body>
</html>
```

## Add the gem
Run:
`bundle add simple_calendar`

## Add Calendar to availabilities index page
- Each day is a card and each availability is a nested card.
- When a day has no availabilities, there is a button to create a new availability.
- Check if the current user is the one who created the availability.
- If the condition is true, show an "Edit" button linked to the edit path of the availability.
- If the condition is false, display the "Climb with {username}" request button. 

```html
<p style="color: green"><%= notice %></p>
<div class="container text-center" style="padding-left: 20px; padding-right: 20px;">
  <h1>Climb Times</h1>
  <div><%= link_to "New availability", new_availability_path, class: "btn btn-primary btn-sm" %></div>
  <%= month_calendar events: @availabilities do |date, availabilities| %>
    <div class="card mb-3">
      <div class="card-header">
        <%= date.strftime("%m/%d/%Y") %>
      </div>
      <div class="card-body p-0">
        <% if availabilities.any? %>
          <% availabilities.each do |availability| %>
            <div class="border-bottom">
              <div class="p-2">
                <%= render availability %>
                <% if availability.user == current_user %>
                  <%= link_to "Edit availability", edit_availability_path(availability), class: "btn btn-info btn-sm d-block mt-2" %>
                <% else %>
                  <%= link_to "Climb with #{availability.user.username}", new_request_path(availability_id: availability.id), class: "btn btn-primary btn-sm d-block mt-2" %>
                <% end %>
              </div>
            </div>
          <% end %>
        <% else %>
          <p class="p-2">
            <%= link_to "New availability", new_availability_path(date: date.to_date), class: "btn btn-primary btn-sm d-block mt-2" %>
          </p>
        <% end %>
      </div>
    </div>
  <% end %>
</div>
```

## Sort Availabilities by start time
```rb
class AvailabilitiesController < ApplicationController
  before_action :set_availability, only: %i[ show edit update destroy ]

  # GET /availabilities or /availabilities.json
  def index
    @availabilities = Availability.order(:start_time)
  end
  #...
```

## Pre-populate new availability
When the "New availability" button is clicked, the link will include the date as a query parameter, and the new action in `AvailabilitiesController` will use this parameter to pre-populate the `start_time` and `end_time` field.

```rb
  def new
   @availability = current_user.availabilities.build
   @availability.start_time = params[:date] if params[:date].present?
   @availability.end_time = params[:date] if params[:date].present?
  end
```

### New availability button
```html
<%= link_to "New availability", new_availability_path(date: date.to_date), class: "btn btn-primary btn-sm d-block mt-2" %>
```

## Next Steps
Now that I have a calendar that displays climbing availabilities I want to make it more interactive with AJAX. I will also add a button to accept or reject an availability request right from the calendar.