From 8e4f1ba674162388557ec525a83666b252a1531c Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 3 Dec 2025 14:24:10 +0100 Subject: [PATCH 1/6] feat: add col_click attribute to table component for checkbox column - Add col_click slot attribute to table component that overrides row_click - Clicking anywhere in the checkbox column now toggles the checkbox - Clicking other columns still navigates to member details Closes #223 --- lib/mv_web/components/core_components.ex | 8 +++-- lib/mv_web/live/member_live/index.ex | 10 ++++++ lib/mv_web/live/member_live/index.html.heex | 5 +-- priv/gettext/de/LC_MESSAGES/default.po | 36 ++++++++++----------- priv/gettext/default.pot | 36 ++++++++++----------- priv/gettext/en/LC_MESSAGES/default.po | 36 ++++++++++----------- 6 files changed, 71 insertions(+), 60 deletions(-) diff --git a/lib/mv_web/components/core_components.ex b/lib/mv_web/components/core_components.ex index 54a5a64..a432652 100644 --- a/lib/mv_web/components/core_components.ex +++ b/lib/mv_web/components/core_components.ex @@ -357,6 +357,7 @@ defmodule MvWeb.CoreComponents do slot :col, required: true do attr :label, :string + attr :col_click, :any, doc: "optional column-specific click handler that overrides row_click" end slot :action, doc: "the slot for showing user actions in the last table column" @@ -391,8 +392,11 @@ defmodule MvWeb.CoreComponents do {render_slot(col, @row_item.(row))} diff --git a/lib/mv_web/live/member_live/index.ex b/lib/mv_web/live/member_live/index.ex index 67ce522..1100f45 100644 --- a/lib/mv_web/live/member_live/index.ex +++ b/lib/mv_web/live/member_live/index.ex @@ -892,6 +892,16 @@ defmodule MvWeb.MemberLive.Index do |> Enum.map(&format_member_email/1) end + @doc """ + Returns a JS command to toggle member selection when clicking the checkbox column. + + Used as `col_click` handler to ensure clicking anywhere in the checkbox column + toggles the checkbox instead of navigating to the member details. + """ + def checkbox_column_click(member) do + JS.push("select_member", value: %{id: member.id}) + end + # Formats a member's email in the format "First Last " # Used for copy_emails feature and mailto links to create email-client-friendly format. def format_member_email(member) do diff --git a/lib/mv_web/live/member_live/index.html.heex b/lib/mv_web/live/member_live/index.html.heex index 9f8851b..6b69882 100644 --- a/lib/mv_web/live/member_live/index.html.heex +++ b/lib/mv_web/live/member_live/index.html.heex @@ -58,6 +58,7 @@ <:col :let={member} + col_click={&MvWeb.MemberLive.Index.checkbox_column_click/1} label={ ~H""" <.input @@ -74,11 +75,7 @@ <.input type="checkbox" name={member.id} - phx-click="select_member" - phx-value-id={member.id} checked={MapSet.member?(@selected_members, member.id)} - phx-capture-click - phx-stop-propagation aria-label={gettext("Select member")} role="checkbox" /> diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index 57df5ab..0098ae1 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -10,12 +10,12 @@ msgid "" msgstr "" "Language: en\n" -#: lib/mv_web/components/core_components.ex:386 +#: lib/mv_web/components/core_components.ex:387 #, elixir-autogen, elixir-format msgid "Actions" msgstr "Aktionen" -#: lib/mv_web/live/member_live/index.html.heex:248 +#: lib/mv_web/live/member_live/index.html.heex:245 #: lib/mv_web/live/user_live/index.html.heex:72 #, 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:53 -#: lib/mv_web/live/member_live/index.html.heex:184 +#: lib/mv_web/live/member_live/index.html.heex:181 #: lib/mv_web/live/member_live/show.ex:58 #, elixir-autogen, elixir-format msgid "City" msgstr "Stadt" -#: lib/mv_web/live/member_live/index.html.heex:250 +#: lib/mv_web/live/member_live/index.html.heex:247 #: lib/mv_web/live/user_live/index.html.heex:74 #, elixir-autogen, elixir-format msgid "Delete" msgstr "Löschen" -#: lib/mv_web/live/member_live/index.html.heex:242 +#: lib/mv_web/live/member_live/index.html.heex:239 #: lib/mv_web/live/user_live/form.ex:265 #: lib/mv_web/live/user_live/index.html.heex:66 #, elixir-autogen, elixir-format @@ -54,7 +54,7 @@ msgid "Edit Member" msgstr "Mitglied bearbeiten" #: lib/mv_web/live/member_live/form.ex:47 -#: lib/mv_web/live/member_live/index.html.heex:112 +#: lib/mv_web/live/member_live/index.html.heex:109 #: lib/mv_web/live/member_live/show.ex:50 #: lib/mv_web/live/user_live/form.ex:46 #: lib/mv_web/live/user_live/index.html.heex:44 @@ -70,7 +70,7 @@ msgid "First Name" msgstr "Vorname" #: lib/mv_web/live/member_live/form.ex:50 -#: lib/mv_web/live/member_live/index.html.heex:220 +#: lib/mv_web/live/member_live/index.html.heex:217 #: lib/mv_web/live/member_live/show.ex:55 #, elixir-autogen, elixir-format msgid "Join Date" @@ -87,7 +87,7 @@ msgstr "Nachname" msgid "New Member" msgstr "Neues Mitglied" -#: lib/mv_web/live/member_live/index.html.heex:239 +#: lib/mv_web/live/member_live/index.html.heex:236 #: lib/mv_web/live/user_live/index.html.heex:63 #, elixir-autogen, elixir-format msgid "Show" @@ -115,7 +115,7 @@ msgid "Exit Date" msgstr "Austrittsdatum" #: lib/mv_web/live/member_live/form.ex:55 -#: lib/mv_web/live/member_live/index.html.heex:148 +#: lib/mv_web/live/member_live/index.html.heex:145 #: lib/mv_web/live/member_live/show.ex:60 #, elixir-autogen, elixir-format msgid "House Number" @@ -130,21 +130,21 @@ msgstr "Notizen" #: lib/mv_web/live/components/payment_filter_component.ex:94 #: lib/mv_web/live/components/payment_filter_component.ex:144 #: lib/mv_web/live/member_live/form.ex:48 -#: lib/mv_web/live/member_live/index.html.heex:229 +#: lib/mv_web/live/member_live/index.html.heex:226 #: lib/mv_web/live/member_live/show.ex:51 #, elixir-autogen, elixir-format msgid "Paid" msgstr "Bezahlt" #: lib/mv_web/live/member_live/form.ex:49 -#: lib/mv_web/live/member_live/index.html.heex:202 +#: lib/mv_web/live/member_live/index.html.heex:199 #: lib/mv_web/live/member_live/show.ex:54 #, elixir-autogen, elixir-format msgid "Phone Number" msgstr "Telefonnummer" #: lib/mv_web/live/member_live/form.ex:56 -#: lib/mv_web/live/member_live/index.html.heex:166 +#: lib/mv_web/live/member_live/index.html.heex:163 #: lib/mv_web/live/member_live/show.ex:61 #, elixir-autogen, elixir-format msgid "Postal Code" @@ -165,7 +165,7 @@ msgid "Saving..." msgstr "Speichern..." #: lib/mv_web/live/member_live/form.ex:54 -#: lib/mv_web/live/member_live/index.html.heex:130 +#: lib/mv_web/live/member_live/index.html.heex:127 #: lib/mv_web/live/member_live/show.ex:59 #, elixir-autogen, elixir-format msgid "Street" @@ -176,7 +176,7 @@ msgstr "Straße" msgid "Id" msgstr "ID" -#: lib/mv_web/live/member_live/index.html.heex:234 +#: lib/mv_web/live/member_live/index.html.heex:231 #: lib/mv_web/live/member_live/index/formatter.ex:61 #: lib/mv_web/live/member_live/show.ex:52 #, elixir-autogen, elixir-format @@ -193,7 +193,7 @@ msgstr "Mitglied anzeigen" msgid "This is a member record from your database." msgstr "Dies ist ein Mitglied aus deiner Datenbank." -#: lib/mv_web/live/member_live/index.html.heex:234 +#: lib/mv_web/live/member_live/index.html.heex:231 #: lib/mv_web/live/member_live/index/formatter.ex:60 #: lib/mv_web/live/member_live/show.ex:52 #, elixir-autogen, elixir-format @@ -359,12 +359,12 @@ msgstr "Profil" msgid "Required" msgstr "Erforderlich" -#: lib/mv_web/live/member_live/index.html.heex:68 +#: lib/mv_web/live/member_live/index.html.heex:69 #, elixir-autogen, elixir-format msgid "Select all members" msgstr "Alle Mitglieder auswählen" -#: lib/mv_web/live/member_live/index.html.heex:82 +#: lib/mv_web/live/member_live/index.html.heex:79 #, elixir-autogen, elixir-format msgid "Select member" msgstr "Mitglied auswählen" @@ -566,7 +566,7 @@ msgstr "Benutzer*innen" msgid "Click to sort" msgstr "Klicke um zu sortieren" -#: lib/mv_web/live/member_live/index.html.heex:94 +#: lib/mv_web/live/member_live/index.html.heex:91 #, elixir-autogen, elixir-format msgid "First name" msgstr "Vorname" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index 1e0e954..58c2602 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -11,12 +11,12 @@ msgid "" msgstr "" -#: lib/mv_web/components/core_components.ex:386 +#: lib/mv_web/components/core_components.ex:387 #, elixir-autogen, elixir-format msgid "Actions" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:248 +#: lib/mv_web/live/member_live/index.html.heex:245 #: lib/mv_web/live/user_live/index.html.heex:72 #, 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:53 -#: lib/mv_web/live/member_live/index.html.heex:184 +#: lib/mv_web/live/member_live/index.html.heex:181 #: lib/mv_web/live/member_live/show.ex:58 #, elixir-autogen, elixir-format msgid "City" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:250 +#: lib/mv_web/live/member_live/index.html.heex:247 #: lib/mv_web/live/user_live/index.html.heex:74 #, elixir-autogen, elixir-format msgid "Delete" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:242 +#: lib/mv_web/live/member_live/index.html.heex:239 #: lib/mv_web/live/user_live/form.ex:265 #: lib/mv_web/live/user_live/index.html.heex:66 #, elixir-autogen, elixir-format @@ -55,7 +55,7 @@ msgid "Edit Member" msgstr "" #: lib/mv_web/live/member_live/form.ex:47 -#: lib/mv_web/live/member_live/index.html.heex:112 +#: lib/mv_web/live/member_live/index.html.heex:109 #: lib/mv_web/live/member_live/show.ex:50 #: lib/mv_web/live/user_live/form.ex:46 #: lib/mv_web/live/user_live/index.html.heex:44 @@ -71,7 +71,7 @@ msgid "First Name" msgstr "" #: lib/mv_web/live/member_live/form.ex:50 -#: lib/mv_web/live/member_live/index.html.heex:220 +#: lib/mv_web/live/member_live/index.html.heex:217 #: lib/mv_web/live/member_live/show.ex:55 #, elixir-autogen, elixir-format msgid "Join Date" @@ -88,7 +88,7 @@ msgstr "" msgid "New Member" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:239 +#: lib/mv_web/live/member_live/index.html.heex:236 #: lib/mv_web/live/user_live/index.html.heex:63 #, elixir-autogen, elixir-format msgid "Show" @@ -116,7 +116,7 @@ msgid "Exit Date" msgstr "" #: lib/mv_web/live/member_live/form.ex:55 -#: lib/mv_web/live/member_live/index.html.heex:148 +#: lib/mv_web/live/member_live/index.html.heex:145 #: lib/mv_web/live/member_live/show.ex:60 #, elixir-autogen, elixir-format msgid "House Number" @@ -131,21 +131,21 @@ msgstr "" #: lib/mv_web/live/components/payment_filter_component.ex:94 #: lib/mv_web/live/components/payment_filter_component.ex:144 #: lib/mv_web/live/member_live/form.ex:48 -#: lib/mv_web/live/member_live/index.html.heex:229 +#: lib/mv_web/live/member_live/index.html.heex:226 #: lib/mv_web/live/member_live/show.ex:51 #, elixir-autogen, elixir-format msgid "Paid" msgstr "" #: lib/mv_web/live/member_live/form.ex:49 -#: lib/mv_web/live/member_live/index.html.heex:202 +#: lib/mv_web/live/member_live/index.html.heex:199 #: lib/mv_web/live/member_live/show.ex:54 #, elixir-autogen, elixir-format msgid "Phone Number" msgstr "" #: lib/mv_web/live/member_live/form.ex:56 -#: lib/mv_web/live/member_live/index.html.heex:166 +#: lib/mv_web/live/member_live/index.html.heex:163 #: lib/mv_web/live/member_live/show.ex:61 #, elixir-autogen, elixir-format msgid "Postal Code" @@ -166,7 +166,7 @@ msgid "Saving..." msgstr "" #: lib/mv_web/live/member_live/form.ex:54 -#: lib/mv_web/live/member_live/index.html.heex:130 +#: lib/mv_web/live/member_live/index.html.heex:127 #: lib/mv_web/live/member_live/show.ex:59 #, elixir-autogen, elixir-format msgid "Street" @@ -177,7 +177,7 @@ msgstr "" msgid "Id" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:234 +#: lib/mv_web/live/member_live/index.html.heex:231 #: lib/mv_web/live/member_live/index/formatter.ex:61 #: lib/mv_web/live/member_live/show.ex:52 #, elixir-autogen, elixir-format @@ -194,7 +194,7 @@ msgstr "" msgid "This is a member record from your database." msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:234 +#: lib/mv_web/live/member_live/index.html.heex:231 #: lib/mv_web/live/member_live/index/formatter.ex:60 #: lib/mv_web/live/member_live/show.ex:52 #, elixir-autogen, elixir-format @@ -360,12 +360,12 @@ msgstr "" msgid "Required" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:68 +#: lib/mv_web/live/member_live/index.html.heex:69 #, elixir-autogen, elixir-format msgid "Select all members" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:82 +#: lib/mv_web/live/member_live/index.html.heex:79 #, elixir-autogen, elixir-format msgid "Select member" msgstr "" @@ -567,7 +567,7 @@ msgstr "" msgid "Click to sort" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:94 +#: lib/mv_web/live/member_live/index.html.heex:91 #, elixir-autogen, elixir-format msgid "First name" msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index 319bcc3..00b269c 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -11,12 +11,12 @@ msgstr "" "Language: en\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: lib/mv_web/components/core_components.ex:386 +#: lib/mv_web/components/core_components.ex:387 #, elixir-autogen, elixir-format msgid "Actions" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:248 +#: lib/mv_web/live/member_live/index.html.heex:245 #: lib/mv_web/live/user_live/index.html.heex:72 #, 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:53 -#: lib/mv_web/live/member_live/index.html.heex:184 +#: lib/mv_web/live/member_live/index.html.heex:181 #: lib/mv_web/live/member_live/show.ex:58 #, elixir-autogen, elixir-format msgid "City" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:250 +#: lib/mv_web/live/member_live/index.html.heex:247 #: lib/mv_web/live/user_live/index.html.heex:74 #, elixir-autogen, elixir-format msgid "Delete" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:242 +#: lib/mv_web/live/member_live/index.html.heex:239 #: lib/mv_web/live/user_live/form.ex:265 #: lib/mv_web/live/user_live/index.html.heex:66 #, elixir-autogen, elixir-format @@ -55,7 +55,7 @@ msgid "Edit Member" msgstr "" #: lib/mv_web/live/member_live/form.ex:47 -#: lib/mv_web/live/member_live/index.html.heex:112 +#: lib/mv_web/live/member_live/index.html.heex:109 #: lib/mv_web/live/member_live/show.ex:50 #: lib/mv_web/live/user_live/form.ex:46 #: lib/mv_web/live/user_live/index.html.heex:44 @@ -71,7 +71,7 @@ msgid "First Name" msgstr "" #: lib/mv_web/live/member_live/form.ex:50 -#: lib/mv_web/live/member_live/index.html.heex:220 +#: lib/mv_web/live/member_live/index.html.heex:217 #: lib/mv_web/live/member_live/show.ex:55 #, elixir-autogen, elixir-format msgid "Join Date" @@ -88,7 +88,7 @@ msgstr "" msgid "New Member" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:239 +#: lib/mv_web/live/member_live/index.html.heex:236 #: lib/mv_web/live/user_live/index.html.heex:63 #, elixir-autogen, elixir-format msgid "Show" @@ -116,7 +116,7 @@ msgid "Exit Date" msgstr "" #: lib/mv_web/live/member_live/form.ex:55 -#: lib/mv_web/live/member_live/index.html.heex:148 +#: lib/mv_web/live/member_live/index.html.heex:145 #: lib/mv_web/live/member_live/show.ex:60 #, elixir-autogen, elixir-format msgid "House Number" @@ -131,21 +131,21 @@ msgstr "" #: lib/mv_web/live/components/payment_filter_component.ex:94 #: lib/mv_web/live/components/payment_filter_component.ex:144 #: lib/mv_web/live/member_live/form.ex:48 -#: lib/mv_web/live/member_live/index.html.heex:229 +#: lib/mv_web/live/member_live/index.html.heex:226 #: lib/mv_web/live/member_live/show.ex:51 #, elixir-autogen, elixir-format msgid "Paid" msgstr "" #: lib/mv_web/live/member_live/form.ex:49 -#: lib/mv_web/live/member_live/index.html.heex:202 +#: lib/mv_web/live/member_live/index.html.heex:199 #: lib/mv_web/live/member_live/show.ex:54 #, elixir-autogen, elixir-format msgid "Phone Number" msgstr "" #: lib/mv_web/live/member_live/form.ex:56 -#: lib/mv_web/live/member_live/index.html.heex:166 +#: lib/mv_web/live/member_live/index.html.heex:163 #: lib/mv_web/live/member_live/show.ex:61 #, elixir-autogen, elixir-format msgid "Postal Code" @@ -166,7 +166,7 @@ msgid "Saving..." msgstr "" #: lib/mv_web/live/member_live/form.ex:54 -#: lib/mv_web/live/member_live/index.html.heex:130 +#: lib/mv_web/live/member_live/index.html.heex:127 #: lib/mv_web/live/member_live/show.ex:59 #, elixir-autogen, elixir-format msgid "Street" @@ -177,7 +177,7 @@ msgstr "" msgid "Id" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:234 +#: lib/mv_web/live/member_live/index.html.heex:231 #: lib/mv_web/live/member_live/index/formatter.ex:61 #: lib/mv_web/live/member_live/show.ex:52 #, elixir-autogen, elixir-format @@ -194,7 +194,7 @@ msgstr "" msgid "This is a member record from your database." msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:234 +#: lib/mv_web/live/member_live/index.html.heex:231 #: lib/mv_web/live/member_live/index/formatter.ex:60 #: lib/mv_web/live/member_live/show.ex:52 #, elixir-autogen, elixir-format @@ -360,12 +360,12 @@ msgstr "" msgid "Required" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:68 +#: lib/mv_web/live/member_live/index.html.heex:69 #, elixir-autogen, elixir-format msgid "Select all members" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:82 +#: lib/mv_web/live/member_live/index.html.heex:79 #, elixir-autogen, elixir-format msgid "Select member" msgstr "" @@ -567,7 +567,7 @@ msgstr "" msgid "Click to sort" msgstr "" -#: lib/mv_web/live/member_live/index.html.heex:94 +#: lib/mv_web/live/member_live/index.html.heex:91 #, elixir-autogen, elixir-format, fuzzy msgid "First name" msgstr "" From 6b0ec28d9b5f6c018aec21b3840157d7e62b929a Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 3 Dec 2025 14:34:31 +0100 Subject: [PATCH 2/6] fix checkbox tests --- test/mv_web/member_live/index_test.exs | 52 ++++++++------------------ 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/test/mv_web/member_live/index_test.exs b/test/mv_web/member_live/index_test.exs index 0bcc731..9e3323f 100644 --- a/test/mv_web/member_live/index_test.exs +++ b/test/mv_web/member_live/index_test.exs @@ -285,14 +285,9 @@ defmodule MvWeb.MemberLive.IndexTest do conn = conn_with_oidc_user(conn) {:ok, view, _html} = live(conn, "/members") - # Select two members - view - |> element("[phx-click='select_member'][phx-value-id='#{member1.id}']") - |> render_click() - - view - |> element("[phx-click='select_member'][phx-value-id='#{member2.id}']") - |> render_click() + # Select two members by sending the select_member event directly + render_click(view, "select_member", %{"id" => member1.id}) + render_click(view, "select_member", %{"id" => member2.id}) # Trigger copy_emails event view |> element("#copy-emails-btn") |> render_click() @@ -336,10 +331,8 @@ defmodule MvWeb.MemberLive.IndexTest do conn = conn_with_oidc_user(conn) {:ok, view, _html} = live(conn, "/members") - # Select member with umlauts - view - |> element("[phx-click='select_member'][phx-value-id='#{member3.id}']") - |> render_click() + # Select member with umlauts by sending the select_member event directly + render_click(view, "select_member", %{"id" => member3.id}) # Trigger copy_emails event - should not crash view |> element("#copy-emails-btn") |> render_click() @@ -355,10 +348,8 @@ defmodule MvWeb.MemberLive.IndexTest do conn = conn_with_oidc_user(conn) {:ok, view, _html} = live(conn, "/members") - # Select a member - view - |> element("[phx-click='select_member'][phx-value-id='#{member1.id}']") - |> render_click() + # Select a member by sending the select_member event directly + render_click(view, "select_member", %{"id" => member1.id}) # Delete the member from the database Ash.destroy!(member1) @@ -379,14 +370,9 @@ defmodule MvWeb.MemberLive.IndexTest do conn = conn_with_oidc_user(conn) {:ok, view, _html} = live(conn, "/members") - # Select two members - view - |> element("[phx-click='select_member'][phx-value-id='#{member1.id}']") - |> render_click() - - view - |> element("[phx-click='select_member'][phx-value-id='#{member2.id}']") - |> render_click() + # Select two members by sending the select_member event directly + render_click(view, "select_member", %{"id" => member1.id}) + render_click(view, "select_member", %{"id" => member2.id}) # Get the socket state to verify the formatted email string state = :sys.get_state(view.pid) @@ -415,10 +401,8 @@ defmodule MvWeb.MemberLive.IndexTest do {:ok, view, _html} = live(conn, "/members") - # Select the test member - view - |> element("[phx-click='select_member'][phx-value-id='#{test_member.id}']") - |> render_click() + # Select the test member by sending the select_member event directly + render_click(view, "select_member", %{"id" => test_member.id}) # The format should be "Test Format " # We verify this by checking the flash shows 1 email was copied @@ -441,10 +425,8 @@ defmodule MvWeb.MemberLive.IndexTest do conn = conn_with_oidc_user(conn) {:ok, view, _html} = live(conn, "/members") - # Select a member - view - |> element("[phx-click='select_member'][phx-value-id='#{member1.id}']") - |> render_click() + # Select a member by sending the select_member event directly + render_click(view, "select_member", %{"id" => member1.id}) # Button should now be visible assert has_element?(view, "#copy-emails-btn") @@ -457,10 +439,8 @@ defmodule MvWeb.MemberLive.IndexTest do conn = conn_with_oidc_user(conn) {:ok, view, _html} = live(conn, "/members") - # Select a member - view - |> element("[phx-click='select_member'][phx-value-id='#{member1.id}']") - |> render_click() + # Select a member by sending the select_member event directly + render_click(view, "select_member", %{"id" => member1.id}) # Click copy button view |> element("#copy-emails-btn") |> render_click() From 94de4295292d928f3c60a8024635b8fa77c5294d Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 3 Dec 2025 22:18:18 +0100 Subject: [PATCH 3/6] style: translate fieldtypes and payment as button --- .../components/payment_filter_component.ex | 2 +- .../live/custom_field_live/index_component.ex | 47 ++++++++++--------- lib/mv_web/translations/field_types.ex | 21 +++++++++ 3 files changed, 48 insertions(+), 22 deletions(-) create mode 100644 lib/mv_web/translations/field_types.ex diff --git a/lib/mv_web/live/components/payment_filter_component.ex b/lib/mv_web/live/components/payment_filter_component.ex index c9dc731..47556dd 100644 --- a/lib/mv_web/live/components/payment_filter_component.ex +++ b/lib/mv_web/live/components/payment_filter_component.ex @@ -44,7 +44,7 @@ defmodule MvWeb.Components.PaymentFilterComponent do - + + """ end diff --git a/lib/mv_web/translations/field_types.ex b/lib/mv_web/translations/field_types.ex new file mode 100644 index 0000000..969f20b --- /dev/null +++ b/lib/mv_web/translations/field_types.ex @@ -0,0 +1,21 @@ +defmodule MvWeb.Translations.FieldTypes do + @moduledoc """ + Helper module to dynamically translate field types. + + ## Features + - Can be used in templates to dynamically translate technical field type words to human friendly text + + ## Example + assigns = assign(assigns, :field_type_label, &MvWeb.Translations.FieldTypes.label/1) + In template: + <%= @field_type_label.(custom_field.value_type) %> + """ + use Gettext, backend: MvWeb.Gettext + + @spec label(atom()) :: String.t() + def label(:string), do: gettext("Text") + def label(:integer), do: gettext("Number") + def label(:boolean), do: gettext("Yes/No-Selection") + def label(:date), do: gettext("Date") + def label(:email), do: gettext("E-Mail") +end From d671103ba530828d19043bb11ce4c20d404c9e36 Mon Sep 17 00:00:00 2001 From: carla Date: Wed, 3 Dec 2025 22:18:40 +0100 Subject: [PATCH 4/6] chore: update translation --- priv/gettext/de/LC_MESSAGES/default.po | 189 ++++++++++++++----------- priv/gettext/default.pot | 25 ++++ priv/gettext/en/LC_MESSAGES/default.po | 25 ++++ 3 files changed, 157 insertions(+), 82 deletions(-) diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index bb781f7..311e727 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -48,7 +48,7 @@ msgstr "Löschen" #: lib/mv_web/live/user_live/index.html.heex #, elixir-autogen, elixir-format msgid "Edit" -msgstr "Bearbeite" +msgstr "Bearbeiten" #: lib/mv_web/live/member_live/form.ex #: lib/mv_web/live/member_live/show.ex @@ -214,7 +214,7 @@ msgstr "Falsche E-Mail oder Passwort" #: lib/mv_web/live/member_live/form.ex #, elixir-autogen, elixir-format msgid "Member %{action} successfully" -msgstr "Mitglied %{action} erfolgreich" +msgstr "Mitglied erfolgreich %{action}" #: lib/mv_web/controllers/auth_controller.ex #, elixir-autogen, elixir-format @@ -419,8 +419,8 @@ msgstr "Administrator*innen-Hinweis" #: lib/mv_web/live/user_live/form.ex #, elixir-autogen, elixir-format -msgid "As an administrator, you can directly set a new password for this user using the same secure Ash Authentication system." -msgstr "Als Administrator*in können Sie direkt ein neues Passwort für diese*n Benutzer*in setzen, wobei das gleiche sichere Ash Authentication System verwendet wird." +msgid "As an administrator, you can directly set a new password for this user." +msgstr "Als Administrator*in können Sie direkt ein neues Passwort für diese*n Benutzer*in setzen." #: lib/mv_web/live/user_live/form.ex #, elixir-autogen, elixir-format @@ -658,7 +658,7 @@ msgstr "Um die Löschung zu bestätigen, gib bitte folgenden Text ein:" #: lib/mv_web/live/custom_field_live/form_component.ex #, elixir-autogen, elixir-format msgid "Show in overview" -msgstr "In der Mitglieder-Übersicht anzeigen" +msgstr "In Übersicht anzeigen" #: lib/mv_web/live/global_settings_live.ex #, elixir-autogen, elixir-format @@ -904,96 +904,96 @@ msgstr "Mitglied erstellen" #, elixir-autogen, elixir-format msgid "%{count} period selected" msgid_plural "%{count} periods selected" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%{count} Zyklus ausgewählt" +msgstr[1] "%{count} Zyklen ausgewählt" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "About Contribution Types" -msgstr "" +msgstr "Über Beitragsarten" #: lib/mv_web/live/contribution_period_live/show.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Amount" -msgstr "" +msgstr "Betrag" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Back to Settings" -msgstr "" +msgstr "Zurück zu den Einstellungen" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Can be changed at any time. Amount changes affect future periods only." -msgstr "" +msgstr "Kann jederzeit geändert werden. Änderungen des Betrags betreffen nur zukünftige Zyklen." #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Cannot delete - members assigned" -msgstr "" +msgstr "Löschen nicht möglich – es sind Mitglieder zugewiesen" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Change Contribution Type" -msgstr "" +msgstr "Beitragsart ändern" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Configure global settings for membership contributions." -msgstr "" +msgstr "Globale Einstellungen für Mitgliedsbeiträge konfigurieren." #: lib/mv_web/components/layouts/navbar.ex #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format, fuzzy msgid "Contribution Settings" -msgstr "Beitrag" +msgstr "Beitragseinstellungen" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format, fuzzy msgid "Contribution Start" -msgstr "Beitrag" +msgstr "Beitragsbeginn" #: lib/mv_web/components/layouts/navbar.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Contribution Types" -msgstr "Beitrag" +msgstr "Beitragsarten" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format, fuzzy msgid "Contribution start" -msgstr "Beitrag" +msgstr "Beitragsbeginn" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format, fuzzy msgid "Contribution type" -msgstr "Beitrag" +msgstr "Beitragsart" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Contribution types define different membership fee structures. Each type has a fixed interval (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation." -msgstr "" +msgstr "Beitragsarten definieren verschiedene Beitragsmodelle. Jede Art hat einen festen Zyklus (monatlich, vierteljährlich, halbjährlich, jährlich), der nach Erstellung nicht mehr geändert werden kann." #: lib/mv_web/components/layouts/navbar.ex #, elixir-autogen, elixir-format, fuzzy msgid "Contributions" -msgstr "Beitrag" +msgstr "Beiträge" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format, fuzzy msgid "Contributions for %{name}" -msgstr "Beitrag" +msgstr "Beiträge für %{name}" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Current" -msgstr "" +msgstr "Aktuell" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Default Contribution Type" -msgstr "" +msgstr "Standard-Beitragsart" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy @@ -1003,28 +1003,28 @@ msgstr "Löschen" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Example: Member Contribution View" -msgstr "" +msgstr "Beispiel: Ansicht Mitgliedsbeiträge" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Examples" -msgstr "" +msgstr "Beispiele" #: lib/mv_web/live/contribution_settings_live.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Family" -msgstr "" +msgstr "Familie" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Fixed after creation. Members can only switch between types with the same interval." -msgstr "" +msgstr "Festgelegt nach der Erstellung. Mitglieder können nur zwischen Beitragsarten mit gleichem Intervall wechseln." #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Generated periods" -msgstr "" +msgstr "Generierte Zyklen" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format, fuzzy @@ -1036,29 +1036,29 @@ msgstr "Vereinsdaten" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Half-yearly" -msgstr "" +msgstr "Halbjährlich" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Half-yearly contribution for supporting members" -msgstr "" +msgstr "Halbjährlicher Beitrag für Fördermitglieder" #: lib/mv_web/live/contribution_period_live/show.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Honorary" -msgstr "" +msgstr "Ehrenamtlich" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Include joining period" -msgstr "" +msgstr "Beitrittsdatum einbeziehen" #: lib/mv_web/live/contribution_period_live/show.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Interval" -msgstr "" +msgstr "Zyklus" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format, fuzzy @@ -1068,240 +1068,240 @@ msgstr "Beitrittsdatum" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Joining year - reduced to 0" -msgstr "" +msgstr "Beitrittsjahr – auf 0 reduziert" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Manage contribution types for membership fees." -msgstr "" +msgstr "Beitragsarten für Mitgliedsbeiträge verwalten." #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Mark as Paid" -msgstr "" +msgstr "Als bezahlt markieren" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Mark as Suspended" -msgstr "" +msgstr "Als pausiert markieren" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Mark as Unpaid" -msgstr "" +msgstr "Als unbezahlt markieren" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Member Contributions" -msgstr "" +msgstr "Mitgliedsbeiträge" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Member pays for the year they joined" -msgstr "" +msgstr "Mitglied zahlt für das Beitrittsjahr" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Member pays from the joining month" -msgstr "" +msgstr "Mitglied zahlt ab Beitrittsmonat" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Member pays from the next full quarter" -msgstr "" +msgstr "Mitglied zahlt ab dem nächsten vollständigen Quartal" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Member pays from the next full year" -msgstr "" +msgstr "Mitglied zahlt ab dem nächsten vollständigen Jahr" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format, fuzzy msgid "Member since" -msgstr "Mitglieder" +msgstr "Mitglied seit" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Members can only switch between contribution types with the same payment interval (e.g., yearly to yearly). This prevents complex period overlaps." -msgstr "" +msgstr "Mitglieder können nur zwischen Beitragsarten mit demselben Zahlungszyklus wechseln (z. B. jährlich zu jährlich). Dadurch werden komplexe Überlappungen vermieden." #: lib/mv_web/live/contribution_period_live/show.ex #: lib/mv_web/live/contribution_settings_live.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "Monthly" -msgstr "monatlich" +msgstr "Monatlich" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Monthly Interval - Joining Period Included" -msgstr "" +msgstr "Monatliches Intervall – Beitrittszeitraum einbezogen" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Monthly fee for students and trainees" -msgstr "" +msgstr "Monatlicher Beitrag für Studierende und Auszubildende" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Name & Amount" -msgstr "" +msgstr "Name & Betrag" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format, fuzzy msgid "New Contribution Type" -msgstr "Beitrag" +msgstr "Neue Beitragsart" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "No fee for honorary members" -msgstr "" +msgstr "Kein Beitrag für ehrenamtliche Mitglieder" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Only possible if no members are assigned to this type." -msgstr "" +msgstr "Nur möglich, wenn diesem Typ keine Mitglieder zugewiesen sind." #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Open Contributions" -msgstr "" +msgstr "Offene Beiträge" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Paid via bank transfer" -msgstr "" +msgstr "Bezahlt durch Überweisung" #: lib/mv_web/live/contribution_period_live/show.ex #: lib/mv_web/live/contribution_settings_live.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Preview Mockup" -msgstr "" +msgstr "Vorschau" #: lib/mv_web/live/contribution_period_live/show.ex #: lib/mv_web/live/contribution_settings_live.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Quarterly" -msgstr "" +msgstr "Vierteljährlich" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Quarterly Interval - Joining Period Excluded" -msgstr "" +msgstr "Vierteljährliches Intervall – Beitrittszeitraum nicht einbezogen" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Quarterly fee for family memberships" -msgstr "" +msgstr "Vierteljährlicher Beitrag für Familienmitgliedschaften" #: lib/mv_web/live/contribution_period_live/show.ex #: lib/mv_web/live/contribution_settings_live.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Reduced" -msgstr "" +msgstr "Reduziert" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Reduced fee for unemployed, pensioners, or low income" -msgstr "" +msgstr "Ermäßigter Beitrag für Arbeitslose, Rentner*innen oder Geringverdienende" #: lib/mv_web/live/contribution_period_live/show.ex #: lib/mv_web/live/contribution_settings_live.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Regular" -msgstr "" +msgstr "Regulär" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Reopen" -msgstr "" +msgstr "Wieder öffnen" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "See how the contribution periods will be displayed for an individual member. This example shows Maria Weber with multiple contribution periods." -msgstr "" +msgstr "Beispielhafte Anzeige der Beitragsperioden für ein einzelnes Mitglied. In diesem Beispiel wird Maria Weber mit mehreren Zyklen angezeigt." #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Standard membership fee for regular members" -msgstr "" +msgstr "Regulärer Mitgliedsbeitrag für Vollmitglieder" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Status" -msgstr "" +msgstr "Status" #: lib/mv_web/live/contribution_settings_live.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Student" -msgstr "" +msgstr "Student" #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "Supporting Member" -msgstr "" +msgstr "Fördermitglied" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Suspend" -msgstr "" +msgstr "Pausieren" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Suspended" -msgstr "" +msgstr "Pausiert" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "This contribution type is automatically assigned to all new members. Can be changed individually per member." -msgstr "" +msgstr "Dieser Beitragstyp wird automatisch neuen Mitgliedern zugewiesen. Kann individuell angepasst werden." #: lib/mv_web/live/contribution_period_live/show.ex #: lib/mv_web/live/contribution_settings_live.ex #: lib/mv_web/live/contribution_type_live/index.ex #, elixir-autogen, elixir-format msgid "This page is not functional and only displays the planned features." -msgstr "" +msgstr "Diese Seite ist nicht funktionsfähig und zeigt nur geplante Funktionen." #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Time Period" -msgstr "" +msgstr "Zeitraum" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Total Contributions" -msgstr "" +msgstr "Gesamtbeiträge" #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Unpaid" -msgstr "" +msgstr "Unbezahlt" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "View Example Member" -msgstr "" +msgstr "Beispielmitglied anzeigen" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "When active: Members pay from the period of their joining." -msgstr "" +msgstr "Wenn aktiviert: Mitglieder zahlen ab dem Zeitraum ihres Beitritts." #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "When inactive: Members pay from the next full period after joining." -msgstr "" +msgstr "Wenn deaktiviert: Mitglieder zahlen ab dem nächsten vollen Beitragszyklus nach dem Beitritt." #: lib/mv_web/live/contribution_period_live/show.ex #, elixir-autogen, elixir-format msgid "Why are not all contribution types shown?" -msgstr "" +msgstr "Warum werden nicht alle Beitragsarten angezeigt?" #: lib/mv_web/live/contribution_period_live/show.ex #: lib/mv_web/live/contribution_settings_live.ex @@ -1313,12 +1313,12 @@ msgstr "jährlich" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Yearly Interval - Joining Period Excluded" -msgstr "" +msgstr "Jährliches Intervall – Beitrittszeitraum nicht einbezogen" #: lib/mv_web/live/contribution_settings_live.ex #, elixir-autogen, elixir-format msgid "Yearly Interval - Joining Period Included" -msgstr "" +msgstr "Jährliches Intervall – Beitrittszeitraum einbezogen" #: lib/mv_web/live/components/field_visibility_dropdown_component.ex #, elixir-autogen, elixir-format @@ -1363,7 +1363,7 @@ msgstr "Zurück zur Felderliste" #: lib/mv_web/live/global_settings_live.ex #, elixir-autogen, elixir-format, fuzzy msgid "Custom field deleted successfully" -msgstr "Benutzerdefiniertes Feld erfolgreich %{action}" +msgstr "Benutzerdefiniertes Feld erfolgreich gelöscht" #: lib/mv_web/live/custom_field_live/form_component.ex #, elixir-autogen, elixir-format, fuzzy @@ -1405,6 +1405,31 @@ msgstr "Diese Felder können zusätzlich zu den normalen Daten ausgefüllt werde msgid "Value Type" msgstr "Wertetyp" +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Date" +msgstr "Datum" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "E-Mail" +msgstr "E-Mail" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Number" +msgstr "Zahl" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Text" +msgstr "Textfeld" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Yes/No-Selection" +msgstr "Ja/Nein-Auswahl" + #~ #: lib/mv_web/live/custom_field_live/show.ex #~ #, elixir-autogen, elixir-format #~ msgid "Auto-generated identifier (immutable)" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index 7581d62..10c230b 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -1405,3 +1405,28 @@ msgstr "" #, elixir-autogen, elixir-format msgid "Value Type" msgstr "" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Date" +msgstr "" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "E-Mail" +msgstr "" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Number" +msgstr "" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Text" +msgstr "" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Yes/No-Selection" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index dc86840..e23030f 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -1406,6 +1406,31 @@ msgstr "" msgid "Value Type" msgstr "" +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Date" +msgstr "" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format, fuzzy +msgid "E-Mail" +msgstr "" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Number" +msgstr "" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Text" +msgstr "" + +#: lib/mv_web/translations/field_types.ex +#, elixir-autogen, elixir-format +msgid "Yes/No-Selection" +msgstr "" + #~ #: lib/mv_web/live/custom_field_live/show.ex #~ #, elixir-autogen, elixir-format #~ msgid "Auto-generated identifier (immutable)" From 8512be02827cef0da97684cda904ee1f6b11cca7 Mon Sep 17 00:00:00 2001 From: carla Date: Thu, 4 Dec 2025 12:32:24 +0100 Subject: [PATCH 5/6] feat: reuse form_section in settings --- lib/mv_web/components/core_components.ex | 59 +++- .../live/custom_field_live/index_component.ex | 270 +++++++++--------- lib/mv_web/live/global_settings_live.ex | 30 +- lib/mv_web/live/member_live/form.ex | 19 -- 4 files changed, 209 insertions(+), 169 deletions(-) diff --git a/lib/mv_web/components/core_components.ex b/lib/mv_web/components/core_components.ex index be64655..f70d245 100644 --- a/lib/mv_web/components/core_components.ex +++ b/lib/mv_web/components/core_components.ex @@ -153,7 +153,7 @@ defmodule MvWeb.CoreComponents do aria-haspopup="menu" aria-expanded={@open} aria-controls={@id} - class="btn btn-ghost" + class="btn" phx-click="toggle_dropdown" phx-target={@phx_target} data-testid="dropdown-button" @@ -236,6 +236,30 @@ defmodule MvWeb.CoreComponents do """ end + @doc """ + Renders a section in with a border similar to cards. + + + ## Examples + + <.form_section title={gettext("Personal Data")}> +

input

+ + """ + attr :title, :string, required: true + slot :inner_block, required: true + + def form_section(assigns) do + ~H""" +
+

{@title}

+
+ {render_slot(@inner_block)} +
+
+ """ + end + @doc """ Renders an input with label and error messages. @@ -434,7 +458,7 @@ defmodule MvWeb.CoreComponents do ~H"""
-

+

{render_slot(@inner_block)}

@@ -474,6 +498,7 @@ defmodule MvWeb.CoreComponents do slot :col, required: true do attr :label, :string + attr :class, :string end slot :action, doc: "the slot for showing user actions in the last table column" @@ -489,7 +514,7 @@ defmodule MvWeb.CoreComponents do - + diff --git a/lib/mv_web/live/custom_field_live/index_component.ex b/lib/mv_web/live/custom_field_live/index_component.ex index 9187aa6..8f63bf8 100644 --- a/lib/mv_web/live/custom_field_live/index_component.ex +++ b/lib/mv_web/live/custom_field_live/index_component.ex @@ -18,141 +18,149 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do ~H"""
- <.form_section title={gettext("Custom Fields")}> -
-

{gettext("These will appear in addition to other data when adding new members.")}

-
- <.button class="ml-auto" variant="primary" phx-click="new_custom_field" phx-target={@myself}> - <.icon name="hero-plus" /> {gettext("New Custom field")} - -
-
- <%!-- Show form when creating or editing --%> -
- <.live_component - module={MvWeb.CustomFieldLive.FormComponent} - id={@form_id} - custom_field={@editing_custom_field} - on_save={ - fn custom_field, action -> send(self(), {:custom_field_saved, custom_field, action}) end - } - on_cancel={fn -> send_update(__MODULE__, id: @id, show_form: false) end} - /> -
- - <%!-- Hide table when form is visible --%> - <.table - :if={!@show_form} - id="custom_fields" - rows={@streams.custom_fields} - row_click={ - fn {_id, custom_field} -> - JS.push("edit_custom_field", value: %{id: custom_field.id}, target: @myself) - end - } - > - <:col :let={{_id, custom_field}} label={gettext("Name")}>{custom_field.name} - - <:col :let={{_id, custom_field}} label={gettext("Value Type")}> - {@field_type_label.(custom_field.value_type)} - - - <:col :let={{_id, custom_field}} label={gettext("Description")}> - {custom_field.description} - - - <:col :let={{_id, custom_field}} label={gettext("Show in overview")} class="max-w-[9.375rem] text-center"> - - {gettext("Yes")} - - - {gettext("No")} - - - - <:action :let={{_id, custom_field}}> - <.icon_button - icon="hero-pencil" - label={gettext("Edit custom field")} - size="sm" - phx-click={JS.push("edit_custom_field", value: %{id: custom_field.id}, target: @myself)} - /> - - - <:action :let={{_id, custom_field}}> - <.icon_button - icon="hero-trash" - label={gettext("Delete custom field")} - size="sm" - class="btn-error" - phx-click={JS.push("prepare_delete", value: %{id: custom_field.id}, target: @myself)} - /> - - - - <%!-- Delete Confirmation Modal --%> - - + <%!-- Show form when creating or editing --%> +
+ <.live_component + module={MvWeb.CustomFieldLive.FormComponent} + id={@form_id} + custom_field={@editing_custom_field} + on_save={ + fn custom_field, action -> send(self(), {:custom_field_saved, custom_field, action}) end + } + on_cancel={fn -> send_update(__MODULE__, id: @id, show_form: false) end} + /> +
+ + <%!-- Hide table when form is visible --%> + <.table + :if={!@show_form} + id="custom_fields" + rows={@streams.custom_fields} + row_click={ + fn {_id, custom_field} -> + JS.push("edit_custom_field", value: %{id: custom_field.id}, target: @myself) + end + } + > + <:col :let={{_id, custom_field}} label={gettext("Name")}>{custom_field.name} + + <:col :let={{_id, custom_field}} label={gettext("Value Type")}> + {@field_type_label.(custom_field.value_type)} + + + <:col :let={{_id, custom_field}} label={gettext("Description")}> + {custom_field.description} + + + <:col + :let={{_id, custom_field}} + label={gettext("Show in overview")} + class="max-w-[9.375rem] text-center" + > + + {gettext("Yes")} + + + {gettext("No")} + + + + <:action :let={{_id, custom_field}}> + <.link phx-click={ + JS.push("edit_custom_field", value: %{id: custom_field.id}, target: @myself) + }> + {gettext("Edit")} + + + + <:action :let={{_id, custom_field}}> + <.link phx-click={ + JS.push("prepare_delete", value: %{id: custom_field.id}, target: @myself) + }> + {gettext("Delete")} + + + + + <%!-- Delete Confirmation Modal --%> + +
diff --git a/lib/mv_web/live/global_settings_live.ex b/lib/mv_web/live/global_settings_live.ex index bb919cb..0b3ec1c 100644 --- a/lib/mv_web/live/global_settings_live.ex +++ b/lib/mv_web/live/global_settings_live.ex @@ -46,22 +46,22 @@ defmodule MvWeb.GlobalSettingsLive do <%!-- Club Settings Section --%> - <.header> - {gettext("Club Settings")} - - <.form for={@form} id="settings-form" phx-change="validate" phx-submit="save"> - <.input - field={@form[:club_name]} - type="text" - label={gettext("Association Name")} - required - /> - - <.button phx-disable-with={gettext("Saving...")} variant="primary"> - {gettext("Save Settings")} - - + <.form_section title={gettext("Club Settings")}> + <.form for={@form} id="settings-form" phx-change="validate" phx-submit="save"> +
+ <.input + field={@form[:club_name]} + type="text" + label={gettext("Association Name")} + required + /> +
+ <.button phx-disable-with={gettext("Saving...")} variant="primary"> + {gettext("Save Settings")} + + + <%!-- Custom Fields Section --%> <.live_component module={MvWeb.CustomFieldLive.IndexComponent} diff --git a/lib/mv_web/live/member_live/form.ex b/lib/mv_web/live/member_live/form.ex index 5380d0f..87148ad 100644 --- a/lib/mv_web/live/member_live/form.ex +++ b/lib/mv_web/live/member_live/form.ex @@ -348,25 +348,6 @@ defmodule MvWeb.MemberLive.Form do defp return_path("show", nil), do: ~p"/members" defp return_path("show", member), do: ~p"/members/#{member.id}" - # ----------------------------------------------------------------- - # Helper Components - # ----------------------------------------------------------------- - - # Renders a form section box with border and title. - attr :title, :string, required: true - slot :inner_block, required: true - - defp form_section(assigns) do - ~H""" -
-

{@title}

-
- {render_slot(@inner_block)} -
-
- """ - end - # ----------------------------------------------------------------- # Helper Functions for Custom Fields # ----------------------------------------------------------------- From c3e95ca71171c673788c5d920a8004c137609261 Mon Sep 17 00:00:00 2001 From: carla Date: Mon, 8 Dec 2025 11:51:45 +0100 Subject: [PATCH 6/6] formatting --- lib/mv_web/components/core_components.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mv_web/components/core_components.ex b/lib/mv_web/components/core_components.ex index bee2d2a..d19b1eb 100644 --- a/lib/mv_web/components/core_components.ex +++ b/lib/mv_web/components/core_components.ex @@ -511,9 +511,9 @@ defmodule MvWeb.CoreComponents do
{col[:label]}{col[:label]} <.live_component module={MvWeb.Components.SortHeaderComponent} @@ -510,7 +535,33 @@ defmodule MvWeb.CoreComponents do {render_slot(col, @row_item.(row))} {render_slot(col, @row_item.(row))}