updated template management, including time_input: required fix

This commit is contained in:
Adam Piontek 2022-08-14 09:49:34 -04:00
parent 6a5d2346ff
commit ada166fb41
7 changed files with 165 additions and 161 deletions

View file

@ -0,0 +1,23 @@
<div>
<div class="modal-body">
Are you sure you want to delete "<%= @delete_shift_template.subject %>
(<%= format_shift_time(@delete_shift_template.time_start) %>
&mdash;
<%= format_shift_time(@delete_shift_template.time_end) %>)"?
</div>
<div class="modal-footer">
<%= link "Cancel", to: "#", class: "btn btn-outline-dark", phx_click: "hide", phx_target: "##{@modal_id}" %>
<%= link "Confirm Delete", to: "#",
class: "btn btn-danger",
phx_click: "confirm",
phx_target: @myself,
phx_value_id: @delete_shift_template.id,
phx_value_subject: @delete_shift_template.subject %>
</div>
</div>

View file

@ -1,19 +0,0 @@
<div class="modal-body">
Are you sure you want to delete "<%= @delete_shift_template.subject %>
(<%= format_shift_time(@delete_shift_template.time_start) %>
&mdash;
<%= format_shift_time(@delete_shift_template.time_end) %>)"?
</div>
<div class="modal-footer">
<%= link "Cancel", to: "#", class: "btn btn-outline-dark", phx_click: "hide", phx_target: "##{@modal_id}" %>
<%= link "Confirm Delete", to: "#",
class: "btn btn-danger",
phx_click: "confirm",
phx_target: @myself,
phx_value_id: @delete_shift_template.id,
phx_value_subject: @delete_shift_template.subject %>
</div>

View file

@ -0,0 +1,123 @@
<div>
<%= form_for @changeset, "#", [
id: "shift_template-form",
phx_target: @myself,
phx_change: "validate",
phx_submit: "save"
], fn f -> %>
<div class="modal-body">
<%= label f, :subject, "Subject/Title", class: "form-label" %>
<div class="inner-addon left-addon mb-3" phx-feedback-for={input_id(f, :subject)}>
<i class="bi bi-tag icon is-left text-muted fs-5"></i>
<%= text_input f, :subject,
value: input_value(f, :subject),
class: input_class(f, :subject, "form-control"),
autofocus: true,
phx_debounce: 250,
aria_describedby: error_ids(f, :subject)
%>
<%= error_tag f, :subject %>
</div>
<div class="row gx-2 gx-sm-3">
<div class="col-6" phx-feedback-for={input_id(f, :time_start)}>
<%= label f, :time_start, "Start", class: "form-label" %>
<%= time_input f, :time_start,
precision: :minute,
value: input_value(f, :time_start),
class: input_class(f, :time_start, "form-control"),
aria_describedby: error_ids(f, :time_start),
required: true
%>
</div>
<div class="col-6" phx-feedback-for={input_id(f, :time_end)}>
<%= label f, :time_end, "End", class: "form-label" %>
<%= time_input f, :time_end,
precision: :minute,
value: input_value(f, :time_end),
class: input_class(f, :time_end, "form-control"),
aria_describedby: error_ids(f, :time_end),
required: true
%>
</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(f, :time_start)}>
<%= error_tag f, :time_start %>
</div>
<div class="phx-orphaned-feedback" phx-feedback-for={input_id(f, :time_end)}>
<%= error_tag f, :time_end %>
</div>
<%= label f, :location, class: "form-label mt-3" %>
<div class="inner-addon left-addon mb-3" phx-feedback-for={input_id(f, :location)}>
<i class="bi bi-geo icon is-left text-muted fs-5"></i>
<%= text_input f, :location,
value: input_value(f, :location),
class: input_class(f, :location, "form-control"),
phx_debounce: 250,
aria_describedby: error_ids(f, :location)
%>
<%= error_tag f, :location %>
</div>
<%= label f, :description, class: "form-label" %>
<div class="mb-3" phx-feedback-for={input_id(f, :description)}>
<%= textarea f, :description,
value: input_value(f, :description),
class: input_class(f, :description, "form-control"),
phx_debounce: 250,
aria_describedby: error_ids(f, :description)
%>
<%= error_tag f, :description %>
</div>
<%= label f, :time_zone, class: "form-label" %>
<div class="inner-addon left-addon mb-3" phx-feedback-for={input_id(f, :time_zone)}>
<i class="bi bi-map icon is-left text-muted fs-5"></i>
<%= text_input f, :time_zone,
value: input_value(f, :time_zone),
class: input_class(f, :time_zone, "form-control"),
phx_debounce: 250,
list: "tz_list"
%>
<datalist id="tz_list">
<%= for tz_name <- Tzdata.zone_list() do %>
<option value={tz_name}></option>
<% end %>
</datalist>
<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>
<%= error_tag f, :time_zone %>
</div>
</div>
<div class="modal-footer">
<%= link "Cancel", to: "#", class: "btn btn-outline-dark", phx_click: "hide", phx_target: "##{@modal_id}" %>
<%= submit "Save",
class: "btn btn-primary ",
disabled: !@changeset.valid?,
aria_disabled: !@changeset.valid? && "true" || false,
phx_disable_with: "Saving..."
%>
</div>
<% end %>
</div>

View file

@ -1,116 +0,0 @@
<%= f = form_for @changeset, "#",
id: "shift_template-form",
phx_target: @myself,
phx_change: "validate",
phx_submit: "save" %>
<div class="modal-body">
<%= label f, :subject, "Subject/Title", class: "form-label" %>
<div class="inner-addon left-addon mb-3" phx-feedback-for="<%= input_id(f, :subject) %>">
<%= icon_div @socket, "bi-tag", [class: "icon is-left text-muted fs-5"] %>
<%= text_input f, :subject,
value: input_value(f, :subject),
class: input_class(f, :subject, "form-control"),
autofocus: true,
phx_debounce: 250,
aria_describedby: error_ids(f, :subject)
%>
<%= error_tag f, :subject %>
</div>
<div class="row gx-2 gx-sm-3">
<div class="col-6" phx-feedback-for="<%= input_id(f, :time_start) %>">
<%= label f, :time_start, "Start", class: "form-label" %>
<%= time_input f, :time_start,
precision: :minute,
value: input_value(f, :time_start),
class: input_class(f, :time_start, "form-control"),
aria_describedby: error_ids(f, :time_start)
%>
</div>
<div class="col-6" phx-feedback-for="<%= input_id(f, :time_end) %>">
<%= label f, :time_end, "End", class: "form-label" %>
<%= time_input f, :time_end,
precision: :minute,
value: input_value(f, :time_end),
class: input_class(f, :time_end, "form-control"),
aria_describedby: error_ids(f, :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(f, :time_start) %>">
<%= error_tag f, :time_start %>
</div>
<div class="phx-orphaned-feedback" phx-feedback-for="<%= input_id(f, :time_end) %>">
<%= error_tag f, :time_end %>
</div>
<%= label f, :location, class: "form-label mt-3" %>
<div class="inner-addon left-addon mb-3" phx-feedback-for="<%= input_id(f, :location) %>">
<%= icon_div @socket, "bi-geo", [class: "icon is-left text-muted fs-5"] %>
<%= text_input f, :location,
value: input_value(f, :location),
class: input_class(f, :location, "form-control"),
phx_debounce: 250,
aria_describedby: error_ids(f, :location)
%>
<%= error_tag f, :location %>
</div>
<%= label f, :description, class: "form-label" %>
<div class="mb-3" phx-feedback-for="<%= input_id(f, :description) %>">
<%= textarea f, :description,
value: input_value(f, :description),
class: input_class(f, :description, "form-control"),
phx_debounce: 250,
aria_describedby: error_ids(f, :description)
%>
<%= error_tag f, :description %>
</div>
<%= label f, :time_zone, class: "form-label" %>
<div class="inner-addon left-addon mb-3" phx-feedback-for="<%= input_id(f, :time_zone) %>">
<%= icon_div @socket, "bi-map", [class: "icon is-left text-muted fs-5"] %>
<%= text_input f, :time_zone,
value: input_value(f, :time_zone),
class: input_class(f, :time_zone, "form-control"),
phx_debounce: 250,
list: "tz_list"
%>
<datalist id="tz_list">
<%= for tz_name <- Tzdata.zone_list() do %>
<option value="<%= tz_name %>"></option>
<% end %>
</datalist>
<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>
<%= error_tag f, :time_zone %>
</div>
</div>
<div class="modal-footer">
<%= link "Cancel", to: "#", class: "btn btn-outline-dark", phx_click: "hide", phx_target: "##{@modal_id}" %>
<%= submit "Save",
class: "btn btn-primary ",
disabled: !@changeset.valid?,
aria_disabled: !@changeset.valid? && "true" || false,
phx_disable_with: "Saving..."
%>
</div>
</form>

View file

@ -20,12 +20,10 @@
<div class="d-flex flex-column flex-sm-row justify-content-between align-items-start align-items-sm-center">
<h2 class="mb-3 mb-sm-0">
<%= icon_div @socket, "bi-clock-history", [class: "icon baseline"] %>
My Shift Templates
<i class="bi bi-clock-history me-1"></i> My Shift Templates
</h2>
<%= live_patch to: Routes.shift_template_index_path(@socket, :new), class: "btn btn-primary" do %>
<%= icon_div @socket, "bi-plus-circle-dotted", [class: "icon baseline"] %>
New Shift Template
<i class="bi bi-plus-circle-dotted me-1"></i> New Shift Template
<% end %>
</div>
@ -39,13 +37,13 @@
<div class="card mt-4">
<h5 class="card-header d-flex justify-content-between align-items-center">
<span class="visually-hidden">Subject:</span>
<%= icon_div @socket, "bi-tag", [class: "icon baseline me-1"] %>
<i class="bi bi-tag me-1"></i>
<div class="w-100"><%= template.subject %></div>
<%= if template.id == @current_user.fave_shift_template_id do %>
<%= icon_div @socket, "bi-star-fill", [class: "icon baseline text-primary align-self-start ms-2"], [role: "img", aria_hidden: false, aria_label: "Unset as favorite", phx_click: "unset-user-fave-shift-template", class: "cursor-pointer"] %>
<% else %>
<%= icon_div @socket, "bi-star", [class: "icon baseline text-primary align-self-start ms-2"], [role: "img", aria_hidden: false, aria_label: "Set as favorite", phx_click: "set-user-fave-shift-template", phx_value_id: template.id, class: "cursor-pointer"] %>
<% end %>
<% fav_icon_data = if template.id == @current_user.fave_shift_template_id, do:
{"bi-star-fill", "Unset as favorite", "unset-user-fave-shift-template"}, else:
{"bi-star", "Set as favorite", "set-user-fave-shift-template"}
%>
<i class={"bi #{elem(fav_icon_data, 0)} text-primary align-self-start ms-2 cursor-pointer"} role="img" aria-hidden="false" aria-label={elem(fav_icon_data, 1)} phx-click={elem(fav_icon_data, 2)} phx-value-id={template.id}></i>
</h5>
<div class="card-body">
@ -53,7 +51,7 @@
<tbody>
<tr>
<th scope="row" class="text-end">
<%= icon_div @socket, "bi-hourglass", [class: "icon baseline text-muted"] %>
<i class="bi bi-hourglass text-muted"></i>
<span class="visually-hidden">Hours:</span>
</th>
<td>
@ -70,7 +68,7 @@
<tr>
<th scope="row" class="text-end">
<%= icon_div @socket, "bi-geo", [class: "icon baseline text-muted"] %>
<i class="bi bi-geo text-muted"></i>
<span class="visually-hidden">Location:</span>
</th>
<td>
@ -83,7 +81,7 @@
</tr>
<tr>
<th scope="row" class="text-end">
<%= icon_div @socket, "bi-justify-left", [class: "icon baseline text-muted"] %>
<i class="bi bi-justify-left text-muted"></i>
<span class="visually-hidden">Description:</span>
</th>
<td>
@ -99,24 +97,19 @@
<%= if Roles.can?(@current_user, template, :edit) do %>
<%= live_patch to: Routes.shift_template_index_path(@socket, :edit, template), class: "btn btn-primary btn-sm text-nowrap" do %>
<%= icon_div @socket, "bi-pencil", [class: "icon baseline"] %>
Edit
<i class="bi bi-pencil me-1"></i> Edit
<% end %>
<% end %>
<%= if Roles.can?(@current_user, template, :clone) do %>
<%= live_patch to: Routes.shift_template_index_path(@socket, :clone, template), class: "btn btn-outline-primary btn-sm text-nowrap" do %>
<%= icon_div @socket, "bi-clipboard-plus", [class: "icon baseline"] %>
Clone
<i class="bi bi-clipboard-plus me-1"></i> Clone
<% end %>
<% end %>
<%#= button "" %>
<%= if Roles.can?(@current_user, template, :delete) do %>
<button class="btn btn-outline-danger btn-sm text-nowrap" phx-click="delete-modal" phx-value-id="<%= template.id %>">
<%= icon_div @socket, "bi-trash", [class: "icon baseline"] %>
Delete
<button class="btn btn-outline-danger btn-sm text-nowrap" phx-click="delete-modal" phx-value-id={template.id}>
<i class="bi bi-trash me-1"></i> Delete
</button>
<% end %>

View file

@ -1,10 +1,10 @@
<li class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle" id="navbarDropdownUserMenu" data-bs-toggle="dropdown" aria-expanded="false">
<a href="#" class="nav-link dropdown-toggle" id="navbarDropdownNoUserMenu" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-person-circle me-1"></i> Hello?
</a>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownUserMenu">
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownNoUserMenu">
<li>
<%= link nav_link_opts(@conn, to: Routes.user_registration_path(@conn, :new), class: "dropdown-item") do %>

View file

@ -1,10 +1,10 @@
<li class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle" id="navbarDropdownUserMenu" data-bs-toggle="dropdown" aria-expanded="false">
<a href="#" class="nav-link dropdown-toggle" id="navbarDropdownShiftsMenu" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-calendar2 me-1"></i> Shifts
</a>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownUserMenu">
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownShiftsMenu">
<li>
<%= link nav_link_opts(@conn, to: Routes.shift_assign_index_path(@conn, :index), class: "dropdown-item") do %>