diff --git a/assets/css/_phx-liveview.scss b/assets/css/_phx-liveview.scss index 702bdd9f..2c7087ab 100644 --- a/assets/css/_phx-liveview.scss +++ b/assets/css/_phx-liveview.scss @@ -2,9 +2,13 @@ /* hides the feedback field help if liveview indicates field not touched yet */ .phx-no-feedback.invalid-feedback, -.phx-no-feedback .invalid-feedback { +.phx-no-feedback .invalid-feedback, +.phx-orphaned-feedback.phx-no-feedback .invalid-feedback { display: none; } +.phx-orphaned-feedback .invalid-feedback { + display: block !important; +} /* sets default bootstrap form-control styles if field not touched yet */ .phx-no-feedback .form-control.is-valid, diff --git a/assets/js/app.js b/assets/js/app.js index a376add3..72edd2eb 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -34,12 +34,14 @@ import "../node_modules/bootstrap-icons/icons/arrow-repeat.svg"; // resend confi import "../node_modules/@mdi/svg/svg/head-question-outline.svg"; // forgot password import "../node_modules/bootstrap-icons/icons/people.svg"; // users management // calendar/event icons -import "../node_modules/bootstrap-icons/icons/calendar3-event.svg"; // brand -import "../node_modules/bootstrap-icons/icons/clock-history.svg"; // brand -import "../node_modules/bootstrap-icons/icons/hourglass.svg"; // brand -import "../node_modules/bootstrap-icons/icons/geo.svg"; // brand -import "../node_modules/bootstrap-icons/icons/justify-left.svg"; // brand -import "../node_modules/bootstrap-icons/icons/plus-circle-dotted.svg"; // brand +import "../node_modules/bootstrap-icons/icons/calendar3-event.svg"; +import "../node_modules/bootstrap-icons/icons/clock-history.svg"; // shift template +import "../node_modules/bootstrap-icons/icons/tag.svg"; +import "../node_modules/bootstrap-icons/icons/hourglass.svg"; +import "../node_modules/bootstrap-icons/icons/map.svg"; +import "../node_modules/bootstrap-icons/icons/geo.svg"; +import "../node_modules/bootstrap-icons/icons/justify-left.svg"; +import "../node_modules/bootstrap-icons/icons/plus-circle-dotted.svg"; // webpack automatically bundles all modules in your // entry points. Those entry points can be configured diff --git a/lib/shift73k/shift_templates.ex b/lib/shift73k/shift_templates.ex index b5f7139a..9520613c 100644 --- a/lib/shift73k/shift_templates.ex +++ b/lib/shift73k/shift_templates.ex @@ -22,8 +22,8 @@ defmodule Shift73k.ShiftTemplates do end def list_shift_templates_by_user_id(user_id) do - from(s in ShiftTemplate, where: s.user_id == ^user_id) - |> Repo.all() + q = from s in ShiftTemplate, where: s.user_id == ^user_id, order_by: s.subject + Repo.all(q) end @doc """ diff --git a/lib/shift73k/shift_templates/shift_template.ex b/lib/shift73k/shift_templates/shift_template.ex index 6dc0975c..f5c6c2ca 100644 --- a/lib/shift73k/shift_templates/shift_template.ex +++ b/lib/shift73k/shift_templates/shift_template.ex @@ -8,13 +8,12 @@ defmodule Shift73k.ShiftTemplates.ShiftTemplate do @primary_key {:id, :binary_id, autogenerate: true} @foreign_key_type :binary_id schema "shift_templates" do - field :subject, :string, default: "My Work Shift" + field :subject, :string field :description, :string field :location, :string - field :timezone, :string, default: @time_zone - field :start_time, :time, default: ~T[09:00:00] - field :length_hours, :integer, default: 8 - field :length_minutes, :integer, default: 0 + field :time_zone, :string, default: @time_zone + field :time_start, :time, default: ~T[09:00:00] + field :time_end, :time, default: ~T[17:00:00] belongs_to(:user, Shift73k.Accounts.User) @@ -26,22 +25,61 @@ defmodule Shift73k.ShiftTemplates.ShiftTemplate do shift_template |> cast(attrs, [ :subject, - :description, :location, - :timezone, - :start_time, - :length_hours, - :length_minutes, + :description, + :time_zone, + :time_start, + :time_end, :user_id ]) |> validate_required([ :subject, - :timezone, - :start_time, - :length_hours + :time_zone, + :time_start, + :time_end ]) - |> validate_number(:length_hours, greater_than_or_equal_to: 0, less_than_or_equal_to: 24) - |> validate_number(:length_minutes, greater_than_or_equal_to: 0, less_than: 60) - |> validate_inclusion(:timezone, Tzdata.zone_list()) + |> validate_length(:subject, count: :codepoints, max: 280) + |> validate_length(:location, count: :codepoints, max: 280) + |> validate_change(:time_end, fn :time_end, time_end -> + shift_length = shift_length(get_time_start(attrs), time_end) + + cond do + shift_length == 0 -> + [time_end: "end time cannot equal start time"] + + shift_length >= 16 * 3600 -> + [time_end: "you don't want to work 16 or more hours!"] + + true -> + [] + end + end) + |> validate_inclusion(:time_zone, Tzdata.zone_list()) + end + + defp get_time_start(%{"time_start" => time_start}), do: time_start + defp get_time_start(%{time_start: time_start}), do: time_start + defp get_time_start(_), do: nil + + def shift_length(time_start, time_end) do + cond do + time_end > time_start -> + Time.diff(time_end, time_start) + + time_start > time_end -> + len1 = Time.diff(~T[23:59:59], time_start) + 1 + len2 = Time.diff(time_end, ~T[00:00:00]) + len1 + len2 + + true -> + 0 + end + end + + def shift_length_h_m_tuple(time_start, time_end) do + shift_length_seconds = shift_length(time_start, time_end) + h = shift_length_seconds |> Integer.floor_div(3600) + m = shift_length_seconds |> rem(3600) |> Integer.floor_div(60) + {h, m} end end diff --git a/lib/shift73k_web/live/shift_template_live/delete_component.html.leex b/lib/shift73k_web/live/shift_template_live/delete_component.html.leex index 8047f7c8..ad6435bd 100644 --- a/lib/shift73k_web/live/shift_template_live/delete_component.html.leex +++ b/lib/shift73k_web/live/shift_template_live/delete_component.html.leex @@ -1,13 +1,9 @@