diff --git a/lib/mv_web/components/layouts.ex b/lib/mv_web/components/layouts.ex
index 54f589d..9aff23c 100644
--- a/lib/mv_web/components/layouts.ex
+++ b/lib/mv_web/components/layouts.ex
@@ -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)
diff --git a/lib/mv_web/live/join_live.ex b/lib/mv_web/live/join_live.ex
index 3b8db05..d3d66f0 100644
--- a/lib/mv_web/live/join_live.ex
+++ b/lib/mv_web/live/join_live.ex
@@ -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)
diff --git a/lib/mv_web/live/join_request_live/show.ex b/lib/mv_web/live/join_request_live/show.ex
index 304cb6a..2aab87d 100644
--- a/lib/mv_web/live/join_request_live/show.ex
+++ b/lib/mv_web/live/join_request_live/show.ex
@@ -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
{gettext("Applicant data")}
- <%= 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 %>
@@ -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
diff --git a/test/mv_web/live/join_live_test.exs b/test/mv_web/live/join_live_test.exs
index 383b413..273e786 100644
--- a/test/mv_web/live/join_live_test.exs
+++ b/test/mv_web/live/join_live_test.exs
@@ -159,7 +159,11 @@ defmodule MvWeb.JoinLiveTest do
{:ok, view, _html} = live(conn, "/join")
- assert has_element?(view, "label[for='join-field-#{custom_field.id}'] .label-text", custom_field.name)
+ assert has_element?(
+ view,
+ "label[for='join-field-#{custom_field.id}'] .label-text",
+ custom_field.name
+ )
end
end