Statistics LiveView: robust URL, load_fee_types error handling, clamp percents

This commit is contained in:
Moritz 2026-02-12 18:44:45 +01:00 committed by moritz
parent b416944321
commit 4b61289f33

View file

@ -6,6 +6,8 @@ defmodule MvWeb.StatisticsLive do
""" """
use MvWeb, :live_view use MvWeb, :live_view
require Logger
import MvWeb.LiveHelpers, only: [current_actor: 1] import MvWeb.LiveHelpers, only: [current_actor: 1]
alias Mv.Statistics alias Mv.Statistics
alias Mv.MembershipFees.MembershipFeeType alias Mv.MembershipFees.MembershipFeeType
@ -171,8 +173,15 @@ defmodule MvWeb.StatisticsLive do
{:noreply, push_patch(socket, to: ~p"/statistics")} {:noreply, push_patch(socket, to: ~p"/statistics")}
end end
def handle_event("change_fee_type", %{"fee_type_id" => id}, socket) do def handle_event("change_fee_type", %{"fee_type_id" => id}, socket) when is_binary(id) do
{:noreply, push_patch(socket, to: ~p"/statistics?fee_type_id=#{id}")} trimmed = String.trim(id)
to =
if trimmed == "",
do: ~p"/statistics",
else: ~p"/statistics" <> "?" <> URI.encode_query(%{"fee_type_id" => trimmed})
{:noreply, push_patch(socket, to: to)}
end end
attr :joins_exits_by_year, :list, required: true attr :joins_exits_by_year, :list, required: true
@ -187,11 +196,15 @@ defmodule MvWeb.StatisticsLive do
sum = row.joins + row.exits sum = row.joins + row.exits
bar_pct = bar_pct =
if max_total > 0 and sum > 0, do: Float.round(sum / max_total * 100, 1), else: 0 if max_total > 0 and sum > 0 do
min(100.0, Float.round(sum / max_total * 100, 1))
else
0
end
seg_scale = max(sum, 1) seg_scale = max(sum, 1)
joins_pct = row.joins / seg_scale * 100 joins_pct = min(100.0, row.joins / seg_scale * 100)
exits_pct = row.exits / seg_scale * 100 exits_pct = min(100.0, row.exits / seg_scale * 100)
%{ %{
year: row.year, year: row.year,
@ -323,13 +336,25 @@ defmodule MvWeb.StatisticsLive do
if Decimal.compare(sum_positive, 0) == :gt, do: sum_positive, else: Decimal.new(1) if Decimal.compare(sum_positive, 0) == :gt, do: sum_positive, else: Decimal.new(1)
paid_pct = paid_pct =
row.paid |> Decimal.div(seg_scale) |> Decimal.mult(100) |> Decimal.to_float() row.paid
|> Decimal.div(seg_scale)
|> Decimal.mult(100)
|> Decimal.to_float()
|> min(100.0)
unpaid_pct = unpaid_pct =
row.unpaid |> Decimal.div(seg_scale) |> Decimal.mult(100) |> Decimal.to_float() row.unpaid
|> Decimal.div(seg_scale)
|> Decimal.mult(100)
|> Decimal.to_float()
|> min(100.0)
suspended_pct = suspended_pct =
row.suspended |> Decimal.div(seg_scale) |> Decimal.mult(100) |> Decimal.to_float() row.suspended
|> Decimal.div(seg_scale)
|> Decimal.mult(100)
|> Decimal.to_float()
|> min(100.0)
%{ %{
year: row.year, year: row.year,
@ -458,7 +483,8 @@ defmodule MvWeb.StatisticsLive do
defp bar_pct(value, max) do defp bar_pct(value, max) do
scale = if Decimal.compare(max, 0) == :gt, do: max, else: Decimal.new(1) scale = if Decimal.compare(max, 0) == :gt, do: max, else: Decimal.new(1)
value |> Decimal.div(scale) |> Decimal.mult(100) |> Decimal.to_float() pct = value |> Decimal.div(scale) |> Decimal.mult(100) |> Decimal.to_float()
min(100.0, pct)
end end
attr :cycle_totals, :map, required: true attr :cycle_totals, :map, required: true
@ -512,12 +538,19 @@ defmodule MvWeb.StatisticsLive do
defp load_fee_types(socket) do defp load_fee_types(socket) do
actor = current_actor(socket) actor = current_actor(socket)
fee_types = case MembershipFeeType
MembershipFeeType |> Ash.Query.sort(name: :asc)
|> Ash.Query.sort(name: :asc) |> Ash.read(domain: Mv.MembershipFees, actor: actor) do
|> Ash.read!(domain: Mv.MembershipFees, actor: actor) {:ok, fee_types} ->
assign(socket, :membership_fee_types, fee_types)
assign(socket, :membership_fee_types, fee_types) {:error, reason} ->
Logger.warning("StatisticsLive: failed to load fee types: #{inspect(reason)}")
socket
|> put_flash(:error, gettext("Fee types could not be loaded."))
|> assign(:membership_fee_types, [])
end
end end
defp load_statistics(socket) do defp load_statistics(socket) do