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 use MvWeb, :live_view
import Ash.Query import Ash.Query
alias MvWeb.Helpers.MembershipFeeHelpers
@impl true @impl true
def render(assigns) do def render(assigns) do
~H""" ~H"""
@ -162,25 +164,37 @@ defmodule MvWeb.MemberLive.Show do
<% end %> <% end %>
</div> </div>
<%!-- Payment Data Section (Mockup) --%> <%!-- Payment Data Section --%>
<div class="max-w-xl"> <div class="max-w-xl">
<.section_box title={gettext("Payment Data")}> <.section_box title={gettext("Payment Data")}>
<div role="alert" class="alert alert-info mb-4"> <%= if @member.membership_fee_type do %>
<.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"> <div class="flex gap-6">
<.data_field label={gettext("Contribution")} value="72 €" class="w-24" /> <.data_field
<.data_field label={gettext("Payment Cycle")} value={gettext("monthly")} class="w-28" /> label={gettext("Membership Fee")}
<.data_field label={gettext("Paid")} class="w-24"> value={MembershipFeeHelpers.format_currency(@member.membership_fee_type.amount)}
<%= if @member.paid do %> class="w-24"
<span class="badge badge-success">{gettext("Paid")}</span> />
<.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 %> <% else %>
<span class="badge badge-warning">{gettext("Pending")}</span> <span class="badge badge-ghost">{gettext("No cycles")}</span>
<% end %> <% end %>
</.data_field> </.data_field>
</div> </div>
<% else %>
<div class="text-base-content/70 italic">
{gettext("No membership fee type assigned")}
</div>
<% end %>
</.section_box> </.section_box>
</div> </div>
<% end %> <% end %>
@ -216,6 +230,10 @@ defmodule MvWeb.MemberLive.Show do
member = Ash.read_one!(query) 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, {:noreply,
socket socket
|> assign(:page_title, page_title(socket.assigns.live_action)) |> 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(""), do: ""
defp display_value(value), do: value 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 defp format_address(member) do
street_part = street_part =
[member.street, member.house_number] [member.street, member.house_number]