cannery/lib/cannery_web/components/shot_record_table_component.ex

124 lines
3.2 KiB
Elixir
Raw Normal View History

2023-03-30 20:43:30 -04:00
defmodule CanneryWeb.Components.ShotRecordTableComponent do
2022-12-03 21:40:05 -05:00
@moduledoc """
2023-03-30 20:43:30 -04:00
A component that displays a list of shot records
2022-12-03 21:40:05 -05:00
"""
use CanneryWeb, :live_component
2023-03-30 20:43:30 -04:00
alias Cannery.{Accounts.User, ActivityLog.ShotRecord, Ammo, ComparableDate}
2022-12-03 21:40:05 -05:00
alias Ecto.UUID
alias Phoenix.LiveView.{Rendered, Socket}
@impl true
@spec update(
%{
required(:id) => UUID.t(),
required(:current_user) => User.t(),
2023-03-30 20:43:30 -04:00
optional(:shot_records) => [ShotRecord.t()],
2022-12-03 21:40:05 -05:00
optional(:actions) => Rendered.t(),
optional(any()) => any()
},
Socket.t()
) :: {:ok, Socket.t()}
2023-03-30 20:43:30 -04:00
def update(
%{id: _id, shot_records: _shot_records, current_user: _current_user} = assigns,
socket
) do
2022-12-03 21:40:05 -05:00
socket =
socket
|> assign(assigns)
|> assign_new(:actions, fn -> [] end)
2023-03-30 20:43:30 -04:00
|> display_shot_records()
2022-12-03 21:40:05 -05:00
{:ok, socket}
end
2023-03-30 20:43:30 -04:00
defp display_shot_records(
2022-12-03 21:40:05 -05:00
%{
assigns: %{
2023-03-30 20:43:30 -04:00
shot_records: shot_records,
2022-12-03 21:40:05 -05:00
current_user: current_user,
actions: actions
}
} = socket
) do
columns = [
%{label: gettext("Ammo"), key: :name},
%{label: gettext("Rounds shot"), key: :count},
%{label: gettext("Notes"), key: :notes},
2023-03-19 11:19:55 -04:00
%{label: gettext("Date"), key: :date, type: ComparableDate},
2023-03-19 12:35:26 -04:00
%{label: gettext("Actions"), key: :actions, sortable: false}
2022-12-03 21:40:05 -05:00
]
2023-03-29 22:54:55 -04:00
packs =
2023-03-30 20:43:30 -04:00
shot_records
2023-03-29 22:54:55 -04:00
|> Enum.map(fn %{pack_id: pack_id} -> pack_id end)
|> Ammo.get_packs(current_user)
2023-03-29 22:54:55 -04:00
extra_data = %{current_user: current_user, actions: actions, packs: packs}
2022-12-03 21:40:05 -05:00
rows =
2023-03-30 20:43:30 -04:00
shot_records
|> Enum.map(fn shot_record ->
shot_record |> get_row_data_for_shot_record(columns, extra_data)
2022-12-03 21:40:05 -05:00
end)
socket
|> assign(
columns: columns,
rows: rows
)
end
@impl true
def render(assigns) do
~H"""
<div id={@id} class="w-full">
<.live_component
module={CanneryWeb.Components.TableComponent}
2023-05-12 21:50:23 -04:00
id={"shot-record-table-#{@id}"}
2022-12-03 21:40:05 -05:00
columns={@columns}
rows={@rows}
initial_key={:date}
initial_sort_mode={:desc}
/>
</div>
"""
end
2023-03-30 20:43:30 -04:00
@spec get_row_data_for_shot_record(ShotRecord.t(), columns :: [map()], extra_data :: map()) ::
2022-12-03 21:40:05 -05:00
map()
2023-03-30 20:43:30 -04:00
defp get_row_data_for_shot_record(shot_record, columns, extra_data) do
2022-12-03 21:40:05 -05:00
columns
|> Map.new(fn %{key: key} ->
2023-03-30 20:43:30 -04:00
{key, get_row_value(key, shot_record, extra_data)}
2022-12-03 21:40:05 -05:00
end)
end
2023-03-29 22:54:55 -04:00
defp get_row_value(:name, %{pack_id: pack_id}, %{packs: packs}) do
assigns = %{pack: pack = Map.fetch!(packs, pack_id)}
2022-12-03 21:40:05 -05:00
2023-03-30 21:53:52 -04:00
{pack.type.name,
~H"""
2023-04-14 23:34:11 -04:00
<.link navigate={~p"/ammo/show/#{@pack}"} class="link">
2023-03-30 21:53:52 -04:00
<%= @pack.type.name %>
</.link>
"""}
2022-12-03 21:40:05 -05:00
end
defp get_row_value(:date, %{date: date} = assigns, _extra_data) do
{date,
~H"""
<.date id={"#{@id}-date"} date={@date} />
"""}
2023-01-26 00:39:16 -05:00
end
2022-12-03 21:40:05 -05:00
2023-03-30 20:43:30 -04:00
defp get_row_value(:actions, shot_record, %{actions: actions}) do
assigns = %{actions: actions, shot_record: shot_record}
2022-12-03 21:40:05 -05:00
~H"""
2023-03-30 20:43:30 -04:00
<%= render_slot(@actions, @shot_record) %>
2022-12-03 21:40:05 -05:00
"""
end
2023-03-30 20:43:30 -04:00
defp get_row_value(key, shot_record, _extra_data), do: shot_record |> Map.get(key)
2022-12-03 21:40:05 -05:00
end