From d9e48a37d2a190e062fe87583fe8ff715132d1d8 Mon Sep 17 00:00:00 2001 From: carla Date: Fri, 26 Sep 2025 11:10:14 +0200 Subject: [PATCH 01/11] feat: sort header for members list --- .../live/components/sort_header_component.ex | 64 +++++++ lib/mv_web/live/member_live/index.ex | 173 ++++++++++++++---- lib/mv_web/live/member_live/index.html.heex | 142 ++++++++++++-- 3 files changed, 327 insertions(+), 52 deletions(-) create mode 100644 lib/mv_web/live/components/sort_header_component.ex diff --git a/lib/mv_web/live/components/sort_header_component.ex b/lib/mv_web/live/components/sort_header_component.ex new file mode 100644 index 0000000..147001e --- /dev/null +++ b/lib/mv_web/live/components/sort_header_component.ex @@ -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() # Ash‑Field 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""" + + """ + end + + @impl true + def handle_event("sort", %{"field" => field_str}, socket) do + send(self(), {:sort, field_str}) + {:noreply, socket} + end + + # ------------------------------------------------- + # Hilfsfunktionen für ARIA‑Attribute & Icon‑SVG + # ------------------------------------------------- + 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 diff --git a/lib/mv_web/live/member_live/index.ex b/lib/mv_web/live/member_live/index.ex index 47a36ef..066b5e3 100644 --- a/lib/mv_web/live/member_live/index.ex +++ b/lib/mv_web/live/member_live/index.ex @@ -5,18 +5,18 @@ defmodule MvWeb.MemberLive.Index do import MvWeb.TableComponents @impl true - def mount(_params, _session, socket) do - members = Ash.read!(Mv.Membership.Member) - sorted = Enum.sort_by(members, & &1.first_name) - - {:ok, - socket - |> assign(:page_title, gettext("Members")) + def mount(params, _session, socket) do + socket = + socket + |> assign(:page_title, gettext("Members")) |> assign(:query, "") - |> assign(:sort_field, :first_name) - |> assign(:sort_order, :asc) - |> assign(:members, sorted) - |> assign(:selected_members, [])} + |> assign_new(:sort_field, fn -> :first_name end) + |> assign_new(:sort_order, fn -> :asc end) + |> assign(:selected_members, []) + + # We call handle params to use the query from the URL + {:noreply, socket} = handle_params(params, nil, socket) + {:ok, socket} end # ----------------------------------------------------------------- @@ -45,6 +45,11 @@ defmodule MvWeb.MemberLive.Index do # Handle Events # ----------------------------------------------------------------- + # ----------------------------------------------------------------- + # Handle Events + # ----------------------------------------------------------------- + + # Delete a member @impl true def handle_event("delete", %{"id" => id}, socket) do member = Ash.get!(Mv.Membership.Member, id) @@ -67,32 +72,7 @@ defmodule MvWeb.MemberLive.Index do {:noreply, assign(socket, :selected_members, selected)} end - # Sorts the list of members according to a field, when you click on the column header - @impl true - def handle_event("sort", %{"field" => field_str}, socket) do - members = socket.assigns.members - field = String.to_existing_atom(field_str) - - new_order = - if socket.assigns.sort_field == field do - toggle_order(socket.assigns.sort_order) - else - :asc - end - - sorted_members = - members - |> Enum.sort_by(&Map.get(&1, field), sort_fun(new_order)) - - {:noreply, - socket - |> assign(:sort_field, field) - |> assign(:sort_order, new_order) - |> assign(:members, sorted_members)} - end - - # Selects all members in the list of members - + # Selects all members in the list of members @impl true def handle_event("select_all", _params, socket) do members = socket.assigns.members @@ -109,8 +89,123 @@ defmodule MvWeb.MemberLive.Index do {:noreply, assign(socket, :selected_members, selected)} end + # ----------------------------------------------------------------- + # Handle Infos from Child Components + # ----------------------------------------------------------------- + + # Sorts the list of members according to a field, when you click on the column header + @impl true + def handle_info({:sort, field_str}, socket) do + field = String.to_existing_atom(field_str) + + {new_order, new_field} = + if socket.assigns.sort_field == field do + {toggle_order(socket.assigns.sort_order), field} + else + {:asc, field} + end + + active_id = :"sort_#{new_field}" + + # Update the SortHeader to + send_update(MvWeb.Components.SortHeaderComponent, + id: active_id, + sort_field: new_field, + sort_order: new_order + ) + + # Build the URL with queries + query_params = %{ + "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) + + # Push the new URL + {:noreply, + push_patch(socket, + to: new_path, + # replace true + replace: true + )} + end + + # ----------------------------------------------------------------- + # Handle Params from the URL + # ----------------------------------------------------------------- + @impl true + def handle_params(params, _url, socket) do + socket = + socket + |> maybe_update_sort(params) + |> load_members() + + {:noreply, socket} + end + + # ------------------------------------------------------------- + # FUNCTIONS + # ------------------------------------------------------------- + # Load members eg based on a query for sorting + defp load_members(socket) do + query = + Mv.Membership.Member + |> Ash.Query.new() + |> Ash.Query.select([ + :id, + :first_name, + :last_name, + :email, + :street, + :house_number, + :postal_code, + :city, + :phone_number, + :join_date + ]) + |> maybe_sort(socket.assigns.sort_field, socket.assigns.sort_order) + + members = Ash.read!(query) + assign(socket, :members, members) + end + + defp maybe_update_sort(socket, %{"sort_field" => sf, "sort_order" => so}) do + field = + try do + String.to_existing_atom(sf) + rescue + ArgumentError -> socket.assigns.sort_field + end + + order = if so in ["asc", "desc"], do: String.to_atom(so), else: socket.assigns.sort_order + + IO.inspect(order) + + socket + |> assign(:sort_field, field) + |> assign(:sort_order, order) + end + + # ------------------------------------------------------------- + # Helper Functions + # ------------------------------------------------------------- + + # Functions to toggle sorting order defp toggle_order(:asc), do: :desc defp toggle_order(:desc), do: :asc - defp sort_fun(:asc), do: &<=/2 - defp sort_fun(:desc), do: &>=/2 + defp toggle_order(nil), do: :asc + + # Function to turn a string into an atom only if it already exists + defp maybe_atom(nil), do: nil + defp maybe_atom(atom) when is_atom(atom), do: atom + defp maybe_atom(str) when is_binary(str), do: String.to_existing_atom(str) + + # Function to sort the column if needed + defp maybe_sort(query, nil, _), do: query + defp maybe_sort(query, field, :asc), do: Ash.Query.sort(query, [{field, :asc}]) + defp maybe_sort(query, field, :desc), do: Ash.Query.sort(query, [{field, :desc}]) + # no changes + defp maybe_update_sort(socket, _), do: socket end diff --git a/lib/mv_web/live/member_live/index.html.heex b/lib/mv_web/live/member_live/index.html.heex index 410728a..cb2ccd8 100644 --- a/lib/mv_web/live/member_live/index.html.heex +++ b/lib/mv_web/live/member_live/index.html.heex @@ -52,23 +52,139 @@ <:col :let={member} label={ - sort_button(%{ - field: :first_name, - label: gettext("Name"), - sort_field: @sort_field, - sort_order: @sort_order - }) + ~H""" + <.live_component + module={MvWeb.Components.SortHeaderComponent} + id={:sort_first_name} + field={:first_name} + label={gettext("First name")} + sort_field={@sort_field} + sort_order={@sort_order} + /> + """ } > {member.first_name} {member.last_name} - <:col :let={member} label={gettext("Email")}>{member.email} - <:col :let={member} label={gettext("Street")}>{member.street} - <:col :let={member} label={gettext("House Number")}>{member.house_number} - <:col :let={member} label={gettext("Postal Code")}>{member.postal_code} - <:col :let={member} label={gettext("City")}>{member.city} - <:col :let={member} label={gettext("Phone Number")}>{member.phone_number} - <:col :let={member} label={gettext("Join Date")}>{member.join_date} + <:col + :let={member} + label={ + ~H""" + <.live_component + module={MvWeb.Components.SortHeaderComponent} + id={:sort_email} + field={:email} + label={gettext("Email")} + sort_field={@sort_field} + sort_order={@sort_order} + /> + """ + } + > + {member.email} + + <:col + :let={member} + label={ + ~H""" + <.live_component + module={MvWeb.Components.SortHeaderComponent} + id={:sort_street} + field={:street} + label={gettext("Street")} + sort_field={@sort_field} + sort_order={@sort_order} + /> + """ + } + > + {member.street} + + <:col + :let={member} + label={ + ~H""" + <.live_component + module={MvWeb.Components.SortHeaderComponent} + id={:sort_house_number} + field={:house_number} + label={gettext("House Number")} + sort_field={@sort_field} + sort_order={@sort_order} + /> + """ + } + > + {member.house_number} + + <:col + :let={member} + label={ + ~H""" + <.live_component + module={MvWeb.Components.SortHeaderComponent} + id={:sort_postal_code} + field={:postal_code} + label={gettext("Postal Code")} + sort_field={@sort_field} + sort_order={@sort_order} + /> + """ + } + > + {member.postal_code} + + <:col + :let={member} + label={ + ~H""" + <.live_component + module={MvWeb.Components.SortHeaderComponent} + id={:sort_city} + field={:city} + label={gettext("City")} + sort_field={@sort_field} + sort_order={@sort_order} + /> + """ + } + > + {member.city} + + <:col + :let={member} + label={ + ~H""" + <.live_component + module={MvWeb.Components.SortHeaderComponent} + id={:sort_phone_number} + field={:phone_number} + label={gettext("Phone Number")} + sort_field={@sort_field} + sort_order={@sort_order} + /> + """ + } + > + {member.phone_number} + + <:col + :let={member} + label={ + ~H""" + <.live_component + module={MvWeb.Components.SortHeaderComponent} + id={:sort_join_date} + field={:join_date} + label={gettext("Join Date")} + sort_field={@sort_field} + sort_order={@sort_order} + /> + """ + } + > + {member.join_date} + <:action :let={member}>
-- 2.47.2 From c3502a326e183af333f9abf276870741260956ba Mon Sep 17 00:00:00 2001 From: carla Date: Tue, 30 Sep 2025 16:19:36 +0200 Subject: [PATCH 02/11] docs: formatting, docs and accessibility fix --- .../live/components/sort_header_component.ex | 25 ++++++------- lib/mv_web/live/member_live/index.ex | 36 ++++++++----------- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/lib/mv_web/live/components/sort_header_component.ex b/lib/mv_web/live/components/sort_header_component.ex index 147001e..e69357e 100644 --- a/lib/mv_web/live/components/sort_header_component.ex +++ b/lib/mv_web/live/components/sort_header_component.ex @@ -14,32 +14,29 @@ defmodule MvWeb.Components.SortHeaderComponent do {:ok, assign(socket, assigns)} end + # Check if we can add the aria-sort label directly to the daisyUI header + # aria-sort={aria_sort(@field, @sort_field, @sort_order)} @impl true def render(assigns) do ~H""" """ end @@ -55,10 +52,10 @@ defmodule MvWeb.Components.SortHeaderComponent do # ------------------------------------------------- defp aria_sort(field, sort_field, dir) when field == sort_field do case dir do - :asc -> "ascending" - :desc -> "descending" + :asc -> gettext("ascending") + :desc -> gettext("descending") end end - defp aria_sort(_, _, _), do: "none" + defp aria_sort(_, _, _), do: gettext("Click to sort") end diff --git a/lib/mv_web/live/member_live/index.ex b/lib/mv_web/live/member_live/index.ex index 066b5e3..52b16ae 100644 --- a/lib/mv_web/live/member_live/index.ex +++ b/lib/mv_web/live/member_live/index.ex @@ -171,6 +171,21 @@ defmodule MvWeb.MemberLive.Index do assign(socket, :members, members) end + # ------------------------------------------------------------- + # Helper Functions + # ------------------------------------------------------------- + + # Functions to toggle sorting order + defp toggle_order(:asc), do: :desc + defp toggle_order(:desc), do: :asc + defp toggle_order(nil), do: :asc + + # Function to sort the column if needed + defp maybe_sort(query, nil, _), do: query + defp maybe_sort(query, field, :asc), do: Ash.Query.sort(query, [{field, :asc}]) + defp maybe_sort(query, field, :desc), do: Ash.Query.sort(query, [{field, :desc}]) + + # Function to maybe update the sort defp maybe_update_sort(socket, %{"sort_field" => sf, "sort_order" => so}) do field = try do @@ -181,31 +196,10 @@ defmodule MvWeb.MemberLive.Index do order = if so in ["asc", "desc"], do: String.to_atom(so), else: socket.assigns.sort_order - IO.inspect(order) - socket |> assign(:sort_field, field) |> assign(:sort_order, order) end - # ------------------------------------------------------------- - # Helper Functions - # ------------------------------------------------------------- - - # Functions to toggle sorting order - defp toggle_order(:asc), do: :desc - defp toggle_order(:desc), do: :asc - defp toggle_order(nil), do: :asc - - # Function to turn a string into an atom only if it already exists - defp maybe_atom(nil), do: nil - defp maybe_atom(atom) when is_atom(atom), do: atom - defp maybe_atom(str) when is_binary(str), do: String.to_existing_atom(str) - - # Function to sort the column if needed - defp maybe_sort(query, nil, _), do: query - defp maybe_sort(query, field, :asc), do: Ash.Query.sort(query, [{field, :asc}]) - defp maybe_sort(query, field, :desc), do: Ash.Query.sort(query, [{field, :desc}]) - # no changes defp maybe_update_sort(socket, _), do: socket end -- 2.47.2 From 3cfae95b1e9596333986265d934c973efd01a233 Mon Sep 17 00:00:00 2001 From: carla Date: Tue, 30 Sep 2025 16:19:52 +0200 Subject: [PATCH 03/11] test: added tests --- .../components/sort_header_component_test.exs | 12 ++++++ test/mv_web/member_live/index_test.exs | 37 ++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test/mv_web/components/sort_header_component_test.exs diff --git a/test/mv_web/components/sort_header_component_test.exs b/test/mv_web/components/sort_header_component_test.exs new file mode 100644 index 0000000..9b1c006 --- /dev/null +++ b/test/mv_web/components/sort_header_component_test.exs @@ -0,0 +1,12 @@ +defmodule MvWeb.Components.SortHeaderComponentTest do + use MvWeb.ConnCase, async: true + use Phoenix.Component + import Phoenix.LiveViewTest + + test "renders sort header with correct attributes", %{conn: conn} do + conn = conn_with_oidc_user(conn) + {:ok, view, _html} = live(conn, "/members") + + assert view |> element("[data-testid='first_name']") + end +end diff --git a/test/mv_web/member_live/index_test.exs b/test/mv_web/member_live/index_test.exs index 240e15e..f697d6e 100644 --- a/test/mv_web/member_live/index_test.exs +++ b/test/mv_web/member_live/index_test.exs @@ -56,7 +56,6 @@ defmodule MvWeb.MemberLive.IndexTest do test "shows translated flash message after creating a member in English", %{conn: conn} do conn = conn_with_oidc_user(conn) - conn = Plug.Test.init_test_session(conn, locale: "en") {:ok, form_view, _html} = live(conn, "/members/new") form_data = %{ @@ -75,6 +74,42 @@ defmodule MvWeb.MemberLive.IndexTest do assert has_element?(index_view, "#flash-group", "Member create successfully") end + describe "sorting interaction" do + test "clicking a column header toggles sort order and updates the URL", %{conn: conn} do + conn = conn_with_oidc_user(conn) + {:ok, view, _html} = live(conn, "/members") + + # The component data test ids are built as "" + # First click – should sort ASC + view + |> element("[data-testid='email']") + |> render_click() + + # The LiveView pushes a patch with the new query params + assert_patch(view, "/members?sort_field=email&sort_order=asc") + + # Second click – toggles to DESC + view + |> element("[data-testid='email']") + |> render_click() + + assert_patch(view, "/members?sort_field=email&sort_order=desc") + end + end + + describe "URL param handling" do + test "handle_params reads sort query and applies it", %{conn: conn} do + conn = conn_with_oidc_user(conn) + url = "/members?sort_field=email&sort_order=desc" + + conn = get(conn, url) + + # The LiveView must have parsed the params and stored them as atoms. + assert conn.assigns.sort_field == :email + assert conn.assigns.sort_order == :desc + end + end + test "handle_info(:search_changed) updates assigns with search results", %{conn: conn} do conn = conn_with_oidc_user(conn) {:ok, view, _html} = live(conn, "/members") -- 2.47.2 From 017ca8b32c63e2da4a38162615a81607893fbc37 Mon Sep 17 00:00:00 2001 From: carla Date: Tue, 30 Sep 2025 16:23:33 +0200 Subject: [PATCH 04/11] chore: updated translation --- priv/gettext/de/LC_MESSAGES/auth.po | 3 + priv/gettext/de/LC_MESSAGES/default.po | 58 ++++++++------ priv/gettext/default.pot | 51 +++++++----- priv/gettext/en/LC_MESSAGES/auth.po | 3 + priv/gettext/en/LC_MESSAGES/default.po | 105 ++++++++----------------- 5 files changed, 101 insertions(+), 119 deletions(-) diff --git a/priv/gettext/de/LC_MESSAGES/auth.po b/priv/gettext/de/LC_MESSAGES/auth.po index f7eef3e..967755e 100644 --- a/priv/gettext/de/LC_MESSAGES/auth.po +++ b/priv/gettext/de/LC_MESSAGES/auth.po @@ -61,3 +61,6 @@ msgstr "Anmelden..." msgid "Your password has successfully been reset" msgstr "Das Passwort wurde erfolgreich zurückgesetzt" + +#~ msgid "Sign in with Rauthy" +#~ msgstr "Anmelden mit der Vereinscloud" diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index bd86f61..c8c219a 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -15,7 +15,7 @@ msgstr "" msgid "Actions" msgstr "Aktionen" -#: lib/mv_web/live/member_live/index.html.heex:84 +#: lib/mv_web/live/member_live/index.html.heex:193 #: lib/mv_web/live/user_live/index.html.heex:65 #, elixir-autogen, elixir-format msgid "Are you sure?" @@ -28,19 +28,19 @@ msgid "Attempting to reconnect" msgstr "Verbindung wird wiederhergestellt" #: lib/mv_web/live/member_live/form.ex:25 -#: lib/mv_web/live/member_live/index.html.heex:69 -#: lib/mv_web/live/member_live/show.ex:37 +#: lib/mv_web/live/member_live/index.html.heex:138 +#: lib/mv_web/live/member_live/show.ex:36 #, elixir-autogen, elixir-format msgid "City" msgstr "Stadt" -#: lib/mv_web/live/member_live/index.html.heex:86 +#: lib/mv_web/live/member_live/index.html.heex:195 #: lib/mv_web/live/user_live/index.html.heex:67 #, elixir-autogen, elixir-format msgid "Delete" msgstr "Löschen" -#: lib/mv_web/live/member_live/index.html.heex:78 +#: lib/mv_web/live/member_live/index.html.heex:187 #: lib/mv_web/live/user_live/form.ex:109 #: lib/mv_web/live/user_live/index.html.heex:59 #, elixir-autogen, elixir-format @@ -54,8 +54,8 @@ msgid "Edit Member" msgstr "Mitglied bearbeiten" #: lib/mv_web/live/member_live/form.ex:18 -#: lib/mv_web/live/member_live/index.html.heex:65 -#: lib/mv_web/live/member_live/show.ex:28 +#: lib/mv_web/live/member_live/index.html.heex:70 +#: lib/mv_web/live/member_live/show.ex:27 #: lib/mv_web/live/user_live/form.ex:14 #: lib/mv_web/live/user_live/index.html.heex:44 #: lib/mv_web/live/user_live/show.ex:25 @@ -70,8 +70,8 @@ msgid "First Name" msgstr "Vorname" #: lib/mv_web/live/member_live/form.ex:22 -#: lib/mv_web/live/member_live/index.html.heex:71 -#: lib/mv_web/live/member_live/show.ex:34 +#: lib/mv_web/live/member_live/index.html.heex:172 +#: lib/mv_web/live/member_live/show.ex:33 #, elixir-autogen, elixir-format msgid "Join Date" msgstr "Beitrittsdatum" @@ -87,7 +87,7 @@ msgstr "Nachname" msgid "New Member" msgstr "Neues Mitglied" -#: lib/mv_web/live/member_live/index.html.heex:75 +#: lib/mv_web/live/member_live/index.html.heex:184 #: lib/mv_web/live/user_live/index.html.heex:56 #, elixir-autogen, elixir-format msgid "Show" @@ -127,8 +127,8 @@ msgid "Exit Date" msgstr "Austrittsdatum" #: lib/mv_web/live/member_live/form.ex:27 -#: lib/mv_web/live/member_live/index.html.heex:67 -#: lib/mv_web/live/member_live/show.ex:39 +#: lib/mv_web/live/member_live/index.html.heex:104 +#: lib/mv_web/live/member_live/show.ex:38 #, elixir-autogen, elixir-format msgid "House Number" msgstr "Hausnummer" @@ -146,15 +146,15 @@ msgid "Paid" msgstr "Bezahlt" #: lib/mv_web/live/member_live/form.ex:21 -#: lib/mv_web/live/member_live/index.html.heex:70 -#: lib/mv_web/live/member_live/show.ex:33 +#: lib/mv_web/live/member_live/index.html.heex:155 +#: lib/mv_web/live/member_live/show.ex:32 #, elixir-autogen, elixir-format msgid "Phone Number" msgstr "Telefonnummer" #: lib/mv_web/live/member_live/form.ex:28 -#: lib/mv_web/live/member_live/index.html.heex:68 -#: lib/mv_web/live/member_live/show.ex:40 +#: lib/mv_web/live/member_live/index.html.heex:121 +#: lib/mv_web/live/member_live/show.ex:39 #, elixir-autogen, elixir-format msgid "Postal Code" msgstr "Postleitzahl" @@ -173,8 +173,8 @@ msgid "Saving..." msgstr "Speichern..." #: lib/mv_web/live/member_live/form.ex:26 -#: lib/mv_web/live/member_live/index.html.heex:66 -#: lib/mv_web/live/member_live/show.ex:38 +#: lib/mv_web/live/member_live/index.html.heex:87 +#: lib/mv_web/live/member_live/show.ex:37 #, elixir-autogen, elixir-format msgid "Street" msgstr "Straße" @@ -317,14 +317,13 @@ msgstr "Benutzer*innen auflisten" msgid "Member" msgstr "Mitglied" -#: lib/mv_web/components/layouts/navbar.ex:19 -#: lib/mv_web/live/member_live/index.ex:14 +#: lib/mv_web/components/layouts/navbar.ex:14 +#: lib/mv_web/live/member_live/index.ex:8 #: lib/mv_web/live/member_live/index.html.heex:3 #, elixir-autogen, elixir-format msgid "Members" msgstr "Mitglieder" -#: lib/mv_web/live/member_live/index.html.heex:57 #: lib/mv_web/live/property_type_live/form.ex:16 #, elixir-autogen, elixir-format msgid "Name" @@ -469,11 +468,13 @@ msgid "Value type" msgstr "Wertetyp" #: lib/mv_web/components/table_components.ex:30 +#: lib/mv_web/live/components/sort_header_component.ex:55 #, elixir-autogen, elixir-format msgid "ascending" msgstr "aufsteigend" #: lib/mv_web/components/table_components.ex:30 +#: lib/mv_web/live/components/sort_header_component.ex:56 #, elixir-autogen, elixir-format msgid "descending" msgstr "absteigend" @@ -600,10 +601,15 @@ msgstr "Dunklen Modus umschalten" #: lib/mv_web/live/components/search_bar_component.ex:15 #: lib/mv_web/live/member_live/index.html.heex:15 #, elixir-autogen, elixir-format -msgid "Search..." -msgstr "" +msgid "Click to sort" +msgstr "Klicke um zu sortieren" -#: lib/mv_web/components/layouts/navbar.ex:20 +#: lib/mv_web/live/member_live/index.html.heex:53 #, elixir-autogen, elixir-format, fuzzy -msgid "Users" -msgstr "Benutzer*innen" +msgid "First name" +msgstr "Vorname" + +#~ #: lib/mv_web/auth_overrides.ex:30 +#~ #, elixir-autogen, elixir-format +#~ msgid "or" +#~ msgstr "oder" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index 93c5d95..4c5438a 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -16,7 +16,7 @@ msgstr "" msgid "Actions" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:84 +#: lib/mv_web/live/member_live/index.html.heex:193 #: lib/mv_web/live/user_live/index.html.heex:65 #, elixir-autogen, elixir-format msgid "Are you sure?" @@ -29,19 +29,19 @@ msgid "Attempting to reconnect" msgstr "" #: lib/mv_web/live/member_live/form.ex:25 -#: lib/mv_web/live/member_live/index.html.heex:69 -#: lib/mv_web/live/member_live/show.ex:37 +#: lib/mv_web/live/member_live/index.html.heex:138 +#: lib/mv_web/live/member_live/show.ex:36 #, elixir-autogen, elixir-format msgid "City" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:86 +#: lib/mv_web/live/member_live/index.html.heex:195 #: lib/mv_web/live/user_live/index.html.heex:67 #, elixir-autogen, elixir-format msgid "Delete" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:78 +#: lib/mv_web/live/member_live/index.html.heex:187 #: lib/mv_web/live/user_live/form.ex:109 #: lib/mv_web/live/user_live/index.html.heex:59 #, elixir-autogen, elixir-format @@ -55,8 +55,8 @@ msgid "Edit Member" msgstr "" #: lib/mv_web/live/member_live/form.ex:18 -#: lib/mv_web/live/member_live/index.html.heex:65 -#: lib/mv_web/live/member_live/show.ex:28 +#: lib/mv_web/live/member_live/index.html.heex:70 +#: lib/mv_web/live/member_live/show.ex:27 #: lib/mv_web/live/user_live/form.ex:14 #: lib/mv_web/live/user_live/index.html.heex:44 #: lib/mv_web/live/user_live/show.ex:25 @@ -71,8 +71,8 @@ msgid "First Name" msgstr "" #: lib/mv_web/live/member_live/form.ex:22 -#: lib/mv_web/live/member_live/index.html.heex:71 -#: lib/mv_web/live/member_live/show.ex:34 +#: lib/mv_web/live/member_live/index.html.heex:172 +#: lib/mv_web/live/member_live/show.ex:33 #, elixir-autogen, elixir-format msgid "Join Date" msgstr "" @@ -88,7 +88,7 @@ msgstr "" msgid "New Member" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:75 +#: lib/mv_web/live/member_live/index.html.heex:184 #: lib/mv_web/live/user_live/index.html.heex:56 #, elixir-autogen, elixir-format msgid "Show" @@ -128,8 +128,8 @@ msgid "Exit Date" msgstr "" #: lib/mv_web/live/member_live/form.ex:27 -#: lib/mv_web/live/member_live/index.html.heex:67 -#: lib/mv_web/live/member_live/show.ex:39 +#: lib/mv_web/live/member_live/index.html.heex:104 +#: lib/mv_web/live/member_live/show.ex:38 #, elixir-autogen, elixir-format msgid "House Number" msgstr "" @@ -147,15 +147,15 @@ msgid "Paid" msgstr "" #: lib/mv_web/live/member_live/form.ex:21 -#: lib/mv_web/live/member_live/index.html.heex:70 -#: lib/mv_web/live/member_live/show.ex:33 +#: lib/mv_web/live/member_live/index.html.heex:155 +#: lib/mv_web/live/member_live/show.ex:32 #, elixir-autogen, elixir-format msgid "Phone Number" msgstr "" #: lib/mv_web/live/member_live/form.ex:28 -#: lib/mv_web/live/member_live/index.html.heex:68 -#: lib/mv_web/live/member_live/show.ex:40 +#: lib/mv_web/live/member_live/index.html.heex:121 +#: lib/mv_web/live/member_live/show.ex:39 #, elixir-autogen, elixir-format msgid "Postal Code" msgstr "" @@ -174,8 +174,8 @@ msgid "Saving..." msgstr "" #: lib/mv_web/live/member_live/form.ex:26 -#: lib/mv_web/live/member_live/index.html.heex:66 -#: lib/mv_web/live/member_live/show.ex:38 +#: lib/mv_web/live/member_live/index.html.heex:87 +#: lib/mv_web/live/member_live/show.ex:37 #, elixir-autogen, elixir-format msgid "Street" msgstr "" @@ -318,14 +318,13 @@ msgstr "" msgid "Member" msgstr "" -#: lib/mv_web/components/layouts/navbar.ex:19 -#: lib/mv_web/live/member_live/index.ex:14 +#: lib/mv_web/components/layouts/navbar.ex:14 +#: lib/mv_web/live/member_live/index.ex:8 #: lib/mv_web/live/member_live/index.html.heex:3 #, elixir-autogen, elixir-format msgid "Members" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:57 #: lib/mv_web/live/property_type_live/form.ex:16 #, elixir-autogen, elixir-format msgid "Name" @@ -470,11 +469,13 @@ msgid "Value type" msgstr "" #: lib/mv_web/components/table_components.ex:30 +#: lib/mv_web/live/components/sort_header_component.ex:55 #, elixir-autogen, elixir-format msgid "ascending" msgstr "" #: lib/mv_web/components/table_components.ex:30 +#: lib/mv_web/live/components/sort_header_component.ex:56 #, elixir-autogen, elixir-format msgid "descending" msgstr "" @@ -607,4 +608,12 @@ msgstr "" #: lib/mv_web/components/layouts/navbar.ex:20 #, elixir-autogen, elixir-format msgid "Users" +#: lib/mv_web/live/components/sort_header_component.ex:60 +#, elixir-autogen, elixir-format +msgid "Click to sort" +msgstr "" + +#: lib/mv_web/live/member_live/index.html.heex:53 +#, elixir-autogen, elixir-format +msgid "First name" msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/auth.po b/priv/gettext/en/LC_MESSAGES/auth.po index 21bb4a4..59ce742 100644 --- a/priv/gettext/en/LC_MESSAGES/auth.po +++ b/priv/gettext/en/LC_MESSAGES/auth.po @@ -58,3 +58,6 @@ msgstr "" msgid "Your password has successfully been reset" msgstr "" + +#~ msgid "Sign in with Rauthy" +#~ msgstr "Sign in with Vereinscloud" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index ac30f5d..451ba84 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -16,7 +16,7 @@ msgstr "" msgid "Actions" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:84 +#: lib/mv_web/live/member_live/index.html.heex:193 #: lib/mv_web/live/user_live/index.html.heex:65 #, elixir-autogen, elixir-format msgid "Are you sure?" @@ -29,19 +29,19 @@ msgid "Attempting to reconnect" msgstr "" #: lib/mv_web/live/member_live/form.ex:25 -#: lib/mv_web/live/member_live/index.html.heex:69 -#: lib/mv_web/live/member_live/show.ex:37 +#: lib/mv_web/live/member_live/index.html.heex:138 +#: lib/mv_web/live/member_live/show.ex:36 #, elixir-autogen, elixir-format msgid "City" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:86 +#: lib/mv_web/live/member_live/index.html.heex:195 #: lib/mv_web/live/user_live/index.html.heex:67 #, elixir-autogen, elixir-format msgid "Delete" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:78 +#: lib/mv_web/live/member_live/index.html.heex:187 #: lib/mv_web/live/user_live/form.ex:109 #: lib/mv_web/live/user_live/index.html.heex:59 #, elixir-autogen, elixir-format @@ -55,8 +55,8 @@ msgid "Edit Member" msgstr "" #: lib/mv_web/live/member_live/form.ex:18 -#: lib/mv_web/live/member_live/index.html.heex:65 -#: lib/mv_web/live/member_live/show.ex:28 +#: lib/mv_web/live/member_live/index.html.heex:70 +#: lib/mv_web/live/member_live/show.ex:27 #: lib/mv_web/live/user_live/form.ex:14 #: lib/mv_web/live/user_live/index.html.heex:44 #: lib/mv_web/live/user_live/show.ex:25 @@ -71,8 +71,8 @@ msgid "First Name" msgstr "" #: lib/mv_web/live/member_live/form.ex:22 -#: lib/mv_web/live/member_live/index.html.heex:71 -#: lib/mv_web/live/member_live/show.ex:34 +#: lib/mv_web/live/member_live/index.html.heex:172 +#: lib/mv_web/live/member_live/show.ex:33 #, elixir-autogen, elixir-format msgid "Join Date" msgstr "" @@ -88,7 +88,7 @@ msgstr "" msgid "New Member" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:75 +#: lib/mv_web/live/member_live/index.html.heex:184 #: lib/mv_web/live/user_live/index.html.heex:56 #, elixir-autogen, elixir-format msgid "Show" @@ -128,8 +128,8 @@ msgid "Exit Date" msgstr "" #: lib/mv_web/live/member_live/form.ex:27 -#: lib/mv_web/live/member_live/index.html.heex:67 -#: lib/mv_web/live/member_live/show.ex:39 +#: lib/mv_web/live/member_live/index.html.heex:104 +#: lib/mv_web/live/member_live/show.ex:38 #, elixir-autogen, elixir-format msgid "House Number" msgstr "" @@ -147,15 +147,15 @@ msgid "Paid" msgstr "" #: lib/mv_web/live/member_live/form.ex:21 -#: lib/mv_web/live/member_live/index.html.heex:70 -#: lib/mv_web/live/member_live/show.ex:33 +#: lib/mv_web/live/member_live/index.html.heex:155 +#: lib/mv_web/live/member_live/show.ex:32 #, elixir-autogen, elixir-format msgid "Phone Number" msgstr "" #: lib/mv_web/live/member_live/form.ex:28 -#: lib/mv_web/live/member_live/index.html.heex:68 -#: lib/mv_web/live/member_live/show.ex:40 +#: lib/mv_web/live/member_live/index.html.heex:121 +#: lib/mv_web/live/member_live/show.ex:39 #, elixir-autogen, elixir-format msgid "Postal Code" msgstr "" @@ -174,8 +174,8 @@ msgid "Saving..." msgstr "" #: lib/mv_web/live/member_live/form.ex:26 -#: lib/mv_web/live/member_live/index.html.heex:66 -#: lib/mv_web/live/member_live/show.ex:38 +#: lib/mv_web/live/member_live/index.html.heex:87 +#: lib/mv_web/live/member_live/show.ex:37 #, elixir-autogen, elixir-format msgid "Street" msgstr "" @@ -318,14 +318,13 @@ msgstr "" msgid "Member" msgstr "" -#: lib/mv_web/components/layouts/navbar.ex:19 -#: lib/mv_web/live/member_live/index.ex:14 +#: lib/mv_web/components/layouts/navbar.ex:14 +#: lib/mv_web/live/member_live/index.ex:8 #: lib/mv_web/live/member_live/index.html.heex:3 #, elixir-autogen, elixir-format msgid "Members" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:57 #: lib/mv_web/live/property_type_live/form.ex:16 #, elixir-autogen, elixir-format msgid "Name" @@ -470,11 +469,13 @@ msgid "Value type" msgstr "" #: lib/mv_web/components/table_components.ex:30 +#: lib/mv_web/live/components/sort_header_component.ex:55 #, elixir-autogen, elixir-format msgid "ascending" msgstr "" #: lib/mv_web/components/table_components.ex:30 +#: lib/mv_web/live/components/sort_header_component.ex:56 #, elixir-autogen, elixir-format msgid "descending" msgstr "" @@ -554,57 +555,17 @@ msgstr "Set Password" msgid "User will be created without a password. Check 'Set Password' to add one." msgstr "User will be created without a password. Check 'Set Password' to add one." -#: lib/mv_web/live/user_live/show.ex:30 +#: lib/mv_web/live/components/sort_header_component.ex:60 +#, elixir-autogen, elixir-format +msgid "Click to sort" +msgstr "" + +#: lib/mv_web/live/member_live/index.html.heex:53 #, elixir-autogen, elixir-format, fuzzy -msgid "Linked Member" +msgid "First name" msgstr "" -#: lib/mv_web/live/member_live/show.ex:41 -#, elixir-autogen, elixir-format -msgid "Linked User" -msgstr "" - -#: lib/mv_web/live/user_live/show.ex:40 -#, elixir-autogen, elixir-format -msgid "No member linked" -msgstr "" - -#: lib/mv_web/live/member_live/show.ex:51 -#, elixir-autogen, elixir-format -msgid "No user linked" -msgstr "" - -#: lib/mv_web/live/member_live/show.ex:14 -#: lib/mv_web/live/member_live/show.ex:16 -#, elixir-autogen, elixir-format -msgid "Back to members list" -msgstr "" - -#: lib/mv_web/live/user_live/show.ex:13 -#: lib/mv_web/live/user_live/show.ex:15 -#, elixir-autogen, elixir-format -msgid "Back to users list" -msgstr "" - -#: lib/mv_web/components/layouts/navbar.ex:27 -#: lib/mv_web/components/layouts/navbar.ex:33 -#, elixir-autogen, elixir-format, fuzzy -msgid "Select language" -msgstr "" - -#: lib/mv_web/components/layouts/navbar.ex:40 -#: lib/mv_web/components/layouts/navbar.ex:60 -#, elixir-autogen, elixir-format -msgid "Toggle dark mode" -msgstr "" - -#: lib/mv_web/live/components/search_bar_component.ex:15 -#: lib/mv_web/live/member_live/index.html.heex:15 -#, elixir-autogen, elixir-format -msgid "Search..." -msgstr "" - -#: lib/mv_web/components/layouts/navbar.ex:20 -#, elixir-autogen, elixir-format, fuzzy -msgid "Users" -msgstr "" +#~ #: lib/mv_web/auth_overrides.ex:30 +#~ #, elixir-autogen, elixir-format +#~ msgid "or" +#~ msgstr "" -- 2.47.2 From 9d98ec2494feb16ecf8dd6f259bb812cd2da8a25 Mon Sep 17 00:00:00 2001 From: carla Date: Tue, 30 Sep 2025 16:46:03 +0200 Subject: [PATCH 05/11] formatting --- lib/mv_web/live/member_live/index.ex | 47 +++++++++++----------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/lib/mv_web/live/member_live/index.ex b/lib/mv_web/live/member_live/index.ex index 52b16ae..7a0de39 100644 --- a/lib/mv_web/live/member_live/index.ex +++ b/lib/mv_web/live/member_live/index.ex @@ -2,14 +2,13 @@ defmodule MvWeb.MemberLive.Index do use MvWeb, :live_view import Ash.Expr import Ash.Query - import MvWeb.TableComponents @impl true def mount(params, _session, socket) do socket = socket |> assign(:page_title, gettext("Members")) - |> assign(:query, "") + |> assign(:query, "") |> assign_new(:sort_field, fn -> :first_name end) |> assign_new(:sort_order, fn -> :asc end) |> assign(:selected_members, []) @@ -19,32 +18,6 @@ defmodule MvWeb.MemberLive.Index do {:ok, socket} end - # ----------------------------------------------------------------- - # Receive messages from any toolbar component - # ----------------------------------------------------------------- - - # 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 - - {:noreply, - socket - |> assign(:query, q) - |> assign(:members, members)} - end - - # ----------------------------------------------------------------- - # Handle Events - # ----------------------------------------------------------------- - # ----------------------------------------------------------------- # Handle Events # ----------------------------------------------------------------- @@ -132,6 +105,24 @@ defmodule MvWeb.MemberLive.Index do )} end + # 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 + + {:noreply, + socket + |> assign(:query, q) + |> assign(:members, members)} + end + # ----------------------------------------------------------------- # Handle Params from the URL # ----------------------------------------------------------------- -- 2.47.2 From 85e1f370f674f1134102b21618f00842f8a15bfd Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 23 Oct 2025 15:43:08 +0200 Subject: [PATCH 06/11] fix: keep search term while sorting --- .../live/components/sort_header_component.ex | 48 ++++++----- lib/mv_web/live/member_live/index.ex | 84 ++++++++++++++----- 2 files changed, 89 insertions(+), 43 deletions(-) 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 -- 2.47.2 From eb42b9fe0adc10b3f1ba936624ae30cc06d816e8 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 23 Oct 2025 15:44:08 +0200 Subject: [PATCH 07/11] fix: keep search term on refresh and enter --- lib/mv_web/live/components/search_bar_component.ex | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/mv_web/live/components/search_bar_component.ex b/lib/mv_web/live/components/search_bar_component.ex index 3eb5246..c45a1e5 100644 --- a/lib/mv_web/live/components/search_bar_component.ex +++ b/lib/mv_web/live/components/search_bar_component.ex @@ -8,10 +8,10 @@ defmodule MvWeb.Components.SearchBarComponent do use MvWeb, :live_component @impl true - def update(_assigns, socket) do + def update(%{query: query}, socket) do socket = socket - |> assign_new(:query, fn -> "" end) + |> assign_new(:query, fn -> query || "" end) |> assign_new(:placeholder, fn -> gettext("Search...") end) {:ok, socket} @@ -20,7 +20,7 @@ defmodule MvWeb.Components.SearchBarComponent do @impl true def render(assigns) do ~H""" -