2

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.

enter image description here

enter image description here

  • i wanted to ask, do you have an image for this functionality it would make everything more clear. So basically the user will be able to see a calendar with many week rows for each user? he will see also the rows for the other users in the database? Probably you never got answers because it is hard to understand what you want to accomplish without an image... – Fabrizio Bertoglio Mar 09 '17 at 07:34
  • @FabrizioBertoglio Yes images would certainly help :) I've edited the question to include them. For now, each user would be able to see all rows, but once I have the calendar functionality working, I will look into permissions so that only the employer would have this ability. – dividedunit Mar 09 '17 at 23:21
  • This is a very bad solution, did you think of doing a query of all users, `@users = User.all` and using it to loop that row multiple times instead of just showing it once. In your view `<%= @users.each do |user| %> <% end %>` You may need some fixing, but It will help me knowing why this is not possible – Fabrizio Bertoglio Mar 10 '17 at 09:38

0 Answers0