allow filtering ammo types when creating new packs and fix some form errors not displaying on create

This commit is contained in:
2024-10-26 15:15:14 -04:00
parent 7e14f292a6
commit ab3d3721d6
33 changed files with 404 additions and 266 deletions

View File

@ -9,7 +9,11 @@ defmodule CanneryWeb.PackLive.FormComponent do
alias Ecto.Changeset
alias Phoenix.LiveView.Socket
@pack_create_limit 10_000
@impl true
@spec mount(Socket.t()) :: {:ok, Socket.t()}
def mount(socket) do
{:ok, socket |> assign(:class, :all)}
end
@impl true
@spec update(
@ -24,7 +28,6 @@ defmodule CanneryWeb.PackLive.FormComponent do
def update(%{assigns: %{current_user: current_user}} = socket) do
socket =
socket
|> assign(:pack_create_limit, @pack_create_limit)
|> assign(:types, Ammo.list_types(current_user))
|> assign_new(:containers, fn -> Containers.list_containers(current_user) end)
@ -33,7 +36,20 @@ defmodule CanneryWeb.PackLive.FormComponent do
@impl true
def handle_event("validate", %{"pack" => pack_params}, socket) do
{:noreply, socket |> assign_changeset(pack_params, :validate)}
matched_class =
case pack_params["class"] do
"rifle" -> :rifle
"shotgun" -> :shotgun
"pistol" -> :pistol
_other -> :all
end
socket =
socket
|> assign_changeset(pack_params, :validate)
|> assign(:class, matched_class)
{:noreply, socket}
end
def handle_event(
@ -51,11 +67,18 @@ defmodule CanneryWeb.PackLive.FormComponent do
containers |> Enum.map(fn %{id: id, name: name} -> {name, id} end)
end
@spec type_options([Type.t()]) :: [{String.t(), Type.id()}]
defp type_options(types) do
@spec type_options([Type.t()], Type.class() | :all) ::
[{String.t(), Type.id()}]
defp type_options(types, :all) do
types |> Enum.map(fn %{id: id, name: name} -> {name, id} end)
end
defp type_options(types, selected_class) do
types
|> Enum.filter(fn %{class: class} -> class == selected_class end)
|> Enum.map(fn %{id: id, name: name} -> {name, id} end)
end
# Save Helpers
defp assign_changeset(
@ -126,53 +149,15 @@ defmodule CanneryWeb.PackLive.FormComponent do
end
defp save_pack(
%{assigns: %{changeset: changeset}} = socket,
%{assigns: %{changeset: changeset, current_user: current_user, return_to: return_to}} =
socket,
action,
%{"multiplier" => multiplier_str} = pack_params
)
when action in [:new, :clone] do
socket =
case multiplier_str |> Integer.parse() do
{multiplier, _remainder}
when multiplier >= 1 and multiplier <= @pack_create_limit ->
socket |> create_multiple(pack_params, multiplier)
{multiplier, _remainder} ->
error_msg =
dgettext(
"errors",
"Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}",
max: @pack_create_limit,
multiplier: multiplier
)
save_multiplier_error(socket, changeset, error_msg)
:error ->
error_msg = dgettext("errors", "Could not parse number of copies")
save_multiplier_error(socket, changeset, error_msg)
end
{:noreply, socket}
end
@spec save_multiplier_error(Socket.t(), Changeset.t(), String.t()) :: Socket.t()
defp save_multiplier_error(socket, changeset, error_msg) do
{:error, changeset} =
changeset
|> Changeset.add_error(:multiplier, error_msg)
|> Changeset.apply_action(:insert)
socket |> assign(:changeset, changeset)
end
defp create_multiple(
%{assigns: %{current_user: current_user, return_to: return_to}} = socket,
pack_params,
multiplier
) do
case Ammo.create_packs(pack_params, multiplier, current_user) do
{:ok, {count, _packs}} ->
with {multiplier, _remainder} <- multiplier_str |> Integer.parse(),
{:ok, {count, _packs}} <- Ammo.create_packs(pack_params, multiplier, current_user) do
prompt =
dngettext(
"prompts",
@ -182,9 +167,21 @@ defmodule CanneryWeb.PackLive.FormComponent do
)
socket |> put_flash(:info, prompt) |> push_navigate(to: return_to)
else
{:error, %Changeset{} = changeset} ->
socket |> assign(changeset: changeset)
{:error, %Changeset{} = changeset} ->
socket |> assign(changeset: changeset)
end
:error ->
error_msg = dgettext("errors", "Could not parse number of copies")
{:error, changeset} =
changeset
|> Changeset.add_error(:multiplier, error_msg)
|> Changeset.apply_action(:insert)
socket |> assign(:changeset, changeset)
end
{:noreply, socket}
end
end

View File

@ -19,8 +19,23 @@
<%= changeset_errors(@changeset) %>
</div>
<%= label(f, :class, gettext("Class"), class: "title text-lg text-primary-600") %>
<%= select(
f,
:class,
[
{gettext("Any"), :all},
{gettext("Rifle"), :rifle},
{gettext("Shotgun"), :shotgun},
{gettext("Pistol"), :pistol}
],
class: "text-center col-span-2 input input-primary",
value: @class
) %>
<%= error_tag(f, :class, "col-span-3 text-center") %>
<%= label(f, :type_id, gettext("Type"), class: "title text-lg text-primary-600") %>
<%= select(f, :type_id, type_options(@types),
<%= select(f, :type_id, type_options(@types, @class),
class: "text-center col-span-2 input input-primary",
id: "pack-form-type-select",
phx_hook: "SlimSelect"
@ -80,7 +95,6 @@
<%= label(f, :multiplier, gettext("Copies"), class: "title text-lg text-primary-600") %>
<%= number_input(f, :multiplier,
max: @pack_create_limit,
class: "text-center input input-primary",
value: 1,
phx_update: "ignore"