display used-up date on used-up ammo
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		| @@ -4,7 +4,7 @@ defmodule CanneryWeb.Components.AmmoGroupCard do | ||||
|   """ | ||||
|  | ||||
|   use CanneryWeb, :component | ||||
|   alias Cannery.Repo | ||||
|   alias Cannery.{Ammo, Repo} | ||||
|   alias CanneryWeb.Endpoint | ||||
|  | ||||
|   def ammo_group_card(%{ammo_group: ammo_group} = assigns) do | ||||
| @@ -47,6 +47,13 @@ defmodule CanneryWeb.Components.AmmoGroupCard do | ||||
|           <%= @ammo_group.inserted_at |> display_datetime() %> | ||||
|         </span> | ||||
|  | ||||
|         <%= if @ammo_group.count == 0 do %> | ||||
|           <span class="rounded-lg title text-lg"> | ||||
|             <%= gettext("Used up on:") %> | ||||
|             <%= @ammo_group |> Ammo.get_last_used_shot_group() |> Map.get(:date) |> display_date() %> | ||||
|           </span> | ||||
|         <% end %> | ||||
|  | ||||
|         <%= if @ammo_group.price_paid do %> | ||||
|           <span class="rounded-lg title text-lg"> | ||||
|             <%= gettext("Price paid:") %> | ||||
|   | ||||
| @@ -6,7 +6,7 @@ defmodule CanneryWeb.Components.TableComponent do | ||||
|     - `:columns`: An array of maps containing the following keys | ||||
|       - `:label`: A gettext'd or otherwise user-facing string label for the | ||||
|         column. Can be nil | ||||
|       - `:key`: A string key used for sorting | ||||
|       - `:key`: An atom key used for sorting | ||||
|       - `:class`: Extra classes to be applied to the column element, if desired. | ||||
|         Optional | ||||
|       - `:sortable`: If false, will prevent the user from sorting with it. | ||||
| @@ -28,13 +28,13 @@ defmodule CanneryWeb.Components.TableComponent do | ||||
|             required(:columns) => | ||||
|               list(%{ | ||||
|                 required(:label) => String.t() | nil, | ||||
|                 required(:key) => String.t() | nil, | ||||
|                 required(:key) => atom() | nil, | ||||
|                 optional(:class) => String.t(), | ||||
|                 optional(:sortable) => false | ||||
|               }), | ||||
|             required(:rows) => | ||||
|               list(%{ | ||||
|                 (key :: String.t()) => any() | {custom_sort_value :: String.t(), value :: any()} | ||||
|                 (key :: atom()) => any() | {custom_sort_value :: String.t(), value :: any()} | ||||
|               }), | ||||
|             optional(any()) => any() | ||||
|           }, | ||||
| @@ -56,20 +56,19 @@ defmodule CanneryWeb.Components.TableComponent do | ||||
|   def handle_event( | ||||
|         "sort_by", | ||||
|         %{"sort-key" => key}, | ||||
|         %{assigns: %{rows: rows, last_sort_key: key, sort_mode: sort_mode}} = socket | ||||
|         %{assigns: %{rows: rows, last_sort_key: last_sort_key, sort_mode: sort_mode}} = socket | ||||
|       ) do | ||||
|     sort_mode = if sort_mode == :asc, do: :desc, else: :asc | ||||
|     rows = rows |> sort_by_custom_sort_value_or_value(key, sort_mode) | ||||
|     {:noreply, socket |> assign(sort_mode: sort_mode, rows: rows)} | ||||
|   end | ||||
|     key = key |> String.to_existing_atom() | ||||
|  | ||||
|   def handle_event( | ||||
|         "sort_by", | ||||
|         %{"sort-key" => key}, | ||||
|         %{assigns: %{rows: rows}} = socket | ||||
|       ) do | ||||
|     rows = rows |> sort_by_custom_sort_value_or_value(key, :asc) | ||||
|     {:noreply, socket |> assign(last_sort_key: key, sort_mode: :asc, rows: rows)} | ||||
|     sort_mode = | ||||
|       case {key, sort_mode} do | ||||
|         {^last_sort_key, :asc} -> :desc | ||||
|         {^last_sort_key, :desc} -> :asc | ||||
|         {_new_sort_key, _last_sort_mode} -> :asc | ||||
|       end | ||||
|  | ||||
|     rows = rows |> sort_by_custom_sort_value_or_value(key, sort_mode) | ||||
|     {:noreply, socket |> assign(last_sort_key: key, sort_mode: sort_mode, rows: rows)} | ||||
|   end | ||||
|  | ||||
|   defp sort_by_custom_sort_value_or_value(rows, key, sort_mode) do | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| <div class="w-full overflow-x-auto border border-gray-600 rounded-lg shadow-lg bg-black"> | ||||
| <div id={@id} class="w-full overflow-x-auto border border-gray-600 rounded-lg shadow-lg bg-black"> | ||||
|   <table class="min-w-full table-auto text-center bg-white"> | ||||
|     <thead class="border-b border-primary-600"> | ||||
|       <tr> | ||||
|   | ||||
| @@ -73,7 +73,7 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def handle_event("toggle_show_used", _, %{assigns: %{show_used: show_used}} = socket) do | ||||
|   def handle_event("toggle_show_used", _params, %{assigns: %{show_used: show_used}} = socket) do | ||||
|     {:noreply, socket |> assign(:show_used, !show_used) |> display_ammo_groups()} | ||||
|   end | ||||
|  | ||||
| @@ -87,16 +87,24 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | ||||
|     containers_count = Containers.get_containers_count!(current_user) | ||||
|  | ||||
|     columns = [ | ||||
|       %{label: gettext("Ammo type"), key: "ammo_type"}, | ||||
|       %{label: gettext("Count"), key: "count"}, | ||||
|       %{label: gettext("Price paid"), key: "price_paid"}, | ||||
|       %{label: gettext("% left"), key: "remaining"}, | ||||
|       %{label: gettext("Range"), key: "range"}, | ||||
|       %{label: gettext("Container"), key: "container"}, | ||||
|       %{label: gettext("Added on"), key: "added_on"}, | ||||
|       %{label: nil, key: "actions", sortable: false} | ||||
|       %{label: gettext("Ammo type"), key: :ammo_type}, | ||||
|       %{label: gettext("Count"), key: :count}, | ||||
|       %{label: gettext("Price paid"), key: :price_paid}, | ||||
|       %{label: gettext("% left"), key: :remaining}, | ||||
|       %{label: gettext("Range"), key: :range}, | ||||
|       %{label: gettext("Container"), key: :container}, | ||||
|       %{label: gettext("Added on"), key: :added_on} | ||||
|     ] | ||||
|  | ||||
|     columns = | ||||
|       if show_used do | ||||
|         columns ++ [%{label: gettext("Used up on"), key: :used_up_on}] | ||||
|       else | ||||
|         columns | ||||
|       end | ||||
|  | ||||
|     columns = columns ++ [%{label: nil, key: :actions, sortable: false}] | ||||
|  | ||||
|     rows = | ||||
|       ammo_groups | ||||
|       |> Enum.map(fn ammo_group -> ammo_group |> get_row_data_for_ammo_group(columns) end) | ||||
| @@ -119,8 +127,8 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | ||||
|     |> Enum.into(%{}, fn %{key: key} -> {key, get_value_for_key(key, ammo_group)} end) | ||||
|   end | ||||
|  | ||||
|   @spec get_value_for_key(String.t(), AmmoGroup.t()) :: any() | ||||
|   defp get_value_for_key("ammo_type", %{ammo_type: ammo_type}) do | ||||
|   @spec get_value_for_key(atom(), AmmoGroup.t()) :: any() | ||||
|   defp get_value_for_key(:ammo_type, %{ammo_type: ammo_type}) do | ||||
|     {ammo_type.name, | ||||
|      live_patch(ammo_type.name, | ||||
|        to: Routes.ammo_type_show_path(Endpoint, :show, ammo_type), | ||||
| @@ -128,12 +136,12 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | ||||
|      )} | ||||
|   end | ||||
|  | ||||
|   defp get_value_for_key("price_paid", %{price_paid: nil}), do: {"a", nil} | ||||
|   defp get_value_for_key(:price_paid, %{price_paid: nil}), do: {"a", nil} | ||||
|  | ||||
|   defp get_value_for_key("price_paid", %{price_paid: price_paid}), | ||||
|   defp get_value_for_key(:price_paid, %{price_paid: price_paid}), | ||||
|     do: gettext("$%{amount}", amount: price_paid |> :erlang.float_to_binary(decimals: 2)) | ||||
|  | ||||
|   defp get_value_for_key("added_on", %{inserted_at: inserted_at}) do | ||||
|   defp get_value_for_key(:added_on, %{inserted_at: inserted_at}) do | ||||
|     assigns = %{inserted_at: inserted_at} | ||||
|  | ||||
|     {inserted_at, | ||||
| @@ -142,7 +150,22 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | ||||
|      """} | ||||
|   end | ||||
|  | ||||
|   defp get_value_for_key("range", %{staged: staged} = ammo_group) do | ||||
|   defp get_value_for_key(:used_up_on, ammo_group) do | ||||
|     last_shot_group_date = | ||||
|       case ammo_group |> Ammo.get_last_used_shot_group() do | ||||
|         %{date: last_shot_group_date} -> last_shot_group_date | ||||
|         _no_shot_groups -> nil | ||||
|       end | ||||
|  | ||||
|     assigns = %{last_shot_group_date: last_shot_group_date} | ||||
|  | ||||
|     {last_shot_group_date, | ||||
|      ~H""" | ||||
|      <%= @last_shot_group_date |> display_date() %> | ||||
|      """} | ||||
|   end | ||||
|  | ||||
|   defp get_value_for_key(:range, %{staged: staged} = ammo_group) do | ||||
|     assigns = %{ammo_group: ammo_group} | ||||
|  | ||||
|     {staged, | ||||
| @@ -165,10 +188,10 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | ||||
|      """} | ||||
|   end | ||||
|  | ||||
|   defp get_value_for_key("remaining", ammo_group), | ||||
|   defp get_value_for_key(:remaining, ammo_group), | ||||
|     do: "#{ammo_group |> Ammo.get_percentage_remaining()}%" | ||||
|  | ||||
|   defp get_value_for_key("actions", ammo_group) do | ||||
|   defp get_value_for_key(:actions, ammo_group) do | ||||
|     assigns = %{ammo_group: ammo_group} | ||||
|  | ||||
|     ~H""" | ||||
| @@ -199,9 +222,9 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | ||||
|     """ | ||||
|   end | ||||
|  | ||||
|   defp get_value_for_key("container", %{container: nil}), do: {nil, nil} | ||||
|   defp get_value_for_key(:container, %{container: nil}), do: {nil, nil} | ||||
|  | ||||
|   defp get_value_for_key("container", %{container: %{name: container_name}} = ammo_group) do | ||||
|   defp get_value_for_key(:container, %{container: %{name: container_name}} = ammo_group) do | ||||
|     assigns = %{ammo_group: ammo_group} | ||||
|  | ||||
|     {container_name, | ||||
| @@ -222,6 +245,5 @@ defmodule CanneryWeb.AmmoGroupLive.Index do | ||||
|      """} | ||||
|   end | ||||
|  | ||||
|   defp get_value_for_key(key, ammo_group), | ||||
|     do: ammo_group |> Map.get(key |> String.to_existing_atom()) | ||||
|   defp get_value_for_key(key, ammo_group), do: ammo_group |> Map.get(key) | ||||
| end | ||||
|   | ||||
| @@ -84,10 +84,10 @@ defmodule CanneryWeb.AmmoGroupLive.Show do | ||||
|     ammo_group = ammo_group |> Repo.preload([:container, :ammo_type, :shot_groups], force: true) | ||||
|  | ||||
|     columns = [ | ||||
|       %{label: gettext("Rounds shot"), key: "count"}, | ||||
|       %{label: gettext("Notes"), key: "notes"}, | ||||
|       %{label: gettext("Date"), key: "date"}, | ||||
|       %{label: nil, key: "actions", sortable: false} | ||||
|       %{label: gettext("Rounds shot"), key: :count}, | ||||
|       %{label: gettext("Notes"), key: :notes}, | ||||
|       %{label: gettext("Date"), key: :date}, | ||||
|       %{label: nil, key: :actions, sortable: false} | ||||
|     ] | ||||
|  | ||||
|     rows = | ||||
| @@ -110,10 +110,10 @@ defmodule CanneryWeb.AmmoGroupLive.Show do | ||||
|     |> Enum.into(%{}, fn %{key: key} -> | ||||
|       value = | ||||
|         case key do | ||||
|           "date" -> | ||||
|           :date -> | ||||
|             {date, date |> display_date()} | ||||
|  | ||||
|           "actions" -> | ||||
|           :actions -> | ||||
|             ~H""" | ||||
|             <div class="px-4 py-2 space-x-4 flex justify-center items-center"> | ||||
|               <%= live_patch to: Routes.ammo_group_show_path(Endpoint, :edit_shot_group, @ammo_group, shot_group), | ||||
| @@ -136,7 +136,7 @@ defmodule CanneryWeb.AmmoGroupLive.Show do | ||||
|             """ | ||||
|  | ||||
|           key -> | ||||
|             shot_group |> Map.get(key |> String.to_existing_atom()) | ||||
|             shot_group |> Map.get(key) | ||||
|         end | ||||
|  | ||||
|       {key, value} | ||||
|   | ||||
| @@ -48,29 +48,29 @@ defmodule CanneryWeb.AmmoTypeLive.Index do | ||||
|  | ||||
|     columns = | ||||
|       [ | ||||
|         %{label: gettext("Name"), key: "name", type: :name}, | ||||
|         %{label: gettext("Bullet type"), key: "bullet_type", type: :string}, | ||||
|         %{label: gettext("Bullet core"), key: "bullet_core", type: :string}, | ||||
|         %{label: gettext("Cartridge"), key: "cartridge", type: :string}, | ||||
|         %{label: gettext("Caliber"), key: "caliber", type: :string}, | ||||
|         %{label: gettext("Case material"), key: "case_material", type: :string}, | ||||
|         %{label: gettext("Jacket type"), key: "jacket_type", type: :string}, | ||||
|         %{label: gettext("Muzzle velocity"), key: "muzzle_velocity", type: :string}, | ||||
|         %{label: gettext("Powder type"), key: "powder_type", type: :string}, | ||||
|         %{label: gettext("Name"), key: :name, type: :name}, | ||||
|         %{label: gettext("Bullet type"), key: :bullet_type, type: :string}, | ||||
|         %{label: gettext("Bullet core"), key: :bullet_core, type: :string}, | ||||
|         %{label: gettext("Cartridge"), key: :cartridge, type: :string}, | ||||
|         %{label: gettext("Caliber"), key: :caliber, type: :string}, | ||||
|         %{label: gettext("Case material"), key: :case_material, type: :string}, | ||||
|         %{label: gettext("Jacket type"), key: :jacket_type, type: :string}, | ||||
|         %{label: gettext("Muzzle velocity"), key: :muzzle_velocity, type: :string}, | ||||
|         %{label: gettext("Powder type"), key: :powder_type, type: :string}, | ||||
|         %{ | ||||
|           label: gettext("Powder grains per charge"), | ||||
|           key: "powder_grains_per_charge", | ||||
|           key: :powder_grains_per_charge, | ||||
|           type: :string | ||||
|         }, | ||||
|         %{label: gettext("Grains"), key: "grains", type: :string}, | ||||
|         %{label: gettext("Pressure"), key: "pressure", type: :string}, | ||||
|         %{label: gettext("Primer type"), key: "primer_type", type: :string}, | ||||
|         %{label: gettext("Firing type"), key: "firing_type", type: :string}, | ||||
|         %{label: gettext("Tracer"), key: "tracer", type: :boolean}, | ||||
|         %{label: gettext("Incendiary"), key: "incendiary", type: :boolean}, | ||||
|         %{label: gettext("Blank"), key: "blank", type: :boolean}, | ||||
|         %{label: gettext("Corrosive"), key: "corrosive", type: :boolean}, | ||||
|         %{label: gettext("Manufacturer"), key: "manufacturer", type: :string}, | ||||
|         %{label: gettext("Grains"), key: :grains, type: :string}, | ||||
|         %{label: gettext("Pressure"), key: :pressure, type: :string}, | ||||
|         %{label: gettext("Primer type"), key: :primer_type, type: :string}, | ||||
|         %{label: gettext("Firing type"), key: :firing_type, type: :string}, | ||||
|         %{label: gettext("Tracer"), key: :tracer, type: :boolean}, | ||||
|         %{label: gettext("Incendiary"), key: :incendiary, type: :boolean}, | ||||
|         %{label: gettext("Blank"), key: :blank, type: :boolean}, | ||||
|         %{label: gettext("Corrosive"), key: :corrosive, type: :boolean}, | ||||
|         %{label: gettext("Manufacturer"), key: :manufacturer, type: :string}, | ||||
|         %{label: gettext("UPC"), key: "upc", type: :string} | ||||
|       ] | ||||
|       |> Enum.filter(fn %{key: key, type: type} -> | ||||
| @@ -79,13 +79,13 @@ defmodule CanneryWeb.AmmoTypeLive.Index do | ||||
|  | ||||
|         ammo_types | ||||
|         |> Enum.any?(fn ammo_type -> | ||||
|           not (ammo_type |> Map.get(key |> String.to_existing_atom()) == default_value) | ||||
|           not (ammo_type |> Map.get(key) == default_value) | ||||
|         end) | ||||
|       end) | ||||
|       |> Kernel.++([ | ||||
|         %{label: gettext("Total # of rounds"), key: "round_count", type: :round_count}, | ||||
|         %{label: gettext("Total # of ammo"), key: "ammo_count", type: :ammo_count}, | ||||
|         %{label: gettext("Average Price paid"), key: "avg_price_paid", type: :avg_price_paid}, | ||||
|         %{label: gettext("Total # of rounds"), key: :round_count, type: :round_count}, | ||||
|         %{label: gettext("Total # of ammo"), key: :ammo_count, type: :ammo_count}, | ||||
|         %{label: gettext("Average Price paid"), key: :avg_price_paid, type: :avg_price_paid}, | ||||
|         %{label: nil, key: "actions", type: :actions, sortable: false} | ||||
|       ]) | ||||
|  | ||||
| @@ -104,7 +104,7 @@ defmodule CanneryWeb.AmmoTypeLive.Index do | ||||
|   end | ||||
|  | ||||
|   defp get_ammo_type_value(:boolean, key, ammo_type, _current_user), | ||||
|     do: ammo_type |> Map.get(key |> String.to_existing_atom()) |> humanize() | ||||
|     do: ammo_type |> Map.get(key) |> humanize() | ||||
|  | ||||
|   defp get_ammo_type_value(:round_count, _key, ammo_type, current_user), | ||||
|     do: ammo_type |> Ammo.get_round_count_for_ammo_type(current_user) | ||||
| @@ -164,6 +164,5 @@ defmodule CanneryWeb.AmmoTypeLive.Index do | ||||
|  | ||||
|   defp get_ammo_type_value(nil, _key, _ammo_type, _current_user), do: nil | ||||
|  | ||||
|   defp get_ammo_type_value(_other, key, ammo_type, _current_user), | ||||
|     do: ammo_type |> Map.get(key |> String.to_existing_atom()) | ||||
|   defp get_ammo_type_value(_other, key, ammo_type, _current_user), do: ammo_type |> Map.get(key) | ||||
| end | ||||
|   | ||||
| @@ -32,7 +32,7 @@ defmodule CanneryWeb.AmmoTypeLive.Show do | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def handle_event("toggle_show_used", _, %{assigns: %{show_used: show_used}} = socket) do | ||||
|   def handle_event("toggle_show_used", _params, %{assigns: %{show_used: show_used}} = socket) do | ||||
|     {:noreply, socket |> assign(:show_used, !show_used) |> display_ammo_type()} | ||||
|   end | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,7 @@ defmodule CanneryWeb.ContainerLive.Show do | ||||
|  | ||||
|   use CanneryWeb, :live_view | ||||
|   import CanneryWeb.Components.{AmmoGroupCard, TagCard} | ||||
|   alias Cannery.{Ammo, Accounts.User, Containers, Containers.Container, Repo, Tags} | ||||
|   alias Cannery.{Accounts.User, Ammo, Containers, Containers.Container, Repo, Tags} | ||||
|   alias CanneryWeb.Endpoint | ||||
|   alias Ecto.Changeset | ||||
|   alias Phoenix.LiveView.Socket | ||||
| @@ -83,7 +83,7 @@ defmodule CanneryWeb.ContainerLive.Show do | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def handle_event("toggle_show_used", _, %{assigns: %{show_used: show_used}} = socket) do | ||||
|   def handle_event("toggle_show_used", _params, %{assigns: %{show_used: show_used}} = socket) do | ||||
|     {:noreply, socket |> assign(:show_used, !show_used) |> render_container()} | ||||
|   end | ||||
|  | ||||
|   | ||||
| @@ -77,11 +77,11 @@ defmodule CanneryWeb.RangeLive.Index do | ||||
|     ammo_groups = Ammo.list_staged_ammo_groups(current_user) | ||||
|  | ||||
|     columns = [ | ||||
|       %{label: gettext("Ammo"), key: "name"}, | ||||
|       %{label: gettext("Rounds shot"), key: "count"}, | ||||
|       %{label: gettext("Notes"), key: "notes"}, | ||||
|       %{label: gettext("Date"), key: "date"}, | ||||
|       %{label: nil, key: "actions", sortable: false} | ||||
|       %{label: gettext("Ammo"), key: :name}, | ||||
|       %{label: gettext("Rounds shot"), key: :count}, | ||||
|       %{label: gettext("Notes"), key: :notes}, | ||||
|       %{label: gettext("Date"), key: :date}, | ||||
|       %{label: nil, key: :actions, sortable: false} | ||||
|     ] | ||||
|  | ||||
|     rows = | ||||
| @@ -101,17 +101,17 @@ defmodule CanneryWeb.RangeLive.Index do | ||||
|     |> Enum.into(%{}, fn %{key: key} -> | ||||
|       value = | ||||
|         case key do | ||||
|           "name" -> | ||||
|           :name -> | ||||
|             {shot_group.ammo_group.ammo_type.name, | ||||
|              live_patch(shot_group.ammo_group.ammo_type.name, | ||||
|                to: Routes.ammo_group_show_path(Endpoint, :show, shot_group.ammo_group), | ||||
|                class: "link" | ||||
|              )} | ||||
|  | ||||
|           "date" -> | ||||
|           :date -> | ||||
|             date |> display_date() | ||||
|  | ||||
|           "actions" -> | ||||
|           :actions -> | ||||
|             ~H""" | ||||
|             <div class="px-4 py-2 space-x-4 flex justify-center items-center"> | ||||
|               <%= live_patch to: Routes.range_index_path(Endpoint, :edit, shot_group), | ||||
| @@ -134,7 +134,7 @@ defmodule CanneryWeb.RangeLive.Index do | ||||
|             """ | ||||
|  | ||||
|           key -> | ||||
|             shot_group |> Map.get(key |> String.to_existing_atom()) | ||||
|             shot_group |> Map.get(key) | ||||
|         end | ||||
|  | ||||
|       {key, value} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user