feat: sort header for members list

This commit is contained in:
carla 2025-09-26 11:10:14 +02:00 committed by moritz
parent 687d653fb7
commit d9e48a37d2
3 changed files with 327 additions and 52 deletions

View file

@ -0,0 +1,64 @@
defmodule MvWeb.Components.SortHeaderComponent do
@moduledoc """
Sort Header that can be used as column header and sorts a table:
Props:
- field: atom() # AshField for sorting
- label: string() # Column Heading (can be aan heex templyte)
- sort_field: atom() | nil # current sort-field from parent liveview
- sort_order: :asc | :desc | nil # current sorting order
"""
use MvWeb, :live_component
@impl true
def update(assigns, socket) do
{:ok, assign(socket, assigns)}
end
@impl true
def render(assigns) do
~H"""
<button
type="button"
aria-sort={aria_sort(@field, @sort_field, @sort_order)}
class="btn btn-ghost select-none"
phx-click="sort"
phx-value-field={@field}
phx-target={@myself}
>
{@label}
<%= if @sort_field == @field do %>
<.icon name={if @sort_order == :asc, do: "hero-chevron-up", else: "hero-chevron-down"} />
<% else %>
<.icon name="hero-chevron-up-down" class="opacity-40" />
<% end %>
<!-- Screen Reader Info -->
<span class="sr-only">
({if @sort_field == @field do
if @sort_order == :asc, do: gettext("ascending"), else: gettext("descending")
else
gettext("not sorted")
end})
</span>
</button>
"""
end
@impl true
def handle_event("sort", %{"field" => field_str}, socket) do
send(self(), {:sort, field_str})
{:noreply, socket}
end
# -------------------------------------------------
# Hilfsfunktionen für ARIAAttribute & IconSVG
# -------------------------------------------------
defp aria_sort(field, sort_field, dir) when field == sort_field do
case dir do
:asc -> "ascending"
:desc -> "descending"
end
end
defp aria_sort(_, _, _), do: "none"
end