feat: add payment data section with membership fee type info

- Add Payment Data section showing membership fee amount, interval, and last cycle status
- Use real membership fee type data instead of mockup
- Calculate last cycle status from loaded cycles
This commit is contained in:
Moritz 2025-12-16 11:59:36 +01:00
parent ebd590c81c
commit 5460ebdd5a
Signed by: moritz
GPG key ID: 1020A035E5DD0824

View file

@ -21,6 +21,8 @@ defmodule MvWeb.MemberLive.Show do
use MvWeb, :live_view
import Ash.Query
alias MvWeb.Helpers.MembershipFeeHelpers
@impl true
def render(assigns) do
~H"""
@ -162,25 +164,37 @@ defmodule MvWeb.MemberLive.Show do
<% end %>
</div>
<%!-- Payment Data Section (Mockup) --%>
<%!-- Payment Data Section --%>
<div class="max-w-xl">
<.section_box title={gettext("Payment Data")}>
<div role="alert" class="alert alert-info mb-4">
<.icon name="hero-information-circle" class="size-5" />
<span>{gettext("This data is for demonstration purposes only (mockup).")}</span>
</div>
<div class="flex gap-6">
<.data_field label={gettext("Contribution")} value="72 €" class="w-24" />
<.data_field label={gettext("Payment Cycle")} value={gettext("monthly")} class="w-28" />
<.data_field label={gettext("Paid")} class="w-24">
<%= if @member.paid do %>
<span class="badge badge-success">{gettext("Paid")}</span>
<% else %>
<span class="badge badge-warning">{gettext("Pending")}</span>
<% end %>
</.data_field>
</div>
<%= if @member.membership_fee_type do %>
<div class="flex gap-6">
<.data_field
label={gettext("Membership Fee")}
value={MembershipFeeHelpers.format_currency(@member.membership_fee_type.amount)}
class="w-24"
/>
<.data_field
label={gettext("Payment Cycle")}
value={MembershipFeeHelpers.format_interval(@member.membership_fee_type.interval)}
class="w-28"
/>
<.data_field label={gettext("Status")} class="w-24">
<%= if @member.last_cycle_status do %>
<% status = @member.last_cycle_status %>
<span class={["badge", MembershipFeeHelpers.status_color(status)]}>
{format_status_label(status)}
</span>
<% else %>
<span class="badge badge-ghost">{gettext("No cycles")}</span>
<% end %>
</.data_field>
</div>
<% else %>
<div class="text-base-content/70 italic">
{gettext("No membership fee type assigned")}
</div>
<% end %>
</.section_box>
</div>
<% end %>
@ -216,6 +230,10 @@ defmodule MvWeb.MemberLive.Show do
member = Ash.read_one!(query)
# Calculate last cycle status from loaded cycles
last_cycle_status = get_last_cycle_status(member)
member = Map.put(member, :last_cycle_status, last_cycle_status)
{:noreply,
socket
|> assign(:page_title, page_title(socket.assigns.live_action))
@ -282,6 +300,18 @@ defmodule MvWeb.MemberLive.Show do
defp display_value(""), do: ""
defp display_value(value), do: value
defp format_status_label(:paid), do: gettext("Paid")
defp format_status_label(:unpaid), do: gettext("Unpaid")
defp format_status_label(:suspended), do: gettext("Suspended")
defp format_status_label(nil), do: gettext("No status")
defp get_last_cycle_status(member) do
case MembershipFeeHelpers.get_last_completed_cycle(member) do
nil -> nil
cycle -> cycle.status
end
end
defp format_address(member) do
street_part =
[member.street, member.house_number]