fix: labels for custom fields in join requests
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Simon 2026-05-06 11:05:28 +02:00
parent a6f6f402af
commit 0a7bbc7fa6
Signed by: simon
GPG key ID: 40E7A58C4AA1EDB2
4 changed files with 88 additions and 12 deletions

View file

@ -138,7 +138,7 @@ defmodule MvWeb.Layouts do
# Single get_settings() for layout; derive club_name and join_form_enabled to avoid duplicate query.
%{club_name: club_name, join_form_enabled: join_form_enabled} = get_layout_settings()
# TODO: unprocessed count runs on every page load when join form enabled; consider
# NOTE: Unprocessed count runs on every page load when join form is enabled; consider
# loading only on navigation or caching briefly if performance becomes an issue.
unprocessed_join_requests_count =
get_unprocessed_join_requests_count(assigns.current_user, join_form_enabled)

View file

@ -216,19 +216,48 @@ defmodule MvWeb.JoinLive do
defp build_join_fields_with_labels(allowlist) do
member_field_strings = Mv.Constants.member_fields() |> Enum.map(&Atom.to_string/1)
custom_field_name_by_id = custom_field_name_map(allowlist, member_field_strings)
Enum.map(allowlist, fn %{id: id, required: required} ->
label =
if id in member_field_strings do
MemberFields.label(String.to_existing_atom(id))
else
gettext("Field")
Map.get(custom_field_name_by_id, id, gettext("Field"))
end
%{id: id, label: label, required: required}
end)
end
defp custom_field_name_map(allowlist, member_field_strings) do
custom_field_ids =
allowlist
|> Enum.map(& &1.id)
|> Enum.reject(&(&1 in member_field_strings))
case custom_field_ids do
[] ->
%{}
ids ->
Mv.Membership.CustomField
|> Ash.Query.select([:id, :name])
|> Ash.read(domain: Mv.Membership, authorize?: false)
|> case do
{:ok, fields} ->
allowed_ids = MapSet.new(ids)
fields
|> Enum.filter(&MapSet.member?(allowed_ids, &1.id))
|> Map.new(&{&1.id, &1.name})
{:error, _} ->
%{}
end
end
end
defp initial_form_params(join_fields) do
join_fields
|> Enum.map(fn f -> {f.id, ""} end)

View file

@ -31,6 +31,7 @@ defmodule MvWeb.JoinRequestLive.Show do
{:ok,
socket
|> assign(:join_request, nil)
|> assign(:custom_field_name_by_id, %{})
|> assign(:join_form_field_ids, [])
|> Layouts.assign_page_title(gettext("Join request"))}
else
@ -53,9 +54,13 @@ defmodule MvWeb.JoinRequestLive.Show do
{:ok, request} ->
field_ids = Membership.get_join_form_allowlist() |> Enum.map(& &1.id)
custom_field_name_by_id =
custom_field_name_map(field_ids ++ Map.keys(request.form_data || %{}), actor)
{:noreply,
socket
|> assign(:join_request, request)
|> assign(:custom_field_name_by_id, custom_field_name_by_id)
|> assign(:join_form_field_ids, field_ids)
|> Layouts.assign_page_title(gettext("Join request %{email}", email: request.email))}
@ -132,7 +137,12 @@ defmodule MvWeb.JoinRequestLive.Show do
<div>
<h2 class="text-lg font-semibold mb-2">{gettext("Applicant data")}</h2>
<div class="border border-base-300 rounded-lg p-4 bg-base-100 space-y-2">
<%= for {label, value} <- applicant_data_rows(@join_request, @join_form_field_ids || []) do %>
<%= for {label, value} <-
applicant_data_rows(
@join_request,
@join_form_field_ids || [],
@custom_field_name_by_id || %{}
) do %>
<.field_row label={label} value={value} empty_text={gettext("Not specified")} />
<% end %>
</div>
@ -230,7 +240,7 @@ defmodule MvWeb.JoinRequestLive.Show do
# Builds a single list of {label, display_value} for all applicant-provided data in join form
# order. Typed fields (email, first_name, last_name) and form_data are merged; legacy
# form_data keys (not in current join form config) are appended at the end.
defp applicant_data_rows(join_request, ordered_field_ids) do
defp applicant_data_rows(join_request, ordered_field_ids, custom_field_name_by_id) do
member_field_strings = Constants.member_fields() |> Enum.map(&Atom.to_string/1)
form_data = join_request.form_data || %{}
@ -244,7 +254,7 @@ defmodule MvWeb.JoinRequestLive.Show do
ordered_field_ids
|> Enum.map(fn key ->
value = Map.get(typed, key) || Map.get(form_data, key)
label = field_key_to_label(key, member_field_strings)
label = field_key_to_label(key, member_field_strings, custom_field_name_by_id)
{label, format_applicant_value(value)}
end)
@ -258,7 +268,7 @@ defmodule MvWeb.JoinRequestLive.Show do
legacy_entries =
Enum.map(legacy_keys, fn key ->
label = field_key_to_label(key, member_field_strings)
label = field_key_to_label(key, member_field_strings, custom_field_name_by_id)
{label, format_applicant_value(form_data[key])}
end)
@ -299,11 +309,44 @@ defmodule MvWeb.JoinRequestLive.Show do
defp format_applicant_value_simple(raw, _value) when is_integer(raw), do: to_string(raw)
defp format_applicant_value_simple(_raw, value), do: to_string(value)
defp field_key_to_label(key, member_field_strings) when is_binary(key) do
if key in member_field_strings,
do: MemberFieldsTranslations.label(String.to_existing_atom(key)),
else: key
defp field_key_to_label(key, member_field_strings, custom_field_name_by_id)
when is_binary(key) do
if key in member_field_strings do
MemberFieldsTranslations.label(String.to_existing_atom(key))
else
Map.get(custom_field_name_by_id, key, key)
end
end
defp field_key_to_label(key, _), do: to_string(key)
defp field_key_to_label(key, _, _), do: to_string(key)
defp custom_field_name_map(field_keys, actor) do
member_field_strings = Constants.member_fields() |> Enum.map(&Atom.to_string/1)
custom_field_ids =
field_keys
|> Enum.uniq()
|> Enum.reject(&(&1 in member_field_strings))
case custom_field_ids do
[] ->
%{}
ids ->
Mv.Membership.CustomField
|> Ash.Query.select([:id, :name])
|> Ash.read(actor: actor, domain: Mv.Membership)
|> case do
{:ok, fields} ->
allowed_ids = MapSet.new(ids)
fields
|> Enum.filter(&MapSet.member?(allowed_ids, &1.id))
|> Map.new(&{&1.id, &1.name})
{:error, _} ->
%{}
end
end
end
end