prop/lib/microwaveprop_web/live/qso_live/index.ex

112 lines
3.6 KiB
Elixir

defmodule MicrowavepropWeb.QsoLive.Index do
@moduledoc false
use MicrowavepropWeb, :live_view
alias Microwaveprop.Radio
@sortable_fields ~w(station1 station2 band mode distance_km qso_timestamp)
@default_sort_by "qso_timestamp"
@default_sort_order "desc"
@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end
@impl true
def handle_params(params, _uri, socket) do
page = params |> Map.get("page", "1") |> String.to_integer() |> max(1)
sort_by = validate_sort_field(Map.get(params, "sort_by", @default_sort_by))
sort_order = validate_sort_order(Map.get(params, "sort_order", @default_sort_order))
result =
Radio.list_qsos(
page: page,
sort_by: String.to_existing_atom(sort_by),
sort_order: String.to_existing_atom(sort_order)
)
{:noreply,
assign(socket,
page_title: "QSOs",
page: result.page,
total_pages: result.total_pages,
total_entries: result.total_entries,
qsos: result.entries,
sort_by: sort_by,
sort_order: sort_order
)}
end
@impl true
def handle_event("sort", %{"field" => field}, socket) do
field = validate_sort_field(field)
new_order =
if socket.assigns.sort_by == field && socket.assigns.sort_order == "asc",
do: "desc",
else: "asc"
{:noreply, push_patch(socket, to: ~p"/qsos?sort_by=#{field}&sort_order=#{new_order}")}
end
defp validate_sort_field(field) when field in @sortable_fields, do: field
defp validate_sort_field(_), do: @default_sort_by
defp validate_sort_order(order) when order in ~w(asc desc), do: order
defp validate_sort_order(_), do: @default_sort_order
@impl true
def render(assigns) do
~H"""
<Layouts.app flash={@flash}>
<.header>
QSOs
<:subtitle>{@total_entries} contacts</:subtitle>
</.header>
<.table
id="qsos"
rows={@qsos}
row_id={fn qso -> "qso-#{qso.id}" end}
row_click={fn qso -> JS.navigate(~p"/qsos/#{qso.id}") end}
sort_by={@sort_by}
sort_order={@sort_order}
>
<:col :let={qso} label="Station 1" sort_field="station1">{qso.station1}</:col>
<:col :let={qso} label="Grid 1">{qso.grid1 || "—"}</:col>
<:col :let={qso} label="Station 2" sort_field="station2">{qso.station2}</:col>
<:col :let={qso} label="Grid 2">{qso.grid2 || "—"}</:col>
<:col :let={qso} label="Band" sort_field="band">{qso.band}</:col>
<:col :let={qso} label="Mode" sort_field="mode">{qso.mode}</:col>
<:col :let={qso} label="Distance (km)" sort_field="distance_km">{qso.distance_km}</:col>
<:col :let={qso} label="Timestamp" sort_field="qso_timestamp">
{Calendar.strftime(qso.qso_timestamp, "%Y-%m-%d %H:%M")}
</:col>
</.table>
<div class="flex items-center justify-between pt-4">
<.link
:if={@page > 1}
patch={~p"/qsos?page=#{@page - 1}&sort_by=#{@sort_by}&sort_order=#{@sort_order}"}
class="btn btn-sm btn-outline"
>
<.icon name="hero-chevron-left" class="w-4 h-4" /> Previous
</.link>
<span :if={@page <= 1} />
<span class="text-sm text-base-content/70">Page {@page} of {@total_pages}</span>
<.link
:if={@page < @total_pages}
patch={~p"/qsos?page=#{@page + 1}&sort_by=#{@sort_by}&sort_order=#{@sort_order}"}
class="btn btn-sm btn-outline"
>
Next <.icon name="hero-chevron-right" class="w-4 h-4" />
</.link>
<span :if={@page >= @total_pages} />
</div>
</Layouts.app>
"""
end
end