diff --git a/lib/mv_web/live/join_live.ex b/lib/mv_web/live/join_live.ex
index d3d66f0..430a6fe 100644
--- a/lib/mv_web/live/join_live.ex
+++ b/lib/mv_web/live/join_live.ex
@@ -5,6 +5,7 @@ defmodule MvWeb.JoinLive do
"""
use MvWeb, :live_view
+ alias Ash.Resource.Info
alias Mv.Membership
alias MvWeb.JoinRateLimit
alias MvWeb.Translations.MemberFields
@@ -54,10 +55,6 @@ defmodule MvWeb.JoinLive do
{gettext("Become a member")}
-
- {gettext("Please enter your details for the membership application here.")}
-
-
<%= if @submitted do %>
@@ -67,6 +64,9 @@ defmodule MvWeb.JoinLive do
<% else %>
+
+ {gettext("Please enter your details for the membership application here.")}
+
<.form
for={@form}
id="join-form"
@@ -80,18 +80,31 @@ defmodule MvWeb.JoinLive do
<% end %>
<%= for field <- @join_fields do %>
-
+
-
+ <%= if field.input_type == "checkbox" do %>
+
+ <% else %>
+
+ <% end %>
<% end %>
@@ -216,21 +229,27 @@ 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)
+ custom_field_by_id = custom_field_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
- Map.get(custom_field_name_by_id, id, gettext("Field"))
- end
-
- %{id: id, label: label, required: required}
+ build_join_field(id, required, member_field_strings, custom_field_by_id)
end)
end
- defp custom_field_name_map(allowlist, member_field_strings) do
+ defp build_join_field(id, required, member_field_strings, custom_field_by_id) do
+ if id in member_field_strings do
+ label = MemberFields.label(String.to_existing_atom(id))
+ %{id: id, label: label, required: required, input_type: member_field_input_type(id)}
+ else
+ custom_field = Map.get(custom_field_by_id, id)
+ label = if custom_field, do: custom_field.name, else: gettext("Field")
+ input_type = custom_field_input_type(custom_field && custom_field.value_type)
+
+ %{id: id, label: label, required: required, input_type: input_type}
+ end
+ end
+
+ defp custom_field_map(allowlist, member_field_strings) do
custom_field_ids =
allowlist
|> Enum.map(& &1.id)
@@ -242,7 +261,7 @@ defmodule MvWeb.JoinLive do
ids ->
Mv.Membership.CustomField
- |> Ash.Query.select([:id, :name])
+ |> Ash.Query.select([:id, :name, :value_type])
|> Ash.read(domain: Mv.Membership, authorize?: false)
|> case do
{:ok, fields} ->
@@ -250,7 +269,7 @@ defmodule MvWeb.JoinLive do
fields
|> Enum.filter(&MapSet.member?(allowed_ids, &1.id))
- |> Map.new(&{&1.id, &1.name})
+ |> Map.new(&{&1.id, &1})
{:error, _} ->
%{}
@@ -265,8 +284,45 @@ defmodule MvWeb.JoinLive do
|> Map.put(@honeypot_field, "")
end
- defp input_type("email"), do: "email"
- defp input_type(_), do: "text"
+ defp member_field_input_type("email"), do: "email"
+
+ defp member_field_input_type(field_id) when is_binary(field_id) do
+ case member_field_atom(field_id) do
+ nil ->
+ "text"
+
+ field_atom ->
+ Mv.Membership.Member
+ |> Info.attribute(field_atom)
+ |> attribute_to_input_type()
+ end
+ end
+
+ defp member_field_input_type(_), do: "text"
+
+ defp member_field_atom(field_id) when is_binary(field_id) do
+ Mv.Constants.member_fields()
+ |> Enum.find(&(Atom.to_string(&1) == field_id))
+ end
+
+ defp custom_field_input_type(type), do: attribute_to_input_type(%{type: type})
+
+ defp attribute_to_input_type(%{type: type}) when type in [:date, Ash.Type.Date], do: "date"
+
+ defp attribute_to_input_type(%{type: type}) when type in [:integer, Ash.Type.Integer],
+ do: "number"
+
+ defp attribute_to_input_type(%{type: type}) when type in [:boolean, Ash.Type.Boolean],
+ do: "checkbox"
+
+ defp attribute_to_input_type(%{type: type}) when type in [:email, Mv.Membership.Email],
+ do: "email"
+
+ defp attribute_to_input_type(%{type: _}), do: "text"
+ defp attribute_to_input_type(nil), do: "text"
+
+ defp checkbox_checked?(value) when value in [true, "true", "on", "1"], do: true
+ defp checkbox_checked?(_), do: false
defp build_submit_attrs(params, join_fields) do
allowlist_ids = MapSet.new(Enum.map(join_fields, & &1.id))
diff --git a/test/mv_web/live/join_live_test.exs b/test/mv_web/live/join_live_test.exs
index 20cd5cf..7bac60f 100644
--- a/test/mv_web/live/join_live_test.exs
+++ b/test/mv_web/live/join_live_test.exs
@@ -192,7 +192,12 @@ defmodule MvWeb.JoinLiveTest do
{:ok, view, _html} = live(conn, "/join")
assert has_element?(view, "#join-form")
- assert has_element?(view, "input#join-field-#{boolean_field.id}[name='#{boolean_field.id}']")
+
+ assert has_element?(
+ view,
+ "input#join-field-#{boolean_field.id}[name='#{boolean_field.id}']"
+ )
+
assert has_element?(view, "input#join-field-#{boolean_field.id}[type='checkbox']")
refute has_element?(view, "input#join-field-#{boolean_field.id}[type='text']")
end
@@ -203,13 +208,19 @@ defmodule MvWeb.JoinLiveTest do
{:ok, settings} = Membership.get_settings()
{:ok, integer_field} =
- Membership.create_custom_field(%{name: "Lucky number", value_type: :integer}, actor: system_actor)
+ Membership.create_custom_field(%{name: "Lucky number", value_type: :integer},
+ actor: system_actor
+ )
{:ok, date_field} =
- Membership.create_custom_field(%{name: "Birth date", value_type: :date}, actor: system_actor)
+ Membership.create_custom_field(%{name: "Birth date", value_type: :date},
+ actor: system_actor
+ )
{:ok, email_field} =
- Membership.create_custom_field(%{name: "Secondary email", value_type: :email}, actor: system_actor)
+ Membership.create_custom_field(%{name: "Secondary email", value_type: :email},
+ actor: system_actor
+ )
{:ok, _} =
Membership.update_settings(settings, %{
@@ -229,6 +240,23 @@ defmodule MvWeb.JoinLiveTest do
assert has_element?(view, "input#join-field-#{date_field.id}[type='date']")
assert has_element?(view, "input#join-field-#{email_field.id}[type='email']")
end
+
+ @tag role: :unauthenticated
+ test "renders standard date member fields with date input type", %{conn: conn} do
+ {:ok, settings} = Membership.get_settings()
+
+ {:ok, _} =
+ Membership.update_settings(settings, %{
+ join_form_enabled: true,
+ join_form_field_ids: ["email", "join_date"],
+ join_form_field_required: %{"email" => true, "join_date" => false}
+ })
+
+ {:ok, view, _html} = live(conn, "/join")
+
+ assert has_element?(view, "input#join-field-join_date[type='date']")
+ refute has_element?(view, "input#join-field-join_date[type='text']")
+ end
end
describe "submit join form with typed custom fields" do