I'm trying to build a staff rostering/scheduling app in Rails 5. The idea is for each staff member to have a user account where they can log in to enter the days they are available for work, then for the boss to book shifts based on availability. A good example of such a site is https://www.findmyshift.com/.
The main part of the site would be a calendar, with each user having their own instance of the calendar. Each user would have their own row in the calendar table, with each row displaying the days of the week.
I've looked at a few plugins, including FullCalendar and dhtmlxScheduler, but decided to try doing it from scratch. I've managed to build a basic calendar based on this Railscast, which works just fine. The 3 main parts of this are as follows:
home_controller.rb:
class HomeController < ApplicationController
def index
@date = params[:date] ? Date.parse(params[:date]) : Date.today
end
end
index.html.erb:
<div id="roster">
<h2 id="month">
<%= link_to "<", date: @date.prev_week %>
<%= @date.strftime("%B %Y") %>
<%= link_to ">", date: @date.next_week %>
</h2>
<%= calendar @date do |date| %>
<%= date.day %>
<% end %>
</div>
calendar_helper.rb:
module CalendarHelper
def calendar(date = Date.today, &block)
Calendar.new(self, date, block).table
end
class Calendar < Struct.new(:view, :date, :callback)
HEADER = %w[Monday Tuesday Wednesday Thursday Friday Saturday Sunday]
START_DAY = :monday
delegate :content_tag, to: :view
def table
content_tag :table, class: "calendar" do
header + week_rows
end
end
def header
content_tag :tr do
HEADER.map { |day| content_tag :th, day }.join.html_safe
end
end
def week_rows
weeks.map do |week|
content_tag :tr do
week.map { |day| day_cell(day) }.join.html_safe
end
end.join.html_safe
end
def day_cell(day)
content_tag :td, view.capture(day, &callback), class: day_classes(day)
end
def day_classes(day)
classes = []
classes << "today" if day == Date.today
classes << "notmonth" if day.month != date.month
classes.empty? ? nil : classes.join(" ")
end
def weeks
first = date.beginning_of_week(START_DAY)
last = date.end_of_week(START_DAY)
(first..last).to_a.in_groups_of(7)
end
end
end
Again, all of this works fine. It displays 1 week row, with arrows to move backwards and forwards in time. What I would like is to have 1 week row PER USER. I'm aware that I could simply render a calendar for each user in my view template, but this would include the whole thing - header, week selector and week row. I just want 1 header + week selector, then a week row for each user as part of the same table.
My guess is that I should iterate over each user somewhere in calendar_helper.rb, adding a row per user, but I'm not too sure how to proceed. Any help would be much appreciated :)
EDIT:
The first image is what I have now, the second image is what I would like to achieve - multiple instances of the calendar week row, rendered dynamically based on number of users.