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
require Logger
import MvWeb.LiveHelpers, only: [current_actor: 1]
alias Mv.Statistics
alias Mv.MembershipFees.MembershipFeeType
@ -171,8 +173,15 @@ defmodule MvWeb.StatisticsLive do
{:noreply, push_patch(socket, to: ~p"/statistics")}
end
def handle_event("change_fee_type", %{"fee_type_id" => id}, socket) do
{:noreply, push_patch(socket, to: ~p"/statistics?fee_type_id=#{id}")}
def handle_event("change_fee_type", %{"fee_type_id" => id}, socket) when is_binary(id) do
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
attr :joins_exits_by_year, :list, required: true
@ -187,11 +196,15 @@ defmodule MvWeb.StatisticsLive do
sum = row.joins + row.exits
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)
joins_pct = row.joins / seg_scale * 100
exits_pct = row.exits / seg_scale * 100
joins_pct = min(100.0, row.joins / seg_scale * 100)
exits_pct = min(100.0, row.exits / seg_scale * 100)
%{
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)
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 =
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 =
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,
@ -458,7 +483,8 @@ defmodule MvWeb.StatisticsLive do
defp bar_pct(value, max) do
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
attr :cycle_totals, :map, required: true
@ -512,12 +538,19 @@ defmodule MvWeb.StatisticsLive do
defp load_fee_types(socket) do
actor = current_actor(socket)
fee_types =
MembershipFeeType
case MembershipFeeType
|> Ash.Query.sort(name: :asc)
|> Ash.read!(domain: Mv.MembershipFees, actor: actor)
|> Ash.read(domain: Mv.MembershipFees, actor: actor) do
{:ok, 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
defp load_statistics(socket) do