From 4b4ec63613fba26c4583696be3ae96d485e99cf8 Mon Sep 17 00:00:00 2001 From: Moritz Date: Thu, 20 Nov 2025 21:45:05 +0100 Subject: [PATCH] feat: improve user-member linking UI and error messages Reload members on email change, extract user-friendly errors from Ash, add translations --- lib/mv_web/live/user_live/form.ex | 39 ++++++++++++++++++++++++-- priv/gettext/de/LC_MESSAGES/default.po | 5 ++++ priv/gettext/de/LC_MESSAGES/errors.po | 4 +++ priv/gettext/default.pot | 5 ++++ priv/gettext/en/LC_MESSAGES/default.po | 5 ++++ priv/gettext/en/LC_MESSAGES/errors.po | 4 +++ priv/gettext/errors.pot | 4 +++ 7 files changed, 63 insertions(+), 3 deletions(-) diff --git a/lib/mv_web/live/user_live/form.ex b/lib/mv_web/live/user_live/form.ex index 9cf3f59..b8a0294 100644 --- a/lib/mv_web/live/user_live/form.ex +++ b/lib/mv_web/live/user_live/form.ex @@ -284,7 +284,20 @@ defmodule MvWeb.UserLive.Form do end def handle_event("validate", %{"user" => user_params}, socket) do - {:noreply, assign(socket, form: AshPhoenix.Form.validate(socket.assigns.form, user_params))} + validated_form = AshPhoenix.Form.validate(socket.assigns.form, user_params) + + # Reload members if email changed (for email-match priority) + socket = + if Map.has_key?(user_params, "email") do + user_email = user_params["email"] + members = load_members_for_linking(user_email, socket.assigns.member_search_query) + + assign(socket, form: validated_form, available_members: members) + else + assign(socket, form: validated_form) + end + + {:noreply, socket} end def handle_event("save", %{"user" => user_params}, socket) do @@ -319,9 +332,15 @@ defmodule MvWeb.UserLive.Form do {:noreply, socket} {:error, error} -> - # Show error from member linking/unlinking + # Show user-friendly error from member linking/unlinking + error_message = extract_error_message(error) + {:noreply, - put_flash(socket, :error, "Failed to update member relationship: #{inspect(error)}")} + put_flash( + socket, + :error, + gettext("Failed to link member: %{error}", error: error_message) + )} end {:error, form} -> @@ -460,4 +479,18 @@ defmodule MvWeb.UserLive.Form do [] end end + + # Extract user-friendly error message from Ash.Error + @spec extract_error_message(any()) :: String.t() + defp extract_error_message(%Ash.Error.Invalid{errors: errors}) when is_list(errors) do + # Take first error and extract message + case List.first(errors) do + %{message: message} when is_binary(message) -> message + %{field: field, message: message} -> "#{field}: #{message}" + _ -> "Unknown error" + end + end + + defp extract_error_message(error) when is_binary(error), do: error + defp extract_error_message(_), do: "Unknown error" end diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index 18e1053..7b8c86e 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -742,3 +742,8 @@ msgstr "Mitglied entverknüpfen" #, elixir-autogen, elixir-format msgid "Unlinking scheduled" msgstr "Entverknüpfung geplant" + +#: lib/mv_web/live/user_live/form.ex:342 +#, elixir-autogen, elixir-format +msgid "Failed to link member: %{error}" +msgstr "" diff --git a/priv/gettext/de/LC_MESSAGES/errors.po b/priv/gettext/de/LC_MESSAGES/errors.po index e0db8dd..92d3048 100644 --- a/priv/gettext/de/LC_MESSAGES/errors.po +++ b/priv/gettext/de/LC_MESSAGES/errors.po @@ -155,3 +155,7 @@ msgstr "muss mindestens 8 Zeichen lang sein" msgid "is required" msgstr "ist erforderlich" + +#: lib/mv_web/live/user_live/form.ex +msgid "Failed to link member: %{error}" +msgstr "Fehler beim Verknüpfen des Mitglieds: %{error}" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index a87d935..a1ae484 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -743,3 +743,8 @@ msgstr "" #, elixir-autogen, elixir-format msgid "Unlinking scheduled" msgstr "" + +#: lib/mv_web/live/user_live/form.ex:342 +#, elixir-autogen, elixir-format +msgid "Failed to link member: %{error}" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index e12b489..28339fc 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -743,3 +743,8 @@ msgstr "" #, elixir-autogen, elixir-format msgid "Unlinking scheduled" msgstr "" + +#: lib/mv_web/live/user_live/form.ex:342 +#, elixir-autogen, elixir-format +msgid "Failed to link member: %{error}" +msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/errors.po b/priv/gettext/en/LC_MESSAGES/errors.po index 62df4a7..e1f18de 100644 --- a/priv/gettext/en/LC_MESSAGES/errors.po +++ b/priv/gettext/en/LC_MESSAGES/errors.po @@ -155,3 +155,7 @@ msgstr "" msgid "is required" msgstr "" + +#: lib/mv_web/live/user_live/form.ex +msgid "Failed to link member: %{error}" +msgstr "" diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot index 8f522c0..5d840fe 100644 --- a/priv/gettext/errors.pot +++ b/priv/gettext/errors.pot @@ -152,3 +152,7 @@ msgstr "" msgid "is required" msgstr "" + +#: lib/mv_web/live/user_live/form.ex +msgid "Failed to link member: %{error}" +msgstr ""