255 lines
10 KiB
Text
255 lines
10 KiB
Text
<%= if @delete_days_shifts do %>
|
|
<%= live_modal @socket, Shift73kWeb.ShiftAssignLive.DeleteComponent,
|
|
id: "delete-days-shifts-#{@current_user.id}",
|
|
title: "Delete Shifts From Selected Days",
|
|
delete_days_shifts: @delete_days_shifts,
|
|
current_user: @current_user
|
|
%>
|
|
<% end %>
|
|
|
|
|
|
<h2 class="mb-3 mb-sm-0">
|
|
<%= icon_div @socket, "bi-calendar2-plus", [class: "icon baseline"] %>
|
|
Schedule Shifts
|
|
</h2>
|
|
|
|
<div class="row justify-content-center mt-4">
|
|
<div class="col-12 col-lg-9 col-xl-8 col-xxl-7 d-flex justify-content-center align-items-end">
|
|
|
|
<%= form_for :template_select, "#", [phx_change: "change-selected-template"], fn sts -> %>
|
|
<%= label sts, :template, "Select shift template to assign to dates", class: "form-label" %>
|
|
<%= select sts, :template, @shift_templates,
|
|
value: @shift_template && @shift_template.id || (@shift_template_options |> hd() |> elem(1)),
|
|
class: "form-select"
|
|
%>
|
|
<% end %>
|
|
|
|
<button type="button" class="ms-2 btn btn-primary text-nowrap <%= if @show_template_btn_active, do: "active" %>" id="#templateDetailsBtn" phx-click="toggle-template-details" phx-value-target_id="#templateDetailsCol">
|
|
<%= icon_div @socket, (@show_template_btn_active && "bi-binoculars-fill" || "bi-binoculars"), [class: "icon baseline"] %>
|
|
<span class="d-none d-sm-inline">Details</span>
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<div class="col-12 col-lg-9 col-xl-8 col-xxl-7 <%= @show_template_details && "collapse show" || "collapse" %>" id="#templateDetailsCol" phx-hook="BsCollapse">
|
|
<div class="card mt-4">
|
|
<div class="card-body">
|
|
|
|
<%= form_for @shift_template_changeset, "#", [phx_change: "validate-shift-template"], fn stf -> %>
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-12 col-md-6">
|
|
<%= label stf, :subject, "Subject/Title", class: "form-label" %>
|
|
<div class="inner-addon left-addon mb-3" phx-feedback-for="<%= input_id(stf, :subject) %>">
|
|
<%= icon_div @socket, "bi-tag", [class: "icon is-left text-muted fs-5"] %>
|
|
<%= text_input stf, :subject,
|
|
value: input_value(stf, :subject),
|
|
class: input_class(stf, :subject, "form-control"),
|
|
phx_debounce: 250,
|
|
disabled: @shift_template.id != @custom_shift.id,
|
|
aria_describedby: error_ids(stf, :subject)
|
|
%>
|
|
<%= error_tag stf, :subject %>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6 mb-3">
|
|
<div class="row gx-2 gx-sm-3">
|
|
|
|
<div class="col-6" phx-feedback-for="<%= input_id(stf, :time_start) %>">
|
|
<%= label stf, :time_start, "Start", class: "form-label" %>
|
|
<%= time_input stf, :time_start,
|
|
precision: :minute,
|
|
value: input_value(stf, :time_start),
|
|
class: input_class(stf, :time_start, "form-control"),
|
|
disabled: @shift_template.id != @custom_shift.id,
|
|
aria_describedby: error_ids(stf, :time_start)
|
|
%>
|
|
</div>
|
|
|
|
<div class="col-6" phx-feedback-for="<%= input_id(stf, :time_end) %>">
|
|
<%= label stf, :time_end, "End", class: "form-label" %>
|
|
<%= time_input stf, :time_end,
|
|
precision: :minute,
|
|
value: input_value(stf, :time_end),
|
|
class: input_class(stf, :time_end, "form-control"),
|
|
disabled: @shift_template.id != @custom_shift.id,
|
|
aria_describedby: error_ids(stf, :time_end)
|
|
%>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="valid-feedback d-block text-primary">Shift length: <%= @shift_length %></div>
|
|
|
|
<div class="phx-orphaned-feedback" phx-feedback-for="<%= input_id(stf, :time_start) %>">
|
|
<%= error_tag stf, :time_start %>
|
|
</div>
|
|
<div class="phx-orphaned-feedback" phx-feedback-for="<%= input_id(stf, :time_end) %>">
|
|
<%= error_tag stf, :time_end %>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6">
|
|
<%= label stf, :location, class: "form-label" %>
|
|
<div class="inner-addon left-addon mb-3" phx-feedback-for="<%= input_id(stf, :location) %>">
|
|
<%= icon_div @socket, "bi-geo", [class: "icon is-left text-muted fs-5"] %>
|
|
<%= text_input stf, :location,
|
|
value: input_value(stf, :location),
|
|
class: input_class(stf, :location, "form-control"),
|
|
phx_debounce: 250,
|
|
disabled: @shift_template.id != @custom_shift.id,
|
|
aria_describedby: error_ids(stf, :location)
|
|
%>
|
|
<%= error_tag stf, :location %>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12 col-md-6">
|
|
<%= label stf, :time_zone, class: "form-label" %>
|
|
<div class="inner-addon left-addon mb-3 mb-md-0" phx-feedback-for="<%= input_id(stf, :time_zone) %>">
|
|
<%= icon_div @socket, "bi-map", [class: "icon is-left text-muted fs-5"] %>
|
|
<%= text_input stf, :time_zone,
|
|
value: input_value(stf, :time_zone),
|
|
class: input_class(stf, :time_zone, "form-control"),
|
|
disabled: @shift_template.id != @custom_shift.id,
|
|
phx_debounce: 250,
|
|
list: "tz_list"
|
|
%>
|
|
<datalist id="tz_list">
|
|
<%= for tz_name <- Timex.timezones() do %>
|
|
<option value="<%= tz_name %>"></option>
|
|
<% end %>
|
|
end
|
|
</datalist>
|
|
<%= if @shift_template.id == @custom_shift.id do %>
|
|
<div class="valid-feedback d-block text-primary">Type to search & select from list of known <%= link "IANA tz database", to: "https://en.wikipedia.org/wiki/List_of_tz_database_time_zones", target: "_blank" %> time zones</div>
|
|
<% end %>
|
|
<%= error_tag stf, :time_zone %>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-12">
|
|
<%= label stf, :description, class: "form-label" %>
|
|
<div phx-feedback-for="<%= input_id(stf, :description) %>">
|
|
|
|
<%= textarea stf, :description,
|
|
value: input_value(stf, :description),
|
|
class: input_class(stf, :description, "form-control"),
|
|
disabled: @shift_template.id != @custom_shift.id,
|
|
phx_debounce: 250,
|
|
aria_describedby: error_ids(stf, :description)
|
|
%>
|
|
<%= error_tag stf, :description %>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<% end %>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<%# month navigation %>
|
|
<div class="d-flex justify-content-between align-items-end mt-4">
|
|
<h3 class="text-muted mb-0">
|
|
<%= Timex.format!(@cursor_date, "{Mfull} {YYYY}") %>
|
|
</h3>
|
|
<div>
|
|
<button type="button" phx-click="month-nav" phx-value-month="now" class="btn btn-info text-white" <%= if Map.get(@cursor_date, :month) == Map.get(Timex.today(), :month), do: "disabled" %>>
|
|
<%= icon_div @socket, "bi-asterisk", [class: "icon baseline"] %>
|
|
<span class="d-none d-sm-inline">Today</span>
|
|
</button>
|
|
<button type="button" phx-click="month-nav" phx-value-month="prev" class="btn btn-primary">
|
|
<%= icon_div @socket, "bi-chevron-left", [class: "icon baseline"] %>
|
|
<span class="d-none d-sm-inline">Prev</span>
|
|
</button>
|
|
<button type="button" phx-click="month-nav" phx-value-month="next" class="btn btn-primary">
|
|
<span class="d-none d-sm-inline">Next</span>
|
|
<%= icon_div @socket, "bi-chevron-right", [class: "icon baseline", style: "margin-left:0.125rem;"] %>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<%# calendar month table display %>
|
|
<table class="table table-rounded table-calendar shadow mt-3">
|
|
<thead>
|
|
<tr>
|
|
<%= for {day_name, _i} <- Enum.with_index(@day_names) do %>
|
|
<th>
|
|
<%= day_name %>
|
|
</th>
|
|
<% end %>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%= for week <- @week_rows do %>
|
|
<tr>
|
|
<%= for day <- week do %>
|
|
<td class="<%= day_color(day, @current_date, @cursor_date, @selected_days) %>" phx-click="select-day" phx-value-day="<%= day %>">
|
|
|
|
<%= Timex.format!(day, "{0D}") %><%= if day.month != @cursor_date.month, do: "-#{Timex.format!(day, "{Mshort}")}" %>
|
|
|
|
<% day_shifts = Enum.filter(@known_shifts, fn s -> s.date == day end) %>
|
|
<% shifts_to_show = shifts_to_show(day_shifts) %>
|
|
|
|
<%= for shift <- shifts_to_show do %>
|
|
<span class="badge bg-primary text-start d-block">
|
|
<span>
|
|
<%= shift.time_start |> Timex.format!("{h12}:{m}{am}") |> String.trim_trailing("m") %>
|
|
<%= shift.subject %>
|
|
</span>
|
|
</span>
|
|
<% end %>
|
|
|
|
<%= if length(day_shifts) > 2 do %>
|
|
<span class="badge bg-primary text-start d-block"><span><%= length(day_shifts) - 1 %> more…</span></span>
|
|
<% end %>
|
|
|
|
|
|
</td>
|
|
<% end %>
|
|
</tr>
|
|
<% end %>
|
|
</tbody>
|
|
</table>
|
|
|
|
|
|
<div class="row justify-content-center justify-content-lg-end my-5">
|
|
<div class="col-12 col-sm-10 col-md-8 col-lg-auto d-flex flex-column-reverse flex-lg-row">
|
|
|
|
<button class="btn btn-outline-danger mb-1 mb-lg-0 me-lg-1" phx-click="delete-days-shifts" <%= if Enum.empty?(@selected_days), do: "disabled" %>>
|
|
<%= icon_div @socket, "bi-trash", [class: "icon baseline"] %>
|
|
Delete shifts from selected days
|
|
</button>
|
|
|
|
<button class="btn btn-outline-dark mb-1 mb-lg-0 me-lg-1" phx-click="clear-days" <%= if Enum.empty?(@selected_days), do: "disabled" %>>
|
|
<%= icon_div @socket, "bi-eraser", [class: "icon baseline"] %>
|
|
De-select all selected
|
|
</button>
|
|
|
|
<button class="btn btn-primary mb-1 mb-lg-0" phx-click="save-days" <%= if (!@shift_template_changeset.valid? || Enum.empty?(@selected_days)), do: "disabled" %>>
|
|
<%= icon_div @socket, "bi-save", [class: "icon baseline"] %>
|
|
Assign shifts to selected days
|
|
</button>
|
|
|
|
</div>
|
|
</div>
|