All checks were successful
continuous-integration/drone/push Build is passing
Complete refactoring of resources, database tables, code references, tests, and documentation for improved naming consistency.
118 lines
3.9 KiB
Elixir
118 lines
3.9 KiB
Elixir
defmodule MvWeb.MemberLive.Show do
|
|
@moduledoc """
|
|
LiveView for displaying a single member's details.
|
|
|
|
## Features
|
|
- Display all member information (personal, contact, address)
|
|
- Show linked user account (if exists)
|
|
- Display custom field values
|
|
- Navigate to edit form
|
|
- Return to member list
|
|
|
|
## Displayed Information
|
|
- Basic: name, email, dates (birth, join, exit)
|
|
- Contact: phone number
|
|
- Address: street, house number, postal code, city
|
|
- Status: paid flag
|
|
- Relationships: linked user account
|
|
- Custom: dynamic custom field values from CustomFields
|
|
|
|
## Navigation
|
|
- Back to member list
|
|
- Edit member (with return_to parameter for back navigation)
|
|
"""
|
|
use MvWeb, :live_view
|
|
import Ash.Query
|
|
|
|
@impl true
|
|
def render(assigns) do
|
|
~H"""
|
|
<Layouts.app flash={@flash} current_user={@current_user}>
|
|
<.header>
|
|
{@member.first_name} {@member.last_name}
|
|
<:subtitle>{gettext("This is a member record from your database.")}</:subtitle>
|
|
|
|
<:actions>
|
|
<.button navigate={~p"/members"} aria-label={gettext("Back to members list")}>
|
|
<.icon name="hero-arrow-left" />
|
|
<span class="sr-only">{gettext("Back to members list")}</span>
|
|
</.button>
|
|
<.button variant="primary" navigate={~p"/members/#{@member}/edit?return_to=show"}>
|
|
<.icon name="hero-pencil-square" /> {gettext("Edit Member")}
|
|
</.button>
|
|
</:actions>
|
|
</.header>
|
|
|
|
<.list>
|
|
<:item title={gettext("Id")}>{@member.id}</:item>
|
|
<:item title={gettext("First Name")}>{@member.first_name}</:item>
|
|
<:item title={gettext("Last Name")}>{@member.last_name}</:item>
|
|
<:item title={gettext("Email")}>{@member.email}</:item>
|
|
<:item title={gettext("Birth Date")}>{@member.birth_date}</:item>
|
|
<:item title={gettext("Paid")}>
|
|
{if @member.paid, do: gettext("Yes"), else: gettext("No")}
|
|
</:item>
|
|
<:item title={gettext("Phone Number")}>{@member.phone_number}</:item>
|
|
<:item title={gettext("Join Date")}>{@member.join_date}</:item>
|
|
<:item title={gettext("Exit Date")}>{@member.exit_date}</:item>
|
|
<:item title={gettext("Notes")}>{@member.notes}</:item>
|
|
<:item title={gettext("City")}>{@member.city}</:item>
|
|
<:item title={gettext("Street")}>{@member.street}</:item>
|
|
<:item title={gettext("House Number")}>{@member.house_number}</:item>
|
|
<:item title={gettext("Postal Code")}>{@member.postal_code}</:item>
|
|
<:item title={gettext("Linked User")}>
|
|
<%= if @member.user do %>
|
|
<.link
|
|
navigate={~p"/users/#{@member.user}"}
|
|
class="text-blue-600 hover:text-blue-800 underline"
|
|
>
|
|
<.icon name="hero-user" class="h-4 w-4 inline mr-1" />
|
|
{@member.user.email}
|
|
</.link>
|
|
<% else %>
|
|
<span class="text-gray-500 italic">{gettext("No user linked")}</span>
|
|
<% end %>
|
|
</:item>
|
|
</.list>
|
|
|
|
<h3 class="mt-8 mb-2 text-lg font-semibold">{gettext("Custom Field Values")}</h3>
|
|
<.generic_list items={
|
|
Enum.map(@member.custom_field_values, fn cfv ->
|
|
{
|
|
# name
|
|
cfv.custom_field && cfv.custom_field.name,
|
|
# value
|
|
case cfv.value do
|
|
%{value: v} -> v
|
|
v -> v
|
|
end
|
|
}
|
|
end)
|
|
} />
|
|
</Layouts.app>
|
|
"""
|
|
end
|
|
|
|
@impl true
|
|
def mount(_params, _session, socket) do
|
|
{:ok, socket}
|
|
end
|
|
|
|
@impl true
|
|
def handle_params(%{"id" => id}, _, socket) do
|
|
query =
|
|
Mv.Membership.Member
|
|
|> filter(id == ^id)
|
|
|> load([:user, custom_field_values: [:custom_field]])
|
|
|
|
member = Ash.read_one!(query)
|
|
|
|
{:noreply,
|
|
socket
|
|
|> assign(:page_title, page_title(socket.assigns.live_action))
|
|
|> assign(:member, member)}
|
|
end
|
|
|
|
defp page_title(:show), do: gettext("Show Member")
|
|
defp page_title(:edit), do: gettext("Edit Member")
|
|
end
|