diff --git a/lib/app/item.ex b/lib/app/item.ex
index 2dbb245a..ab40827f 100644
--- a/lib/app/item.ex
+++ b/lib/app/item.ex
@@ -10,11 +10,11 @@ defmodule App.Item do
@derive {Jason.Encoder,
except: [:__meta__, :__struct__, :timer, :inserted_at, :updated_at]}
schema "items" do
- field :person_id, :integer
- field :status, :integer
- field :text, :string
+ field(:person_id, :integer)
+ field(:status, :integer)
+ field(:text, :string)
- has_many :timer, Timer
+ has_many(:timer, Timer)
many_to_many(:tags, Tag, join_through: ItemTag, on_replace: :delete)
timestamps()
@@ -236,12 +236,18 @@ defmodule App.Item do
%{name: username, num_items: 1, num_timers: 3, person_id: 1}
]
"""
- def person_with_item_and_timer_count(sort_column \\ :person_id) do
+ def person_with_item_and_timer_count(
+ sort_column \\ :person_id,
+ sort_order \\ :asc
+ ) do
sort_column = to_string(sort_column)
+ sort_order = to_string(sort_order)
sort_column =
if validate_sort_column(sort_column), do: sort_column, else: "person_id"
+ sort_order = if validate_order(sort_order), do: sort_order, else: "asc"
+
sql = """
SELECT i.person_id,
COUNT(distinct i.id) AS "num_items",
@@ -252,7 +258,7 @@ defmodule App.Item do
FROM items i
LEFT JOIN timers t ON t.item_id = i.id
GROUP BY i.person_id
- ORDER BY #{sort_column} ASC
+ ORDER BY #{sort_column} #{sort_order}
"""
Ecto.Adapters.SQL.query!(Repo, sql)
@@ -389,4 +395,11 @@ defmodule App.Item do
column
)
end
+
+ defp validate_order(order) do
+ Enum.member?(
+ ~w(asc desc),
+ order
+ )
+ end
end
diff --git a/lib/app_web/live/stats_live.ex b/lib/app_web/live/stats_live.ex
index b1c45684..c2b6f8d9 100644
--- a/lib/app_web/live/stats_live.ex
+++ b/lib/app_web/live/stats_live.ex
@@ -22,7 +22,9 @@ defmodule AppWeb.StatsLive do
{:ok,
assign(socket,
person_id: person_id,
- metrics: metrics
+ metrics: metrics,
+ sort_column: :person_id,
+ sort_order: :asc
)}
end
@@ -66,14 +68,24 @@ defmodule AppWeb.StatsLive do
@impl true
def handle_event("sort", %{"key" => key}, socket) do
- metrics =
+ sort_column =
key
|> String.to_atom()
- |> Item.person_with_item_and_timer_count()
+
+ sort_order =
+ if socket.assigns.sort_column == sort_column do
+ toggle_sort_order(socket.assigns.sort_order)
+ else
+ :asc
+ end
+
+ metrics = Item.person_with_item_and_timer_count(sort_column, sort_order)
{:noreply,
assign(socket,
- metrics: metrics
+ metrics: metrics,
+ sort_column: sort_column,
+ sort_order: sort_order
)}
end
@@ -102,4 +114,7 @@ defmodule AppWeb.StatsLive do
def is_highlighted_person?(metric, person_id),
do: metric.person_id == person_id
+
+ defp toggle_sort_order(:asc), do: :desc
+ defp toggle_sort_order(:desc), do: :asc
end
diff --git a/lib/app_web/live/stats_live.html.heex b/lib/app_web/live/stats_live.html.heex
index ad46b7e6..49360636 100644
--- a/lib/app_web/live/stats_live.html.heex
+++ b/lib/app_web/live/stats_live.html.heex
@@ -8,6 +8,8 @@
module={AppWeb.TableComponent}
id="table_component"
rows={@metrics}
+ sort_column={@sort_column}
+ sort_order={@sort_order}
highlight={&is_highlighted_person?(&1, @person_id)}
>
<:column :let={metric} label="Id" key="person_id">
diff --git a/lib/app_web/templates/table_component/arrow_down.html.heex b/lib/app_web/templates/table_component/arrow_down.html.heex
new file mode 100644
index 00000000..2d4d4faa
--- /dev/null
+++ b/lib/app_web/templates/table_component/arrow_down.html.heex
@@ -0,0 +1,14 @@
+
+
+
diff --git a/lib/app_web/templates/table_component/arrow_up.html.heex b/lib/app_web/templates/table_component/arrow_up.html.heex
new file mode 100644
index 00000000..9d500c75
--- /dev/null
+++ b/lib/app_web/templates/table_component/arrow_up.html.heex
@@ -0,0 +1,31 @@
+<%= if @invisible do %>
+
+
+
+<% else %>
+
+
+
+<% end %>
diff --git a/lib/app_web/templates/table_component/table_component.html.heex b/lib/app_web/templates/table_component/table_component.html.heex
index 9c6c265e..92c2a7b7 100644
--- a/lib/app_web/templates/table_component/table_component.html.heex
+++ b/lib/app_web/templates/table_component/table_component.html.heex
@@ -7,7 +7,19 @@
phx-click="sort"
phx-value-key={column.key}
>
- <%= column.label %>
+
+ <%= column.label %>
+
+ <%= if @sort_column == String.to_atom(column.key) do %>
+ <%= if @sort_order == :asc do %>
+ <%= render_arrow_up() %>
+ <% else %>
+ <%= render_arrow_down() %>
+ <% end %>
+ <% else %>
+ <%= render_arrow_up(:invisible) %>
+ <% end %>
+
<% end %>
diff --git a/lib/app_web/views/table_component_view.ex b/lib/app_web/views/table_component_view.ex
index 60b10630..d8b3c67e 100644
--- a/lib/app_web/views/table_component_view.ex
+++ b/lib/app_web/views/table_component_view.ex
@@ -1,3 +1,19 @@
defmodule AppWeb.TableComponentView do
use AppWeb, :view
+
+ def render_arrow_down() do
+ Phoenix.View.render(AppWeb.TableComponentView, "arrow_down.html", %{})
+ end
+
+ def render_arrow_up() do
+ Phoenix.View.render(AppWeb.TableComponentView, "arrow_up.html", %{
+ invisible: false
+ })
+ end
+
+ def render_arrow_up(:invisible) do
+ Phoenix.View.render(AppWeb.TableComponentView, "arrow_up.html", %{
+ invisible: true
+ })
+ end
end