feat: improve user-member linking UI and error messages
All checks were successful
continuous-integration/drone/push Build is passing

Reload members on email change, extract user-friendly errors from Ash, add translations
This commit is contained in:
Moritz 2025-11-20 21:45:05 +01:00
parent df05eafc99
commit 4b4ec63613
7 changed files with 63 additions and 3 deletions

View file

@ -284,7 +284,20 @@ defmodule MvWeb.UserLive.Form do
end end
def handle_event("validate", %{"user" => user_params}, socket) do 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 end
def handle_event("save", %{"user" => user_params}, socket) do def handle_event("save", %{"user" => user_params}, socket) do
@ -319,9 +332,15 @@ defmodule MvWeb.UserLive.Form do
{:noreply, socket} {:noreply, socket}
{:error, error} -> {:error, error} ->
# Show error from member linking/unlinking # Show user-friendly error from member linking/unlinking
error_message = extract_error_message(error)
{:noreply, {: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 end
{:error, form} -> {:error, form} ->
@ -460,4 +479,18 @@ defmodule MvWeb.UserLive.Form do
[] []
end end
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 end

View file

@ -742,3 +742,8 @@ msgstr "Mitglied entverknüpfen"
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Unlinking scheduled" msgid "Unlinking scheduled"
msgstr "Entverknüpfung geplant" msgstr "Entverknüpfung geplant"
#: lib/mv_web/live/user_live/form.ex:342
#, elixir-autogen, elixir-format
msgid "Failed to link member: %{error}"
msgstr ""

View file

@ -155,3 +155,7 @@ msgstr "muss mindestens 8 Zeichen lang sein"
msgid "is required" msgid "is required"
msgstr "ist erforderlich" 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}"

View file

@ -743,3 +743,8 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Unlinking scheduled" msgid "Unlinking scheduled"
msgstr "" msgstr ""
#: lib/mv_web/live/user_live/form.ex:342
#, elixir-autogen, elixir-format
msgid "Failed to link member: %{error}"
msgstr ""

View file

@ -743,3 +743,8 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Unlinking scheduled" msgid "Unlinking scheduled"
msgstr "" msgstr ""
#: lib/mv_web/live/user_live/form.ex:342
#, elixir-autogen, elixir-format
msgid "Failed to link member: %{error}"
msgstr ""

View file

@ -155,3 +155,7 @@ msgstr ""
msgid "is required" msgid "is required"
msgstr "" msgstr ""
#: lib/mv_web/live/user_live/form.ex
msgid "Failed to link member: %{error}"
msgstr ""

View file

@ -152,3 +152,7 @@ msgstr ""
msgid "is required" msgid "is required"
msgstr "" msgstr ""
#: lib/mv_web/live/user_live/form.ex
msgid "Failed to link member: %{error}"
msgstr ""