From 8957f2d1dd85daffe2588db628108468a651a724 Mon Sep 17 00:00:00 2001
From: Adam Piontek <adam@73k.us>
Date: Fri, 19 Mar 2021 16:38:52 -0400
Subject: [PATCH] much progress on shift assigning & app navigation

---
 lib/shift73k/shifts.ex                        |  32 ++++--
 lib/shift73k/shifts/templates.ex              |   6 +-
 .../shifts/templates/shift_template.ex        |   5 +-
 .../controllers/other_controller.ex           |  16 ---
 lib/shift73k_web/live/modal_component.ex      |  11 +-
 lib/shift73k_web/live/page_live.ex            |  40 -------
 lib/shift73k_web/live/page_live.html.leex     |  49 --------
 .../shift_assign_live/delete_component.ex     |  42 +++++++
 .../delete_component.html.leex                |  31 +++++
 .../live/shift_assign_live/index.ex           | 108 ++++++++++++++----
 .../live/shift_assign_live/index.html.leex    |  29 +++--
 .../shift_template_live/delete_component.ex   |   5 -
 .../delete_component.html.leex                |   2 +-
 .../shift_template_live/form_component.ex     |   5 -
 .../form_component.html.leex                  |   2 +-
 .../live/shift_template_live/index.ex         |  31 ++++-
 .../live/shift_template_live/index.html.leex  |   3 +-
 .../live/user_management/delete_component.ex  |   9 +-
 .../delete_component.html.leex                |   2 +-
 .../live/user_management/form_component.ex    |   5 -
 .../user_management/form_component.html.leex  |   2 +-
 .../live/user_management/index.ex             |  44 ++++---
 .../live/user_management/index.html.leex      |   4 +-
 lib/shift73k_web/plugs/redirector.ex          |  36 ++++++
 lib/shift73k_web/router.ex                    |   3 +-
 .../templates/layout/_navbar.html.eex         |  28 +++--
 .../layout/navbar/_shifts_menu.html.eex       |  25 ++++
 .../layout/navbar/_user_menu.html.eex         |   4 -
 .../templates/other/index.html.eex            |  41 -------
 lib/shift73k_web/views/other_view.ex          |   3 -
 .../20210306171754_create_shift_templates.exs |   2 +-
 ...06173113_add_user_default_shift_column.exs |   2 +-
 test/shift73k_web/live/page_live_test.exs     |  66 -----------
 33 files changed, 363 insertions(+), 330 deletions(-)
 delete mode 100644 lib/shift73k_web/controllers/other_controller.ex
 delete mode 100644 lib/shift73k_web/live/page_live.ex
 delete mode 100644 lib/shift73k_web/live/page_live.html.leex
 create mode 100644 lib/shift73k_web/live/shift_assign_live/delete_component.ex
 create mode 100644 lib/shift73k_web/live/shift_assign_live/delete_component.html.leex
 create mode 100644 lib/shift73k_web/plugs/redirector.ex
 create mode 100644 lib/shift73k_web/templates/layout/navbar/_shifts_menu.html.eex
 delete mode 100644 lib/shift73k_web/templates/other/index.html.eex
 delete mode 100644 lib/shift73k_web/views/other_view.ex
 delete mode 100644 test/shift73k_web/live/page_live_test.exs

diff --git a/lib/shift73k/shifts.ex b/lib/shift73k/shifts.ex
index 93078c87..8f2aefaa 100644
--- a/lib/shift73k/shifts.ex
+++ b/lib/shift73k/shifts.ex
@@ -22,13 +22,26 @@ defmodule Shift73k.Shifts do
   end
 
   def list_shifts_by_user_between_dates(user_id, start_date, end_date) do
-    q = from(
-      s in Shift,
-      select: %{date: s.date, subject: s.subject, time_start: s.time_start, time_end: s.time_end},
-      where: s.user_id == ^user_id and s.date >= ^start_date and s.date < ^end_date,
-      order_by: [s.date, s.time_start]
-    )
-    Repo.all(q)
+    from(s in Shift)
+    |> select([s], %{
+      date: s.date,
+      subject: s.subject,
+      time_start: s.time_start,
+      time_end: s.time_end
+    })
+    |> where([s], s.user_id == ^user_id and s.date >= ^start_date and s.date <= ^end_date)
+    |> order_by([s], [s.date, s.time_start])
+    |> Repo.all()
+  end
+
+  defp query_shifts_by_user_on_list_of_dates(user_id, date_list) do
+    from(s in Shift)
+    |> where([s], s.user_id == ^user_id and s.date in ^date_list)
+  end
+
+  def list_shifts_by_user_on_list_of_dates(user_id, date_list) do
+    query_shifts_by_user_on_list_of_dates(user_id, date_list)
+    |> Repo.all()
   end
 
   @doc """
@@ -99,6 +112,11 @@ defmodule Shift73k.Shifts do
     Repo.delete(shift)
   end
 
+  def delete_shifts_by_user_on_list_of_dates(user_id, date_list) do
+    query_shifts_by_user_on_list_of_dates(user_id, date_list)
+    |> Repo.delete_all()
+  end
+
   @doc """
   Returns an `%Ecto.Changeset{}` for tracking shift changes.
 
diff --git a/lib/shift73k/shifts/templates.ex b/lib/shift73k/shifts/templates.ex
index 286f555d..6530802f 100644
--- a/lib/shift73k/shifts/templates.ex
+++ b/lib/shift73k/shifts/templates.ex
@@ -22,7 +22,11 @@ defmodule Shift73k.Shifts.Templates do
   end
 
   def list_shift_templates_by_user_id(user_id) do
-    q = from s in ShiftTemplate, where: s.user_id == ^user_id, order_by: [s.subject, s.time_start]
+    q =
+      from s in ShiftTemplate,
+        where: s.user_id == ^user_id,
+        order_by: [fragment("lower(?)", s.subject), s.time_start]
+
     Repo.all(q)
   end
 
diff --git a/lib/shift73k/shifts/templates/shift_template.ex b/lib/shift73k/shifts/templates/shift_template.ex
index 55ad1a56..ee749f65 100644
--- a/lib/shift73k/shifts/templates/shift_template.ex
+++ b/lib/shift73k/shifts/templates/shift_template.ex
@@ -19,6 +19,7 @@ defmodule Shift73k.Shifts.Templates.ShiftTemplate do
     field :time_end, :time, default: ~T[17:00:00]
 
     belongs_to(:user, Shift73k.Accounts.User)
+    has_one(:is_fave_of_user, Shift73k.Accounts.User, foreign_key: :fave_shift_template_id)
 
     timestamps()
   end
@@ -58,7 +59,9 @@ defmodule Shift73k.Shifts.Templates.ShiftTemplate do
           []
       end
     end)
-    |> validate_inclusion(:time_zone, Timex.timezones(), message: "must be a valid IANA tz database time zone")
+    |> validate_inclusion(:time_zone, Timex.timezones(),
+      message: "must be a valid IANA tz database time zone"
+    )
   end
 
   defp time_start_from_attrs(%{"time_start" => time_start}), do: time_start
diff --git a/lib/shift73k_web/controllers/other_controller.ex b/lib/shift73k_web/controllers/other_controller.ex
deleted file mode 100644
index 942377cf..00000000
--- a/lib/shift73k_web/controllers/other_controller.ex
+++ /dev/null
@@ -1,16 +0,0 @@
-defmodule Shift73kWeb.OtherController do
-  use Shift73kWeb, :controller
-
-  def index(conn, _params) do
-    conn
-    |> put_flash(:success, "Log in was a success. Good for you.")
-    |> put_flash(:error, "Lorem ipsum dolor sit amet consectetur adipisicing elit.")
-    |> put_flash(
-      :info,
-      "Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatibus dolore sunt quia aperiam sint id reprehenderit? Dolore incidunt alias inventore accusantium nulla optio, ducimus eius aliquam hic, pariatur voluptate distinctio."
-    )
-    |> put_flash(:warning, "Oh no, there's nothing to worry about!")
-    |> put_flash(:primary, "Something in the brand color.")
-    |> render("index.html")
-  end
-end
diff --git a/lib/shift73k_web/live/modal_component.ex b/lib/shift73k_web/live/modal_component.ex
index 3fc7d984..b3f165e3 100644
--- a/lib/shift73k_web/live/modal_component.ex
+++ b/lib/shift73k_web/live/modal_component.ex
@@ -16,10 +16,10 @@ defmodule Shift73kWeb.ModalComponent do
 
           <div class="modal-header">
             <h5 class="modal-title"><%= Keyword.get(@opts, :title, "Modal title") %></h5>
-            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+            <button type="button" class="btn-close" phx-click="hide" phx-target="<%= @myself %>" aria-label="Close"></button>
           </div>
 
-          <%= live_component @socket, @component, @opts %>
+          <%= live_component @socket, @component, Keyword.put(@opts, :modal_id, @id) %>
 
         </div>
       </div>
@@ -27,6 +27,11 @@ defmodule Shift73kWeb.ModalComponent do
     """
   end
 
+  @impl true
+  def update(assigns, socket) do
+    socket |> assign(assigns) |> live_okreply()
+  end
+
   @impl true
   def handle_event("close", _, socket) do
     send(self(), {:close_modal, true})
@@ -35,6 +40,6 @@ defmodule Shift73kWeb.ModalComponent do
 
   @impl true
   def handle_event("hide", _, socket) do
-    {:noreply, push_event(socket, "modal-please-hide", %{})}
+    socket |> push_event("modal-please-hide", %{}) |> live_noreply()
   end
 end
diff --git a/lib/shift73k_web/live/page_live.ex b/lib/shift73k_web/live/page_live.ex
deleted file mode 100644
index aba5f081..00000000
--- a/lib/shift73k_web/live/page_live.ex
+++ /dev/null
@@ -1,40 +0,0 @@
-defmodule Shift73kWeb.PageLive do
-  use Shift73kWeb, :live_view
-
-  @impl true
-  def mount(_params, session, socket) do
-    socket = assign_defaults(socket, session)
-    {:ok, assign(socket, query: "", results: %{})}
-  end
-
-  @impl true
-  def handle_event("suggest", %{"q" => query}, socket) do
-    {:noreply, assign(socket, results: search(query), query: query)}
-  end
-
-  @impl true
-  def handle_event("search", %{"q" => query}, socket) do
-    case search(query) do
-      %{^query => vsn} ->
-        {:noreply, redirect(socket, external: "https://hexdocs.pm/#{query}/#{vsn}")}
-
-      _ ->
-        {:noreply,
-         socket
-         |> put_flash(:error, "No dependencies found matching \"#{query}\"")
-         |> assign(results: %{}, query: query)}
-    end
-  end
-
-  defp search(query) do
-    if not Shift73kWeb.Endpoint.config(:code_reloader) do
-      raise "action disabled when not in development"
-    end
-
-    for {app, desc, vsn} <- Application.started_applications(),
-        app = to_string(app),
-        String.starts_with?(app, query) and not List.starts_with?(desc, ~c"ERTS"),
-        into: %{},
-        do: {app, vsn}
-  end
-end
diff --git a/lib/shift73k_web/live/page_live.html.leex b/lib/shift73k_web/live/page_live.html.leex
deleted file mode 100644
index daf2334a..00000000
--- a/lib/shift73k_web/live/page_live.html.leex
+++ /dev/null
@@ -1,49 +0,0 @@
-<section class="phx-hero">
-  <h1><%= gettext "Welcome to %{name}!", name: "Phoenix" %></h1>
-  <p>Peace of mind from prototype to production</p>
-
-  <form phx-change="suggest" phx-submit="search">
-    <input type="text" name="q" value="<%= @query %>" placeholder="Live dependency search" list="results" autocomplete="off"/>
-    <datalist id="results">
-      <%= for {app, _vsn} <- @results do %>
-        <option value="<%= app %>"><%= app %></option>
-      <% end %>
-    </datalist>
-    <button type="submit" phx-disable-with="Searching...">Go to Hexdocs</button>
-  </form>
-</section>
-
-<section class="row align-items-start">
-  <article class="col">
-    <h2>Resources</h2>
-    <ul>
-      <li>
-        <a href="https://hexdocs.pm/phoenix/overview.html">Guides &amp; Docs</a>
-      </li>
-      <li>
-        <a href="https://github.com/phoenixframework/phoenix">Source</a>
-      </li>
-      <li>
-        <a href="https://github.com/phoenixframework/phoenix/blob/v1.5/CHANGELOG.md">v1.5 Changelog</a>
-      </li>
-    </ul>
-  </article>
-  <article class="col">
-    <h2>Help</h2>
-    <ul>
-      <li>
-        <a href="https://elixirforum.com/c/phoenix-forum">Forum</a>
-      </li>
-      <li>
-        <a href="https://webchat.freenode.net/?channels=elixir-lang">#elixir-lang on Freenode IRC</a>
-      </li>
-      <li>
-        <a href="https://twitter.com/elixirphoenix">Twitter @elixirphoenix</a>
-      </li>
-      <li>
-        <a href="https://elixir-slackin.herokuapp.com/">Elixir on Slack</a>
-      </li>
-    </ul>
-  </article>
-
-</section>
diff --git a/lib/shift73k_web/live/shift_assign_live/delete_component.ex b/lib/shift73k_web/live/shift_assign_live/delete_component.ex
new file mode 100644
index 00000000..8dc279cb
--- /dev/null
+++ b/lib/shift73k_web/live/shift_assign_live/delete_component.ex
@@ -0,0 +1,42 @@
+defmodule Shift73kWeb.ShiftAssignLive.DeleteComponent do
+  use Shift73kWeb, :live_component
+
+  alias Shift73k.Shifts
+
+  @impl true
+  def update(assigns, socket) do
+    socket
+    |> assign(assigns)
+    |> assign_dates()
+    |> live_okreply()
+  end
+
+  defp assign_dates(%{assigns: %{delete_days_shifts: daylist}} = socket) do
+    date_list = Enum.map(daylist, &Date.from_iso8601!/1)
+    year_map = Enum.group_by(date_list, fn d -> d.year end)
+    assign(socket, date_list: date_list, date_map: build_date_map(year_map))
+  end
+
+  def build_date_map(year_map) do
+    year_map
+    |> Map.keys()
+    |> Enum.reduce(year_map, fn y, acc ->
+      Map.put(acc, y, Enum.group_by(acc[y], fn d -> d.month end))
+    end)
+  end
+
+  @impl true
+  def handle_event("confirm-delete-days-shifts", _params, socket) do
+    user = socket.assigns.current_user
+    date_list = socket.assigns.date_list
+    {n, _} = Shifts.delete_shifts_by_user_on_list_of_dates(user.id, date_list)
+    s = (n > 1 && "s") || ""
+    flash = {:info, "Successfully deleted #{n} assigned shift#{s}"}
+    send(self(), {:put_flash_message, flash})
+    send(self(), {:clear_selected_days, true})
+
+    socket
+    |> push_event("modal-please-hide", %{})
+    |> live_noreply()
+  end
+end
diff --git a/lib/shift73k_web/live/shift_assign_live/delete_component.html.leex b/lib/shift73k_web/live/shift_assign_live/delete_component.html.leex
new file mode 100644
index 00000000..f159bcdf
--- /dev/null
+++ b/lib/shift73k_web/live/shift_assign_live/delete_component.html.leex
@@ -0,0 +1,31 @@
+<div class="modal-body">
+
+  <p>Are you sure you want to delete all assigned shifts from the selected days?</p>
+
+  <%= for {y, data} <- @date_map do %>
+    <dt><%= y %></dt>
+    <% months = Map.keys(data) %>
+    <dd>
+      <%= for {m, i} <- Enum.with_index(months, 1) do %>
+        <%= data |> Map.get(m) |> hd() |> Timex.format!("{Mshort}") %>:
+        <% days = Map.get(data, m) %>
+        <%= for {d, i} <- Enum.with_index(days, 1) do %>
+          <%= d.day %><%= if i < length(days) do %>,<% end %>
+        <% end %>
+
+        <%= if i < length(months) do %><br /><% end %>
+      <% end %>
+    </dd>
+  <% 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-delete-days-shifts",
+      phx_target: @myself
+    %>
+
+</div>
diff --git a/lib/shift73k_web/live/shift_assign_live/index.ex b/lib/shift73k_web/live/shift_assign_live/index.ex
index 60535bbd..91640d52 100644
--- a/lib/shift73k_web/live/shift_assign_live/index.ex
+++ b/lib/shift73k_web/live/shift_assign_live/index.ex
@@ -18,9 +18,10 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
     socket
     |> assign_defaults(session)
     |> assign(:custom_shift, @custom_shift)
-    |> assign(:show_template_btn_active, :false)
-    |> assign(:show_template_details, :false)
+    |> assign(:show_template_btn_active, false)
+    |> assign(:show_template_details, false)
     |> assign(:selected_days, [])
+    |> assign(:delete_days_shifts, nil)
     |> live_okreply()
   end
 
@@ -32,12 +33,18 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
     |> show_details_if_custom()
     |> assign_shift_length()
     |> assign_shift_template_changeset()
+    |> assign_modal_close_handlers()
     |> init_today(Timex.today())
     |> init_calendar()
     |> assign_known_shifts()
     |> live_noreply()
   end
 
+  defp assign_modal_close_handlers(socket) do
+    to = Routes.shift_assign_index_path(socket, :index)
+    assign(socket, modal_return_to: to, modal_close_action: :return)
+  end
+
   defp get_shift_template("custom-shift"), do: @custom_shift
   defp get_shift_template(template_id), do: Templates.get_shift_template(template_id)
 
@@ -56,11 +63,11 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
   defp init_calendar(%{assigns: %{current_user: user}} = socket) do
     days = day_names(user.week_start_at)
     {first, last, rows} = week_rows(socket.assigns.cursor_date, user.week_start_at)
-    assign(socket, [day_names: days, week_rows: rows, day_first: first, day_last: last])
+    assign(socket, day_names: days, week_rows: rows, day_first: first, day_last: last)
   end
 
   defp init_today(socket, today) do
-    assign(socket, [current_date: today, cursor_date: today])
+    assign(socket, current_date: today, cursor_date: today)
   end
 
   defp assign_shift_template_changeset(%{assigns: %{shift_template: shift}} = socket) do
@@ -71,7 +78,7 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
   defp init_shift_template(socket) do
     first_list_id = socket.assigns.shift_templates |> hd() |> elem(1)
     fave_id = socket.assigns.current_user.fave_shift_template_id
-    assign_shift_template(socket, (fave_id || first_list_id))
+    assign_shift_template(socket, fave_id || first_list_id)
   end
 
   defp assign_shift_template(socket, template_id) do
@@ -83,14 +90,17 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
       Templates.list_shift_templates_by_user_id(user.id)
       |> Enum.map(fn t -> shift_template_option(t, user.fave_shift_template_id) end)
       |> Enum.concat([@custom_shift_opt])
+
     assign(socket, :shift_templates, shift_templates)
   end
 
   defp shift_template_option(template, fave_id) do
     label =
-      template.subject <> " (" <>
-      format_shift_time(template.time_start) <> "—" <>
-      format_shift_time(template.time_end) <> ")"
+      template.subject <>
+        " (" <>
+        format_shift_time(template.time_start) <>
+        "—" <>
+        format_shift_time(template.time_end) <> ")"
 
     label =
       case fave_id == template.id do
@@ -126,7 +136,7 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
 
     week_rows =
       Interval.new(from: first, until: last, right_open: false)
-      |> Enum.map(& NaiveDateTime.to_date(&1))
+      |> Enum.map(&NaiveDateTime.to_date(&1))
       |> Enum.chunk_every(7)
 
     {first, last, week_rows}
@@ -141,11 +151,14 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
           true -> "bg-triangle-white"
         end
 
-      Timex.compare(day, current_date, :days) == 0 -> "bg-info text-white"
+      Timex.compare(day, current_date, :days) == 0 ->
+        "bg-info text-white"
 
-      day.month != cursor_date.month -> "bg-light text-gray"
+      day.month != cursor_date.month ->
+        "bg-light text-gray"
 
-      true -> ""
+      true ->
+        ""
     end
   end
 
@@ -157,11 +170,12 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
   end
 
   defp show_details_if_custom(socket) do
-    if (socket.assigns.shift_template.id != @custom_shift.id) || socket.assigns.show_template_details do
+    if socket.assigns.shift_template.id != @custom_shift.id ||
+         socket.assigns.show_template_details do
       socket
     else
       socket
-      |> assign(:show_template_btn_active, :true)
+      |> assign(:show_template_btn_active, true)
       |> push_event("toggle-template-details", %{targetId: "#templateDetailsCol"})
     end
   end
@@ -197,7 +211,11 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
   end
 
   @impl true
-  def handle_event("change-selected-template", %{"template_select" => %{"template" => template_id}}, socket) do
+  def handle_event(
+        "change-selected-template",
+        %{"template_select" => %{"template" => template_id}},
+        socket
+      ) do
     socket
     |> assign_shift_template(template_id)
     |> show_details_if_custom()
@@ -210,9 +228,11 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
   def handle_event("month-nav", %{"month" => direction}, socket) do
     new_cursor =
       cond do
-        direction == "now" -> Timex.today()
+        direction == "now" ->
+          Timex.today()
+
         true ->
-          months = direction == "prev" && -1 || 1
+          months = (direction == "prev" && -1) || 1
           Timex.shift(socket.assigns.cursor_date, months: months)
       end
 
@@ -229,12 +249,12 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
 
   @impl true
   def handle_event("collapse-shown", %{"target_id" => _target_id}, socket) do
-    {:noreply, assign(socket, :show_template_details, :true)}
+    {:noreply, assign(socket, :show_template_details, true)}
   end
 
   @impl true
   def handle_event("collapse-hidden", %{"target_id" => _target_id}, socket) do
-    {:noreply, assign(socket, :show_template_details, :false)}
+    {:noreply, assign(socket, :show_template_details, false)}
   end
 
   @impl true
@@ -248,6 +268,14 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
     {:noreply, assign(socket, :selected_days, selected_days)}
   end
 
+  @impl true
+  def handle_event("delete-days-shifts", _params, socket) do
+    socket
+    |> assign(:modal_close_action, :delete_days_shifts)
+    |> assign(:delete_days_shifts, socket.assigns.selected_days)
+    |> live_noreply()
+  end
+
   @impl true
   def handle_event("clear-days", _params, socket) do
     {:noreply, assign(socket, :selected_days, [])}
@@ -259,7 +287,8 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
     shift_data = shift_data_from_template(socket.assigns.shift_template)
 
     # 2. create list of shift attrs to insert
-    to_insert = Enum.map(socket.assigns.selected_days, &shift_from_day_and_shift_data(&1, shift_data))
+    to_insert =
+      Enum.map(socket.assigns.selected_days, &shift_from_day_and_shift_data(&1, shift_data))
 
     # 3. insert the data
     {status, msg} = insert_shifts(to_insert, length(socket.assigns.selected_days))
@@ -271,10 +300,37 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
     |> live_noreply()
   end
 
+  @impl true
+  def handle_info({:put_flash_message, {flash_type, msg}}, socket) do
+    socket |> put_flash(flash_type, msg) |> live_noreply()
+  end
+
+  @impl true
+  def handle_info({:clear_selected_days, _}, socket) do
+    socket |> assign(:selected_days, []) |> live_noreply()
+  end
+
+  @impl true
+  def handle_info({:close_modal, _}, %{assigns: %{modal_close_action: :return}} = socket) do
+    socket
+    |> copy_flash()
+    |> push_patch(to: socket.assigns.modal_return_to)
+    |> live_noreply()
+  end
+
+  @impl true
+  def handle_info({:close_modal, _}, %{assigns: %{modal_close_action: assign_key}} = socket) do
+    socket
+    |> assign(assign_key, nil)
+    |> assign_modal_close_handlers()
+    |> assign_known_shifts()
+    |> live_noreply()
+  end
+
   defp shift_data_from_template(shift_template) do
     shift_template
     |> Map.from_struct()
-    |> Map.drop([:__meta__, :id, :inserted_at, :updated_at, :user])
+    |> Map.drop([:__meta__, :id, :inserted_at, :updated_at, :user, :is_fave_of_user])
   end
 
   defp shift_from_day_and_shift_data(day, shift_data) do
@@ -289,12 +345,16 @@ defmodule Shift73kWeb.ShiftAssignLive.Index do
     |> Repo.transaction()
     |> case do
       {:ok, %{insert_all: {n, _}}} ->
+        s = (n > 1 && "s") || ""
+
         if n == day_count do
-          {:success, "Successfully assigned shift to #{n} day(s)"}
+          {:success, "Successfully assigned shift to #{n} day#{s}"}
         else
-          {:warning, "Some error, only #{n} day(s) inserted but #{day_count} were selected"}
+          {:warning, "Some error, only #{n} day#{s} inserted but #{day_count} were selected"}
         end
-      _ -> {:error, "Ope, unknown error inserting shifts, page the dev"}
+
+      _ ->
+        {:error, "Ope, unknown error inserting shifts, page the dev"}
     end
   end
 
diff --git a/lib/shift73k_web/live/shift_assign_live/index.html.leex b/lib/shift73k_web/live/shift_assign_live/index.html.leex
index c5136885..a8160bfa 100644
--- a/lib/shift73k_web/live/shift_assign_live/index.html.leex
+++ b/lib/shift73k_web/live/shift_assign_live/index.html.leex
@@ -1,3 +1,13 @@
+<%= 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"] %>
   Assign Shift To Dates
@@ -223,17 +233,22 @@
 </table>
 
 
-<div class="row justify-content-end my-4">
-  <div class="col-auto">
+<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-dark" phx-click="clear-days">
-    <%= icon_div @socket, "bi-eraser", [class: "icon baseline"] %>
-    Clear
+  <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-primary" phx-click="save-days" <%= if (!@shift_template_changeset.valid? || Enum.empty?(@selected_days)), do: "disabled" %>>
+  <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"] %>
-    Save assigned shifts
+    Assign shifts to selected days
   </button>
 
   </div>
diff --git a/lib/shift73k_web/live/shift_template_live/delete_component.ex b/lib/shift73k_web/live/shift_template_live/delete_component.ex
index 71205ab3..44209db5 100644
--- a/lib/shift73k_web/live/shift_template_live/delete_component.ex
+++ b/lib/shift73k_web/live/shift_template_live/delete_component.ex
@@ -11,11 +11,6 @@ defmodule Shift73kWeb.ShiftTemplateLive.DeleteComponent do
     |> live_okreply()
   end
 
-  @impl true
-  def handle_event("cancel", _, socket) do
-    {:noreply, push_event(socket, "modal-please-hide", %{})}
-  end
-
   @impl true
   def handle_event("confirm", %{"id" => id, "subject" => subject}, socket) do
     id
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 a14f6a74..8c121a75 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
@@ -8,7 +8,7 @@
 </div>
 <div class="modal-footer">
 
-  <%= link "Cancel", to: "#", class: "btn me-2", phx_click: "cancel", phx_target: @myself %>
+  <%= 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",
diff --git a/lib/shift73k_web/live/shift_template_live/form_component.ex b/lib/shift73k_web/live/shift_template_live/form_component.ex
index f1790457..d4263bcd 100644
--- a/lib/shift73k_web/live/shift_template_live/form_component.ex
+++ b/lib/shift73k_web/live/shift_template_live/form_component.ex
@@ -52,11 +52,6 @@ defmodule Shift73kWeb.ShiftTemplateLive.FormComponent do
     )
   end
 
-  @impl true
-  def handle_event("cancel", _, socket) do
-    {:noreply, push_event(socket, "modal-please-hide", %{})}
-  end
-
   defp save_shift_template(socket, :new, params) do
     case Templates.create_shift_template(params) do
       {:ok, _shift_template} ->
diff --git a/lib/shift73k_web/live/shift_template_live/form_component.html.leex b/lib/shift73k_web/live/shift_template_live/form_component.html.leex
index 8ea39d8b..77de5232 100644
--- a/lib/shift73k_web/live/shift_template_live/form_component.html.leex
+++ b/lib/shift73k_web/live/shift_template_live/form_component.html.leex
@@ -104,7 +104,7 @@
   </div>
   <div class="modal-footer">
 
-    <%= link "Cancel", to: "#", class: "btn", phx_click: "cancel", phx_target: @myself %>
+    <%= link "Cancel", to: "#", class: "btn btn-outline-dark", phx_click: "hide", phx_target: "##{@modal_id}" %>
     <%= submit "Save",
         class: "btn btn-primary ",
         disabled: !@changeset.valid?,
diff --git a/lib/shift73k_web/live/shift_template_live/index.ex b/lib/shift73k_web/live/shift_template_live/index.ex
index af877f65..a1287922 100644
--- a/lib/shift73k_web/live/shift_template_live/index.ex
+++ b/lib/shift73k_web/live/shift_template_live/index.ex
@@ -23,7 +23,7 @@ defmodule Shift73kWeb.ShiftTemplateLive.Index do
     if Roles.can?(current_user, shift_template, live_action) do
       socket
       |> assign_shift_templates()
-      |> assign(:modal_return_to, Routes.shift_template_index_path(socket, :index))
+      |> assign_modal_close_handlers()
       |> assign(:delete_shift_template, nil)
       |> apply_action(socket.assigns.live_action, params)
       |> live_noreply()
@@ -35,6 +35,11 @@ defmodule Shift73kWeb.ShiftTemplateLive.Index do
     end
   end
 
+  defp assign_modal_close_handlers(socket) do
+    to = Routes.shift_template_index_path(socket, :index)
+    assign(socket, modal_return_to: to, modal_close_action: :return)
+  end
+
   defp apply_action(socket, :clone, %{"id" => id}) do
     socket
     |> assign(:page_title, "Clone Shift Template")
@@ -74,9 +79,13 @@ defmodule Shift73kWeb.ShiftTemplateLive.Index do
 
   @impl true
   def handle_event("delete-modal", %{"id" => id}, socket) do
-    {:noreply, assign(socket, :delete_shift_template, Templates.get_shift_template!(id))}
+    socket
+    |> assign(:modal_close_action, :delete_shift_template)
+    |> assign(:delete_shift_template, Templates.get_shift_template!(id))
+    |> live_noreply()
   end
 
+  @impl true
   def handle_event("set-user-fave-shift-template", %{"id" => shift_template_id}, socket) do
     user_id = socket.assigns.current_user.id
     Accounts.set_user_fave_shift_template(user_id, shift_template_id)
@@ -87,6 +96,7 @@ defmodule Shift73kWeb.ShiftTemplateLive.Index do
     |> live_noreply()
   end
 
+  @impl true
   def handle_event("unset-user-fave-shift-template", _params, socket) do
     user_id = socket.assigns.current_user.id
     Accounts.unset_user_fave_shift_template(user_id)
@@ -98,13 +108,24 @@ defmodule Shift73kWeb.ShiftTemplateLive.Index do
   end
 
   @impl true
-  def handle_info({:close_modal, _}, %{assigns: %{modal_return_to: to}} = socket) do
-    socket |> copy_flash() |> push_patch(to: to) |> live_noreply()
+  def handle_info({:close_modal, _}, %{assigns: %{modal_close_action: :return}} = socket) do
+    socket
+    |> copy_flash()
+    |> push_patch(to: socket.assigns.modal_return_to)
+    |> live_noreply()
+  end
+
+  @impl true
+  def handle_info({:close_modal, _}, %{assigns: %{modal_close_action: assign_key}} = socket) do
+    socket
+    |> assign(assign_key, nil)
+    |> assign_modal_close_handlers()
+    |> assign_shift_templates()
+    |> live_noreply()
   end
 
   @impl true
   def handle_info({:put_flash_message, {flash_type, msg}}, socket) do
     socket |> put_flash(flash_type, msg) |> live_noreply()
   end
-
 end
diff --git a/lib/shift73k_web/live/shift_template_live/index.html.leex b/lib/shift73k_web/live/shift_template_live/index.html.leex
index bb9bcd30..bd4c1b1b 100644
--- a/lib/shift73k_web/live/shift_template_live/index.html.leex
+++ b/lib/shift73k_web/live/shift_template_live/index.html.leex
@@ -11,8 +11,7 @@
   <%= live_modal @socket, Shift73kWeb.ShiftTemplateLive.DeleteComponent,
       id: @delete_shift_template.id,
       title: "Delete Shift Template",
-      delete_shift_template: @delete_shift_template,
-      current_user: @current_user %>
+      delete_shift_template: @delete_shift_template %>
 <% end %>
 
 
diff --git a/lib/shift73k_web/live/user_management/delete_component.ex b/lib/shift73k_web/live/user_management/delete_component.ex
index d781c145..b1c48aae 100644
--- a/lib/shift73k_web/live/user_management/delete_component.ex
+++ b/lib/shift73k_web/live/user_management/delete_component.ex
@@ -5,14 +5,7 @@ defmodule Shift73kWeb.UserManagement.DeleteComponent do
 
   @impl true
   def update(assigns, socket) do
-    socket
-    |> assign(assigns)
-    |> live_okreply()
-  end
-
-  @impl true
-  def handle_event("cancel", _, socket) do
-    {:noreply, push_event(socket, "modal-please-hide", %{})}
+    socket |> assign(assigns) |> live_okreply()
   end
 
   @impl true
diff --git a/lib/shift73k_web/live/user_management/delete_component.html.leex b/lib/shift73k_web/live/user_management/delete_component.html.leex
index 06320d34..d7614702 100644
--- a/lib/shift73k_web/live/user_management/delete_component.html.leex
+++ b/lib/shift73k_web/live/user_management/delete_component.html.leex
@@ -5,7 +5,7 @@
 </div>
 <div class="modal-footer">
 
-  <%= link "Cancel", to: "#", class: "btn me-2", phx_click: "cancel", phx_target: @myself %>
+  <%= 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",
diff --git a/lib/shift73k_web/live/user_management/form_component.ex b/lib/shift73k_web/live/user_management/form_component.ex
index fa41df90..2a6f7512 100644
--- a/lib/shift73k_web/live/user_management/form_component.ex
+++ b/lib/shift73k_web/live/user_management/form_component.ex
@@ -80,11 +80,6 @@ defmodule Shift73kWeb.UserManagement.FormComponent do
     save_user(socket, user_params)
   end
 
-  @impl true
-  def handle_event("cancel", _, socket) do
-    {:noreply, push_event(socket, "modal-please-hide", %{})}
-  end
-
   def role_description(role) when is_atom(role) do
     Keyword.get(User.roles(), role)
   end
diff --git a/lib/shift73k_web/live/user_management/form_component.html.leex b/lib/shift73k_web/live/user_management/form_component.html.leex
index db0accd5..15f82296 100644
--- a/lib/shift73k_web/live/user_management/form_component.html.leex
+++ b/lib/shift73k_web/live/user_management/form_component.html.leex
@@ -49,7 +49,7 @@
   </div>
   <div class="modal-footer">
 
-    <%= link "Cancel", to: "#", class: "btn", phx_click: "cancel", phx_target: @myself %>
+    <%= link "Cancel", to: "#", class: "btn btn-outline-dark", phx_click: "hide", phx_target: "##{@modal_id}" %>
     <%= submit "Save",
         class: "btn btn-primary ",
         disabled: !@changeset.valid?,
diff --git a/lib/shift73k_web/live/user_management/index.ex b/lib/shift73k_web/live/user_management/index.ex
index 804fc3f2..64ba2041 100644
--- a/lib/shift73k_web/live/user_management/index.ex
+++ b/lib/shift73k_web/live/user_management/index.ex
@@ -28,9 +28,8 @@ defmodule Shift73kWeb.UserManagementLive.Index do
     if Roles.can?(current_user, user, live_action) do
       socket
       |> assign(:query, query_map(params))
-      |> assign_modal_return_to()
+      |> assign_modal_close_handlers()
       |> assign(:delete_user, nil)
-      |> assign(:page, nil)
       |> request_page_query()
       |> apply_action(socket.assigns.live_action, params)
       |> live_noreply()
@@ -65,9 +64,9 @@ defmodule Shift73kWeb.UserManagementLive.Index do
     |> assign(:user, Accounts.get_user!(id))
   end
 
-  def assign_modal_return_to(%{assigns: %{query: query}} = socket) do
+  defp assign_modal_close_handlers(%{assigns: %{query: query}} = socket) do
     to = Routes.user_management_index_path(socket, :index, Enum.into(query, []))
-    assign(socket, :modal_return_to, to)
+    assign(socket, modal_return_to: to, modal_close_action: :return)
   end
 
   defp user_from_params(params)
@@ -98,7 +97,10 @@ defmodule Shift73kWeb.UserManagementLive.Index do
 
   @impl true
   def handle_event("delete-modal", %{"id" => id}, socket) do
-    {:noreply, assign(socket, :delete_user, Accounts.get_user!(id))}
+    socket
+    |> assign(:modal_close_action, :delete_user)
+    |> assign(:delete_user, Accounts.get_user!(id))
+    |> live_noreply()
   end
 
   @impl true
@@ -114,17 +116,13 @@ defmodule Shift73kWeb.UserManagementLive.Index do
   end
 
   @impl true
-  def handle_event(
-        "sort-change",
-        %{"sort_by" => column} = params,
-        %{assigns: %{query: query}} = socket
-      ) do
-    (column == query.sort_by &&
-       send(
-         self(),
-         {:query_update, %{"sort_order" => (query.sort_order == "asc" && "desc") || "asc"}}
-       )) ||
+  def handle_event("sort-change", %{"sort_by" => column} = params, socket) do
+    if column == socket.assigns.query.sort_by do
+      order = (socket.assigns.query.sort_order == "asc" && "desc") || "asc"
+      send(self(), {:query_update, %{"sort_order" => order}})
+    else
       send(self(), {:query_update, Map.put(params, "sort_order", "asc")})
+    end
 
     {:noreply, socket}
   end
@@ -169,8 +167,20 @@ defmodule Shift73kWeb.UserManagementLive.Index do
   end
 
   @impl true
-  def handle_info({:close_modal, _}, %{assigns: %{modal_return_to: to}} = socket) do
-    socket |> copy_flash() |> push_patch(to: to) |> live_noreply()
+  def handle_info({:close_modal, _}, %{assigns: %{modal_close_action: :return}} = socket) do
+    socket
+    |> copy_flash()
+    |> push_patch(to: socket.assigns.modal_return_to)
+    |> live_noreply()
+  end
+
+  @impl true
+  def handle_info({:close_modal, _}, %{assigns: %{modal_close_action: assign_key}} = socket) do
+    socket
+    |> assign(assign_key, nil)
+    |> assign_modal_close_handlers()
+    |> request_page_query()
+    |> live_noreply()
   end
 
   @impl true
diff --git a/lib/shift73k_web/live/user_management/index.html.leex b/lib/shift73k_web/live/user_management/index.html.leex
index 0279f882..9412d876 100644
--- a/lib/shift73k_web/live/user_management/index.html.leex
+++ b/lib/shift73k_web/live/user_management/index.html.leex
@@ -11,8 +11,8 @@
   <%= live_modal @socket, Shift73kWeb.UserManagement.DeleteComponent,
       id: @delete_user.id,
       title: "Delete User",
-      delete_user: @delete_user,
-      current_user: @current_user %>
+      delete_user: @delete_user
+    %>
 <% end %>
 
 
diff --git a/lib/shift73k_web/plugs/redirector.ex b/lib/shift73k_web/plugs/redirector.ex
new file mode 100644
index 00000000..1435f7d3
--- /dev/null
+++ b/lib/shift73k_web/plugs/redirector.ex
@@ -0,0 +1,36 @@
+defmodule Shift73kWeb.Redirector do
+  import Phoenix.Controller, only: [redirect: 2]
+
+  def init([to: _] = opts), do: opts
+  def init([external: _] = opts), do: opts
+  def init(_default), do: raise("Missing required to: / external: option in redirect")
+
+  def call(conn, [to: to]) do
+    redirect(conn, to: append_query_string(conn, to))
+  end
+  def call(conn, [external: url]) do
+    external = url
+    |> URI.parse
+    |> merge_query_string(conn)
+    |> URI.to_string
+
+    redirect(conn, external: external)
+  end
+
+
+  defp append_query_string(%Plug.Conn{query_string: ""}, path), do: path
+  defp append_query_string(%Plug.Conn{query_string: query}, path), do: "#{path}?#{query}"
+
+  defp merge_query_string(%URI{query: nil} = destination_uri, %Plug.Conn{query_string: source}) do
+    %{destination_uri | query: source}
+  end
+
+  defp merge_query_string(%URI{query: destination} = destination_uri, %Plug.Conn{query_string: source}) do
+    merged_query = Map.merge(
+      URI.decode_query(destination),
+      URI.decode_query(source)
+    )
+
+    %{destination_uri | query: URI.encode_query(merged_query)}
+  end
+end
diff --git a/lib/shift73k_web/router.ex b/lib/shift73k_web/router.ex
index 716513a3..13ede71b 100644
--- a/lib/shift73k_web/router.ex
+++ b/lib/shift73k_web/router.ex
@@ -32,8 +32,7 @@ defmodule Shift73kWeb.Router do
   scope "/", Shift73kWeb do
     pipe_through([:browser])
 
-    live("/", PageLive, :index)
-    get("/other", OtherController, :index)
+    get("/", Redirector, to: "/assign")
   end
 
   # Other scopes may use custom stacks.
diff --git a/lib/shift73k_web/templates/layout/_navbar.html.eex b/lib/shift73k_web/templates/layout/_navbar.html.eex
index ccf4a72a..16d58b79 100644
--- a/lib/shift73k_web/templates/layout/_navbar.html.eex
+++ b/lib/shift73k_web/templates/layout/_navbar.html.eex
@@ -2,7 +2,7 @@
   <div class="container">
 
     <h1 class="fs-4 my-0 py-0 lh-base">
-    <%= link to: Routes.page_path(@conn, :index), class: "navbar-brand fs-4" do %>
+    <%= link to: "/", class: "navbar-brand fs-4" do %>
       <%= icon_div @conn, "bi-calendar2-week", [class: "icon baseline me-1"] %>
       <span class="fw-light">Shift73k</span>
     <% end %>
@@ -26,14 +26,14 @@
       <%# nav LEFT items %>
       <ul class="navbar-nav me-auto mb-2 mb-lg-0">
 
-        <%= if @current_user do %>
-          <li class="nav-item">
-            <%= link nav_link_opts(@conn, to: Routes.shift_template_index_path(@conn, :index), class: "nav-link") do %>
-              <%= icon_div @conn, "bi-clock-history", [class: "icon baseline me-1"] %>
-              Templates
-            <% end %>
-          </li>
-        <% end %>
+        <%#= if @current_user do %>
+          <%# <li class="nav-item"> %>
+            <%#= link nav_link_opts(@conn, to: Routes.shift_template_index_path(@conn, :index), class: "nav-link") do %>
+              <%#= icon_div @conn, "bi-clock-history", [class: "icon baseline me-1"] %>
+              <%# Templates %>
+            <%# end %>
+          <%# </li> %>
+        <%# end %>
 
         <%# normal navbar link example %>
         <%# <li class="nav-item"> %>
@@ -66,13 +66,19 @@
       <%# nav RIGHT items %>
       <ul class="navbar-nav">
 
-        <%= render "navbar/_user_menu.html", assigns %>
+        <%= if @current_user do %>
+
+          <%= render "navbar/_shifts_menu.html", assigns %>
+
+          <%= render "navbar/_user_menu.html", assigns %>
+
+        <% else %>
 
-        <%= if !@current_user do %>
           <%= link nav_link_opts(@conn, to: Routes.user_session_path(@conn, :new), class: "btn btn-outline-light d-none d-lg-block") do %>
             <%= icon_div @conn, "bi-door-open", [class: "icon baseline"] %>
             Log in
           <% end %>
+
         <% end %>
 
       </ul>
diff --git a/lib/shift73k_web/templates/layout/navbar/_shifts_menu.html.eex b/lib/shift73k_web/templates/layout/navbar/_shifts_menu.html.eex
new file mode 100644
index 00000000..f5bc55ba
--- /dev/null
+++ b/lib/shift73k_web/templates/layout/navbar/_shifts_menu.html.eex
@@ -0,0 +1,25 @@
+<li class="nav-item dropdown">
+
+  <a href="#" class="nav-link dropdown-toggle" id="navbarDropdownUserMenu" data-bs-toggle="dropdown" aria-expanded="false">
+    <%= icon_div @conn, "bi-calendar2", [class: "icon baseline me-1"] %>
+    Shifts
+  </a>
+
+  <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownUserMenu">
+
+    <li>
+      <%= link nav_link_opts(@conn, to: Routes.shift_assign_index_path(@conn, :index), class: "dropdown-item") do %>
+        <%= icon_div @conn, "bi-calendar2-plus", [class: "icon baseline me-1"] %>
+        Assign Shift To Dates
+      <% end %>
+    </li>
+    <li>
+      <%= link nav_link_opts(@conn, to: Routes.shift_template_index_path(@conn, :index), class: "dropdown-item") do %>
+        <%= icon_div @conn, "bi-clock-history", [class: "icon baseline me-1"] %>
+        My Shift Templates
+      <% end %>
+    </li>
+
+  </ul>
+
+</li>
diff --git a/lib/shift73k_web/templates/layout/navbar/_user_menu.html.eex b/lib/shift73k_web/templates/layout/navbar/_user_menu.html.eex
index 2634cb17..bd01251d 100644
--- a/lib/shift73k_web/templates/layout/navbar/_user_menu.html.eex
+++ b/lib/shift73k_web/templates/layout/navbar/_user_menu.html.eex
@@ -1,5 +1,3 @@
-<%= if @current_user do %>
-
 <li class="nav-item dropdown">
 
   <a href="#" class="nav-link dropdown-toggle" id="navbarDropdownUserMenu" data-bs-toggle="dropdown" aria-expanded="false">
@@ -36,5 +34,3 @@
   </ul>
 
 </li>
-
-<% end %>
diff --git a/lib/shift73k_web/templates/other/index.html.eex b/lib/shift73k_web/templates/other/index.html.eex
deleted file mode 100644
index 1c00acf7..00000000
--- a/lib/shift73k_web/templates/other/index.html.eex
+++ /dev/null
@@ -1,41 +0,0 @@
-<h1 class="text-3xl font-bold leading-tight text-gunmetal-200">
-  Other Page
-</h1>
-<h2 class="text-xl leading-tight text-gunmetal-400">
-  With a subtitle no less!
-</h2>
-
-<div class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
-  <!-- Replace with your content -->
-  <%# <div class="px-4 py-6 sm:px-0">
-    <div class="border-4 border-dashed border-gray-200 rounded-lg h-96"></div>
-  </div> %>
-    <p>
-      Praesent velit justo, auctor ut nibh id, fermentum eleifend nunc. Cras sed purus dignissim, ornare elit et, ultrices elit. Sed quis neque consequat, laoreet ante a, hendrerit elit. Maecenas dapibus sed nulla vitae consectetur. Duis sollicitudin augue nisl, et rhoncus enim tempor at. Fusce scelerisque sollicitudin purus sit amet iaculis. Phasellus lacinia mi ut laoreet accumsan. Sed sagittis erat nec sem placerat, ut volutpat neque porttitor. Suspendisse tempor mauris vel mollis sagittis. In ut laoreet arcu. Duis sed felis in dui imperdiet luctus nec faucibus sem. Donec commodo urna ut enim fringilla, quis lacinia ligula malesuada. Quisque feugiat fermentum pretium. Integer sed porttitor lacus, sed bibendum diam. Aliquam dapibus neque et pharetra interdum.
-    </p>
-  <!-- /End replace -->
-</div>
-
-<!-- Button trigger modal -->
-<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
-  Launch demo modal
-</button>
-
-<!-- Modal -->
-<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
-  <div class="modal-dialog">
-    <div class="modal-content">
-      <div class="modal-header">
-        <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
-        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
-      </div>
-      <div class="modal-body">
-        Aliquam ultrices elit purus, eget dignissim orci pulvinar id. Curabitur tincidunt, ligula eu condimentum porttitor, nibh sapien scelerisque urna, nec cursus nisi nisi a neque. Mauris hendrerit orci blandit, suscipit ante nec, porttitor neque. Nunc.
-      </div>
-      <div class="modal-footer">
-        <button type="button" class="btn" data-bs-dismiss="modal">Close</button>
-        <button type="button" class="btn btn-primary">Save changes</button>
-      </div>
-    </div>
-  </div>
-</div>
diff --git a/lib/shift73k_web/views/other_view.ex b/lib/shift73k_web/views/other_view.ex
deleted file mode 100644
index 9bfb1801..00000000
--- a/lib/shift73k_web/views/other_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule Shift73kWeb.OtherView do
-  use Shift73kWeb, :view
-end
diff --git a/priv/repo/migrations/20210306171754_create_shift_templates.exs b/priv/repo/migrations/20210306171754_create_shift_templates.exs
index b158bdd0..0721384b 100644
--- a/priv/repo/migrations/20210306171754_create_shift_templates.exs
+++ b/priv/repo/migrations/20210306171754_create_shift_templates.exs
@@ -10,7 +10,7 @@ defmodule Shift73k.Repo.Migrations.CreateShiftTemplates do
       add :time_zone, :string, null: false
       add :time_start, :time, null: false
       add :time_end, :time, null: false
-      add :user_id, references(:users, on_delete: :nothing, type: :binary_id)
+      add :user_id, references(:users, on_delete: :delete_all, type: :binary_id)
 
       timestamps()
     end
diff --git a/priv/repo/migrations/20210306173113_add_user_default_shift_column.exs b/priv/repo/migrations/20210306173113_add_user_default_shift_column.exs
index ee01179f..fff49ac6 100644
--- a/priv/repo/migrations/20210306173113_add_user_default_shift_column.exs
+++ b/priv/repo/migrations/20210306173113_add_user_default_shift_column.exs
@@ -3,7 +3,7 @@ defmodule Shift73k.Repo.Migrations.AddUserDefaultShiftColumn do
 
   def change do
     alter table(:users) do
-      add(:fave_shift_template_id, references(:shift_templates, type: :binary_id, on_delete: :delete_all))
+      add(:fave_shift_template_id, references(:shift_templates, type: :binary_id, on_delete: :nilify_all))
     end
   end
 end
diff --git a/test/shift73k_web/live/page_live_test.exs b/test/shift73k_web/live/page_live_test.exs
deleted file mode 100644
index 716bccab..00000000
--- a/test/shift73k_web/live/page_live_test.exs
+++ /dev/null
@@ -1,66 +0,0 @@
-defmodule Shift73kWeb.PageLiveTest do
-  use Shift73kWeb.ConnCase
-
-  import Phoenix.LiveViewTest
-  import Shift73k.AccountsFixtures
-
-  test "disconnected and connected render with authentication should redirect to index page", %{
-    conn: conn
-  } do
-    conn = conn |> log_in_user(user_fixture())
-
-    {:ok, page_live, disconnected_html} = live(conn, "/")
-    assert disconnected_html =~ "Welcome to Phoenix!"
-    assert render(page_live) =~ "Welcome to Phoenix!"
-  end
-
-  test "logs out when force logout on logged user", %{
-    conn: conn
-  } do
-    user = user_fixture()
-    conn = conn |> log_in_user(user)
-
-    {:ok, page_live, disconnected_html} = live(conn, "/")
-    assert disconnected_html =~ "Welcome to Phoenix!"
-    assert render(page_live) =~ "Welcome to Phoenix!"
-
-    Shift73k.Accounts.logout_user(user)
-
-    # Assert our liveview process is down
-    ref = Process.monitor(page_live.pid)
-    assert_receive {:DOWN, ^ref, _, _, _}
-    refute Process.alive?(page_live.pid)
-
-    # Assert our liveview was redirected, following first to /users/force_logout, then to "/", and then to "/users/log_in"
-    assert_redirect(page_live, "/users/force_logout")
-
-    conn = get(conn, "/users/force_logout")
-    assert "/" = redir_path = redirected_to(conn, 302)
-    conn = get(recycle(conn), redir_path)
-
-    assert html_response(conn, 200) =~
-             "You were logged out. Please login again to continue using our application."
-  end
-
-  test "doesn't log out when force logout on another user", %{
-    conn: conn
-  } do
-    user1 = user_fixture()
-    user2 = user_fixture()
-    conn = conn |> log_in_user(user2)
-
-    {:ok, page_live, disconnected_html} = live(conn, "/")
-    assert disconnected_html =~ "Welcome to Phoenix!"
-    assert render(page_live) =~ "Welcome to Phoenix!"
-
-    Shift73k.Accounts.logout_user(user1)
-
-    # Assert our liveview is alive
-    ref = Process.monitor(page_live.pid)
-    refute_receive {:DOWN, ^ref, _, _, _}
-    assert Process.alive?(page_live.pid)
-
-    # If we are able to rerender the page it means nothing happened
-    assert render(page_live) =~ "Welcome to Phoenix!"
-  end
-end