diff --git a/lib/mv_web/live/components/sort_header_component.ex b/lib/mv_web/live/components/sort_header_component.ex
index e69357e..3439d91 100644
--- a/lib/mv_web/live/components/sort_header_component.ex
+++ b/lib/mv_web/live/components/sort_header_component.ex
@@ -2,9 +2,9 @@ defmodule MvWeb.Components.SortHeaderComponent do
@moduledoc """
Sort Header that can be used as column header and sorts a table:
Props:
- - field: atom() # Ash‑Field for sorting
- - label: string() # Column Heading (can be aan heex templyte)
- - sort_field: atom() | nil # current sort-field from parent liveview
+ - field: atom() # Ash Field for sorting
+ - label: string() # Column Heading (can be an heex template)
+ - sort_field: atom() | nil # current sort field from parent liveview
- sort_order: :asc | :desc | nil # current sorting order
"""
use MvWeb, :live_component
@@ -19,25 +19,27 @@ defmodule MvWeb.Components.SortHeaderComponent do
@impl true
def render(assigns) do
~H"""
-
+
+
+
"""
end
@@ -48,7 +50,7 @@ defmodule MvWeb.Components.SortHeaderComponent do
end
# -------------------------------------------------
- # Hilfsfunktionen für ARIA‑Attribute & Icon‑SVG
+ # Hilfsfunktionen für ARIA Attribute & Icon SVG
# -------------------------------------------------
defp aria_sort(field, sort_field, dir) when field == sort_field do
case dir do
diff --git a/lib/mv_web/live/member_live/index.ex b/lib/mv_web/live/member_live/index.ex
index 7a0de39..4a05e29 100644
--- a/lib/mv_web/live/member_live/index.ex
+++ b/lib/mv_web/live/member_live/index.ex
@@ -4,7 +4,7 @@ defmodule MvWeb.MemberLive.Index do
import Ash.Query
@impl true
- def mount(params, _session, socket) do
+ def mount(_params, _session, socket) do
socket =
socket
|> assign(:page_title, gettext("Members"))
@@ -14,7 +14,6 @@ defmodule MvWeb.MemberLive.Index do
|> assign(:selected_members, [])
# We call handle params to use the query from the URL
- {:noreply, socket} = handle_params(params, nil, socket)
{:ok, socket}
end
@@ -70,6 +69,7 @@ defmodule MvWeb.MemberLive.Index do
@impl true
def handle_info({:sort, field_str}, socket) do
field = String.to_existing_atom(field_str)
+ old_field = socket.assigns.sort_field
{new_order, new_field} =
if socket.assigns.sort_field == field do
@@ -79,28 +79,38 @@ defmodule MvWeb.MemberLive.Index do
end
active_id = :"sort_#{new_field}"
+ old_id = :"sort_#{old_field}"
- # Update the SortHeader to
+ # Update the new SortHeader
send_update(MvWeb.Components.SortHeaderComponent,
id: active_id,
sort_field: new_field,
sort_order: new_order
)
+ # Reset the current SortHeader
+ send_update(MvWeb.Components.SortHeaderComponent,
+ id: old_id,
+ sort_field: new_field,
+ sort_order: new_order
+ )
+
+ existing_search_query = socket.assigns.query
+
# Build the URL with queries
query_params = %{
+ "query" => existing_search_query,
"sort_field" => Atom.to_string(new_field),
"sort_order" => Atom.to_string(new_order)
}
- # "/members" is the path you defined in router.ex
- new_path = "/members?" <> URI.encode_query(query_params)
+ # Set the new path with params
+ new_path = ~p"/members?#{query_params}"
# Push the new URL
{:noreply,
push_patch(socket,
to: new_path,
- # replace true
replace: true
)}
end
@@ -108,19 +118,27 @@ defmodule MvWeb.MemberLive.Index do
# Function to handle search
@impl true
def handle_info({:search_changed, q}, socket) do
- members =
- if String.trim(q) == "" do
- Ash.read!(Mv.Membership.Member)
- else
- Mv.Membership.Member
- |> filter(expr(fragment("search_vector @@ plainto_tsquery('simple', ?)", ^q)))
- |> Ash.read!()
- end
+ socket = load_members(socket, q)
+ existing_field_query = socket.assigns.sort_field
+ existing_sort_query = socket.assigns.sort_order
+
+ # Build the URL with queries
+ query_params = %{
+ "query" => q,
+ "sort_field" => existing_field_query,
+ "sort_order" => existing_sort_query
+ }
+
+ # Set the new path with params
+ new_path = ~p"/members?#{query_params}"
+
+ # Push the new URL
{:noreply,
- socket
- |> assign(:query, q)
- |> assign(:members, members)}
+ push_patch(socket,
+ to: new_path,
+ replace: true
+ )}
end
# -----------------------------------------------------------------
@@ -130,8 +148,9 @@ defmodule MvWeb.MemberLive.Index do
def handle_params(params, _url, socket) do
socket =
socket
+ |> maybe_update_search(params)
|> maybe_update_sort(params)
- |> load_members()
+ |> load_members(params["query"])
{:noreply, socket}
end
@@ -140,7 +159,7 @@ defmodule MvWeb.MemberLive.Index do
# FUNCTIONS
# -------------------------------------------------------------
# Load members eg based on a query for sorting
- defp load_members(socket) do
+ defp load_members(socket, search_query) do
query =
Mv.Membership.Member
|> Ash.Query.new()
@@ -156,7 +175,12 @@ defmodule MvWeb.MemberLive.Index do
:phone_number,
:join_date
])
- |> maybe_sort(socket.assigns.sort_field, socket.assigns.sort_order)
+
+ # Apply the search filter first
+ query = apply_search_filter(query, search_query)
+
+ # Apply sorting based on current socket state
+ query = maybe_sort(query, socket.assigns.sort_field, socket.assigns.sort_order)
members = Ash.read!(query)
assign(socket, :members, members)
@@ -166,6 +190,16 @@ defmodule MvWeb.MemberLive.Index do
# Helper Functions
# -------------------------------------------------------------
+ # Function to apply search query
+ defp apply_search_filter(query, search_query) do
+ if search_query && String.trim(search_query) != "" do
+ query
+ |> filter(expr(fragment("search_vector @@ plainto_tsquery('simple', ?)", ^search_query)))
+ else
+ query
+ end
+ end
+
# Functions to toggle sorting order
defp toggle_order(:asc), do: :desc
defp toggle_order(:desc), do: :asc
@@ -193,4 +227,14 @@ defmodule MvWeb.MemberLive.Index do
end
defp maybe_update_sort(socket, _), do: socket
+
+ # Function to update search parameters
+ defp maybe_update_search(socket, %{"query" => query}) when query != "" do
+ assign(socket, :query, query)
+ end
+
+ defp maybe_update_search(socket, _params) do
+ # Keep the previous search query if no new one is provided
+ socket
+ end
end