forked from shibao/cannery
allow filtering ammo types when creating new packs and fix some form errors not displaying on create
This commit is contained in:
@ -959,25 +959,79 @@ defmodule Cannery.Ammo do
|
||||
|
||||
defp do_create_packs(
|
||||
%{"type_id" => type_id, "container_id" => container_id} = attrs,
|
||||
_multiplier,
|
||||
multiplier,
|
||||
user
|
||||
)
|
||||
when is_binary(type_id) and is_binary(container_id) do
|
||||
changeset =
|
||||
%Pack{}
|
||||
|> Pack.create_changeset(
|
||||
get_type!(type_id, user),
|
||||
Containers.get_container!(container_id, user),
|
||||
user,
|
||||
attrs
|
||||
)
|
||||
|> Changeset.add_error(:multiplier, dgettext("errors", "Invalid multiplier"))
|
||||
|
||||
{:error, changeset}
|
||||
%Pack{}
|
||||
|> Pack.create_changeset(
|
||||
get_type!(type_id, user),
|
||||
Containers.get_container!(container_id, user),
|
||||
user,
|
||||
attrs
|
||||
)
|
||||
|> maybe_add_multiplier_error(multiplier)
|
||||
|> Changeset.apply_action(:insert)
|
||||
end
|
||||
|
||||
defp do_create_packs(invalid_attrs, _multiplier, user) do
|
||||
{:error, %Pack{} |> Pack.create_changeset(nil, nil, user, invalid_attrs)}
|
||||
defp do_create_packs(
|
||||
%{"type_id" => type_id} = attrs,
|
||||
multiplier,
|
||||
user
|
||||
)
|
||||
when is_binary(type_id) do
|
||||
%Pack{}
|
||||
|> Pack.create_changeset(
|
||||
get_type!(type_id, user),
|
||||
nil,
|
||||
user,
|
||||
attrs
|
||||
)
|
||||
|> maybe_add_multiplier_error(multiplier)
|
||||
|> Changeset.apply_action(:insert)
|
||||
end
|
||||
|
||||
defp do_create_packs(
|
||||
%{"container_id" => container_id} = attrs,
|
||||
multiplier,
|
||||
user
|
||||
)
|
||||
when is_binary(container_id) do
|
||||
%Pack{}
|
||||
|> Pack.create_changeset(
|
||||
nil,
|
||||
Containers.get_container!(container_id, user),
|
||||
user,
|
||||
attrs
|
||||
)
|
||||
|> maybe_add_multiplier_error(multiplier)
|
||||
|> Changeset.apply_action(:insert)
|
||||
end
|
||||
|
||||
defp do_create_packs(invalid_attrs, multiplier, user) do
|
||||
%Pack{}
|
||||
|> Pack.create_changeset(nil, nil, user, invalid_attrs)
|
||||
|> maybe_add_multiplier_error(multiplier)
|
||||
|> Changeset.apply_action(:insert)
|
||||
end
|
||||
|
||||
defp maybe_add_multiplier_error(changeset, multiplier)
|
||||
when multiplier >= 1 and
|
||||
multiplier <= @pack_create_limit do
|
||||
changeset
|
||||
end
|
||||
|
||||
defp maybe_add_multiplier_error(changeset, multiplier) do
|
||||
changeset
|
||||
|> Changeset.add_error(
|
||||
:multiplier,
|
||||
dgettext(
|
||||
"errors",
|
||||
"Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}",
|
||||
max: @pack_create_limit,
|
||||
multiplier: multiplier
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@spec preload_pack(Pack.t()) :: Pack.t()
|
||||
|
@ -70,36 +70,45 @@ defmodule Cannery.Ammo.Pack do
|
||||
) :: changeset()
|
||||
def create_changeset(
|
||||
pack,
|
||||
%Type{id: type_id},
|
||||
%Container{id: container_id, user_id: user_id},
|
||||
type,
|
||||
container,
|
||||
%User{id: user_id},
|
||||
attrs
|
||||
)
|
||||
when is_binary(type_id) and is_binary(container_id) and is_binary(user_id) do
|
||||
when is_binary(user_id) do
|
||||
type_id =
|
||||
case type do
|
||||
%Type{id: type_id} when is_binary(type_id) ->
|
||||
type_id
|
||||
|
||||
_invalid_type ->
|
||||
nil
|
||||
end
|
||||
|
||||
container_id =
|
||||
case container do
|
||||
%Container{id: container_id, user_id: ^user_id} when is_binary(container_id) ->
|
||||
container_id
|
||||
|
||||
_invalid_container ->
|
||||
nil
|
||||
end
|
||||
|
||||
pack
|
||||
|> change(type_id: type_id)
|
||||
|> change(user_id: user_id)
|
||||
|> change(container_id: container_id)
|
||||
|> cast(attrs, [:count, :price_paid, :notes, :staged, :purchased_on, :lot_number])
|
||||
|> change(user_id: user_id)
|
||||
|> cast(attrs, [:count, :lot_number, :notes, :price_paid, :purchased_on, :staged])
|
||||
|> validate_required(:type_id, message: dgettext("errors", "Please select a valid type"))
|
||||
|> validate_required(:container_id,
|
||||
message: dgettext("errors", "Please select a valid container")
|
||||
)
|
||||
|> validate_number(:count, greater_than: 0)
|
||||
|> validate_number(:price_paid, greater_than_or_equal_to: 0)
|
||||
|> validate_length(:lot_number, max: 255)
|
||||
|> validate_required([:count, :staged, :purchased_on, :type_id, :container_id, :user_id])
|
||||
end
|
||||
|
||||
@doc """
|
||||
Invalid changeset, used to prompt user to select type and container
|
||||
"""
|
||||
def create_changeset(pack, _invalid_type, _invalid_container, _invalid_user, attrs) do
|
||||
pack
|
||||
|> cast(attrs, [:type_id, :container_id])
|
||||
|> validate_required([:type_id, :container_id])
|
||||
|> validate_number(:count, greater_than: 0)
|
||||
|> validate_number(:price_paid, greater_than_or_equal_to: 0)
|
||||
|> validate_length(:lot_number, max: 255)
|
||||
|> add_error(:invalid, dgettext("errors", "Please select a type and container"))
|
||||
end
|
||||
|
||||
@doc false
|
||||
@spec update_changeset(t() | new_pack(), attrs :: map(), User.t()) :: changeset()
|
||||
def update_changeset(pack, attrs, user) do
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
Reference in New Issue
Block a user