diff --git a/docs/documentation-sync-todos.md b/docs/documentation-sync-todos.md
deleted file mode 100644
index e4fb5a8..0000000
--- a/docs/documentation-sync-todos.md
+++ /dev/null
@@ -1,116 +0,0 @@
-# Documentation Sync - Code Adjustments Todo List
-
-**Created:** 2026-01-13
-**Purpose:** List of all code adjustments identified based on documentation synchronization
-
-
-## Code Adjustments (Priority: Low)
-
-### 1. Domain Public API Documentation Incomplete
-
-**Problem:** The `@moduledoc` in domain modules does not list all public functions.
-
-**Affected Files:**
-- `lib/membership/membership.ex` - Missing functions in Public API:
- - `list_required_custom_fields/0`
- - `update_member_field_visibility/2`
- - `update_single_member_field_visibility/3`
-- `lib/accounts/accounts.ex` - Very short Public API documentation, could be more detailed
-- `lib/membership_fees/membership_fees.ex` - Public API is complete, but could more clearly document that LiveViews use direct Ash calls
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Update Public API sections in all domain modules to list all public functions.
-
-### 2. Outdated Comments in MemberLive.Form
-
-**Problem:** `@moduledoc` in `lib/mv_web/live/member_live/form.ex` still mentions "Payment Data: Mockup section (not editable)", but Membership Fees are now fully implemented.
-
-**Affected File:**
-- `lib/mv_web/live/member_live/form.ex` (Line 16)
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Update `@moduledoc` to reflect the current status.
-
-### 3. Mv.Accounts Domain Public API Missing Completely
-
-**Problem:** The `@moduledoc` in `lib/accounts/accounts.ex` does not mention any Public API functions, although several are defined.
-
-**Affected File:**
-- `lib/accounts/accounts.ex` - Missing Public API documentation for:
- - `create_user/1`
- - `list_users/0`
- - `update_user/2`
- - `destroy_user/1`
- - `create_register_with_rauthy/1`
- - `read_sign_in_with_rauthy/1`
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Add Public API section to `@moduledoc`, similar to other domain modules.
-
-### 4. Mv.Authorization Domain Public API Missing get_role/1
-
-**Problem:** The `@moduledoc` in `lib/mv/authorization/authorization.ex` does not list `get_role/1` in the Public API, although it is defined.
-
-**Affected File:**
-- `lib/mv/authorization/authorization.ex` - Missing function in Public API:
- - `get_role/1` (is defined, but not mentioned in Public API)
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Add `get_role/1` to the Public API list.
-
-### 5. Remove Deprecated Implementations
-
-**Problem:** `lib/mv_web/live/custom_field_value_live/show.ex` `MvWeb.ContributionTypeLive.Index` and `MvWeb.ContributionPeriodLive.Show` are deprecated, they should be removed.
-
-### 6. Missing Tests for Some LiveViews
-
-**Problem:** Some LiveViews do not have corresponding test files.
-
-**Affected LiveViews:**
-- `MvWeb.UserLive.Show` - No test present
-- `MvWeb.RoleLive.Show` - No test present
-
-**Priority:** Medium (Test coverage could be improved)
-
-**Recommendation:** Add tests for the three Show LiveViews to ensure complete test coverage.
-
-### 7. Mv.Accounts.Token @moduledoc Too Short
-
-**Problem:** The `@moduledoc` in `lib/accounts/token.ex` is very short and not informative.
-
-**Affected File:**
-- `lib/accounts/token.ex` - Currently only: "AshAuthentication specific ressource"
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Expand @moduledoc to explain that this is an AshAuthentication Token Resource and is used for session management.
-
-### 8. PageController Missing @moduledoc
-
-**Problem:** The `@moduledoc` in `lib/mv_web/controllers/page_controller.ex` is completely missing.
-
-**Affected File:**
-- `lib/mv_web/controllers/page_controller.ex` - No @moduledoc present
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Add @moduledoc to explain that this controller renders the homepage.
-
-**Note:** Other controller modules (Router, Endpoint, Telemetry) also do not have @moduledoc, but this is common and acceptable for standard Phoenix modules.
-
-## Analysis Summary
-
-### Found Inconsistencies
-
-**1. Domain Public API Documentation Incomplete** (see Code Adjustments #1)
-**2. Outdated Comments in MemberLive.Form** (see Code Adjustments #2)
-**3. Mv.Accounts Domain Public API Missing Completely** (see Code Adjustments #3)
-**4. Mv.Authorization Domain Public API Missing get_role/1** (see Code Adjustments #4)
-**5. CustomFieldValueLive.Show is Deprecated** (see Code Adjustments #5)
-**6. Missing Tests for Some LiveViews** (see Code Adjustments #6)
-**7. Mv.Accounts.Token @moduledoc Too Short** (see Code Adjustments #7)
-**8. PageController Missing @moduledoc** (see Code Adjustments #8)
diff --git a/lib/accounts/accounts.ex b/lib/accounts/accounts.ex
index 7bc5073..13218e0 100644
--- a/lib/accounts/accounts.ex
+++ b/lib/accounts/accounts.ex
@@ -1,6 +1,15 @@
defmodule Mv.Accounts do
@moduledoc """
AshAuthentication specific domain to handle Authentication for users.
+
+ ## Resources
+ - `User` - User accounts with authentication methods (password, OIDC)
+ - `Token` - Session tokens for authentication
+
+ ## Public API
+ The domain exposes these main actions:
+ - User CRUD: `create_user/1`, `list_users/0`, `update_user/2`, `destroy_user/1`
+ - Authentication: `create_register_with_rauthy/1`, `read_sign_in_with_rauthy/1`
"""
use Ash.Domain,
extensions: [AshAdmin.Domain, AshPhoenix]
diff --git a/lib/accounts/token.ex b/lib/accounts/token.ex
index ab9c3a7..e76d8f1 100644
--- a/lib/accounts/token.ex
+++ b/lib/accounts/token.ex
@@ -1,6 +1,10 @@
defmodule Mv.Accounts.Token do
@moduledoc """
- AshAuthentication specific ressource
+ AshAuthentication Token Resource for session management.
+
+ This resource is used by AshAuthentication to manage authentication tokens
+ for user sessions. Tokens are automatically created and managed by the
+ authentication system.
"""
use Ash.Resource,
data_layer: AshPostgres.DataLayer,
diff --git a/lib/membership/membership.ex b/lib/membership/membership.ex
index 982b837..97ac4be 100644
--- a/lib/membership/membership.ex
+++ b/lib/membership/membership.ex
@@ -12,8 +12,8 @@ defmodule Mv.Membership do
The domain exposes these main actions:
- Member CRUD: `create_member/1`, `list_members/0`, `update_member/2`, `destroy_member/1`
- Custom field value management: `create_custom_field_value/1`, `list_custom_field_values/0`, etc.
- - Custom field management: `create_custom_field/1`, `list_custom_fields/0`, etc.
- - Settings management: `get_settings/0`, `update_settings/2`
+ - Custom field management: `create_custom_field/1`, `list_custom_fields/0`, `list_required_custom_fields/0`, etc.
+ - Settings management: `get_settings/0`, `update_settings/2`, `update_member_field_visibility/2`, `update_single_member_field_visibility/3`
## Admin Interface
The domain is configured with AshAdmin for management UI.
diff --git a/lib/membership_fees/membership_fees.ex b/lib/membership_fees/membership_fees.ex
index 114f34c..37b4bc9 100644
--- a/lib/membership_fees/membership_fees.ex
+++ b/lib/membership_fees/membership_fees.ex
@@ -11,6 +11,8 @@ defmodule Mv.MembershipFees do
- MembershipFeeType CRUD: `create_membership_fee_type/1`, `list_membership_fee_types/0`, `update_membership_fee_type/2`, `destroy_membership_fee_type/1`
- MembershipFeeCycle CRUD: `create_membership_fee_cycle/1`, `list_membership_fee_cycles/0`, `update_membership_fee_cycle/2`, `destroy_membership_fee_cycle/1`
+ Note: LiveViews may use direct Ash calls instead of these domain functions for performance or flexibility.
+
## Overview
This domain handles the complete membership fee lifecycle including:
- Fee type definitions (monthly, quarterly, half-yearly, yearly)
diff --git a/lib/mv/authorization/authorization.ex b/lib/mv/authorization/authorization.ex
index aac07a9..57942d1 100644
--- a/lib/mv/authorization/authorization.ex
+++ b/lib/mv/authorization/authorization.ex
@@ -7,7 +7,7 @@ defmodule Mv.Authorization do
## Public API
The domain exposes these main actions:
- - Role CRUD: `create_role/1`, `list_roles/0`, `update_role/2`, `destroy_role/1`
+ - Role CRUD: `create_role/1`, `list_roles/0`, `get_role/1`, `update_role/2`, `destroy_role/1`
## Admin Interface
The domain is configured with AshAdmin for management UI.
diff --git a/lib/mv/membership/import/member_csv.ex b/lib/mv/membership/import/member_csv.ex
index 60cfadf..d56c56e 100644
--- a/lib/mv/membership/import/member_csv.ex
+++ b/lib/mv/membership/import/member_csv.ex
@@ -302,30 +302,25 @@ defmodule Mv.Membership.Import.MemberCSV do
max_errors = Keyword.get(opts, :max_errors, 50)
{inserted, failed, errors, _collected_error_count, truncated?} =
- Enum.reduce(chunk_rows_with_lines, {0, 0, [], 0, false}, fn {line_number, row_map},
- {acc_inserted, acc_failed, acc_errors, acc_error_count, acc_truncated?} ->
- current_error_count = existing_error_count + acc_error_count
+ Enum.reduce(chunk_rows_with_lines, {0, 0, [], 0, false}, fn {line_number, row_map}, acc ->
+ current_error_count = existing_error_count + elem(acc, 3)
case process_row(row_map, line_number, custom_field_lookup) do
{:ok, _member} ->
- {acc_inserted + 1, acc_failed, acc_errors, acc_error_count, acc_truncated?}
+ update_inserted(acc)
{:error, error} ->
- new_acc_failed = acc_failed + 1
-
- # Only collect errors if under limit
- {new_acc_errors, new_error_count, new_truncated?} =
- if current_error_count < max_errors do
- {[error | acc_errors], acc_error_count + 1, acc_truncated?}
- else
- {acc_errors, acc_error_count, true}
- end
-
- {acc_inserted, new_acc_failed, new_acc_errors, new_error_count, new_truncated?}
+ handle_row_error(acc, error, current_error_count, max_errors)
end
end)
- {:ok, %{inserted: inserted, failed: failed, errors: Enum.reverse(errors), errors_truncated?: truncated?}}
+ {:ok,
+ %{
+ inserted: inserted,
+ failed: failed,
+ errors: Enum.reverse(errors),
+ errors_truncated?: truncated?
+ }}
end
@doc """
@@ -389,11 +384,9 @@ defmodule Mv.Membership.Import.MemberCSV do
# Extracts the first error from a changeset and converts it to a MemberCSV.Error struct
defp extract_changeset_error(changeset, csv_line_number) do
- case Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} ->
- Enum.reduce(opts, msg, fn {key, value}, acc ->
- String.replace(acc, "%{#{key}}", to_string(value))
- end)
- end) do
+ errors = Ecto.Changeset.traverse_errors(changeset, &format_error_message/1)
+
+ case errors do
%{email: [message | _]} ->
# Email-specific error
%Error{
@@ -422,6 +415,56 @@ defmodule Mv.Membership.Import.MemberCSV do
end
end
+ # Helper function to update accumulator when row is successfully inserted
+ defp update_inserted({acc_inserted, acc_failed, acc_errors, acc_error_count, acc_truncated?}) do
+ {acc_inserted + 1, acc_failed, acc_errors, acc_error_count, acc_truncated?}
+ end
+
+ # Helper function to handle row error with error count limit checking
+ defp handle_row_error(
+ {acc_inserted, acc_failed, acc_errors, acc_error_count, acc_truncated?},
+ error,
+ current_error_count,
+ max_errors
+ ) do
+ new_acc_failed = acc_failed + 1
+
+ {new_acc_errors, new_error_count, new_truncated?} =
+ collect_error_if_under_limit(
+ error,
+ acc_errors,
+ acc_error_count,
+ acc_truncated?,
+ current_error_count,
+ max_errors
+ )
+
+ {acc_inserted, new_acc_failed, new_acc_errors, new_error_count, new_truncated?}
+ end
+
+ # Helper function to collect error only if under limit
+ defp collect_error_if_under_limit(
+ error,
+ acc_errors,
+ acc_error_count,
+ acc_truncated?,
+ current_error_count,
+ max_errors
+ ) do
+ if current_error_count < max_errors do
+ {[error | acc_errors], acc_error_count + 1, acc_truncated?}
+ else
+ {acc_errors, acc_error_count, true}
+ end
+ end
+
+ # Formats error message by replacing placeholders
+ defp format_error_message({msg, opts}) do
+ Enum.reduce(opts, msg, fn {key, value}, acc ->
+ String.replace(acc, "%{#{key}}", to_string(value))
+ end)
+ end
+
# Maps changeset error messages to appropriate Gettext messages
defp gettext_error_message(message) when is_binary(message) do
cond do
diff --git a/lib/mv_web/controllers/page_controller.ex b/lib/mv_web/controllers/page_controller.ex
index 6e1bc92..8cd38a6 100644
--- a/lib/mv_web/controllers/page_controller.ex
+++ b/lib/mv_web/controllers/page_controller.ex
@@ -1,4 +1,10 @@
defmodule MvWeb.PageController do
+ @moduledoc """
+ Controller for rendering the homepage.
+
+ This controller handles the root route and renders the application's
+ homepage view.
+ """
use MvWeb, :controller
def home(conn, _params) do
diff --git a/lib/mv_web/live/contribution_period_live/show.ex b/lib/mv_web/live/contribution_period_live/show.ex
deleted file mode 100644
index b6a2574..0000000
--- a/lib/mv_web/live/contribution_period_live/show.ex
+++ /dev/null
@@ -1,345 +0,0 @@
-defmodule MvWeb.ContributionPeriodLive.Show do
- @moduledoc """
- Mock-up LiveView for Member Contribution Periods (Admin/Treasurer View).
-
- This is a preview-only page that displays the planned UI for viewing
- and managing contribution periods for a specific member.
- It shows static mock data and is not functional.
-
- ## Planned Features (Future Implementation)
- - Display all contribution periods for a member
- - Show period dates, interval, amount, and status
- - Quick status change (paid/unpaid/suspended)
- - Bulk marking of multiple periods
- - Notes per period
-
- ## Note
- This page is intentionally non-functional and serves as a UI mockup
- for the upcoming Membership Contributions feature.
- """
- use MvWeb, :live_view
-
- @impl true
- def mount(_params, _session, socket) do
- {:ok,
- socket
- |> assign(:page_title, gettext("Member Contributions"))
- |> assign(:member, mock_member())
- |> assign(:periods, mock_periods())
- |> assign(:selected_periods, MapSet.new())}
- end
-
- @impl true
- def render(assigns) do
- ~H"""
-
- <.mockup_warning />
-
- <.header>
- {gettext("Contributions for %{name}", name: MvWeb.Helpers.MemberHelpers.display_name(@member))}
- <:subtitle>
- {gettext("Contribution type")}:
- {@member.contribution_type}
- · {gettext("Member since")}: {@member.joined_at}
-
- <:actions>
- <.link navigate={~p"/membership_fee_settings"} class="btn btn-ghost btn-sm">
- <.icon name="hero-arrow-left" class="size-4" />
- {gettext("Back to Settings")}
-
-
-
-
- <%!-- Member Info Card --%>
-
-
-
-
-
{gettext("Email")}
-
{@member.email}
-
-
-
{gettext("Contribution Start")}
-
{@member.contribution_start}
-
-
-
{gettext("Total Contributions")}
-
{length(@periods)}
-
-
-
{gettext("Open Contributions")}
-
- {Enum.count(@periods, &(&1.status == :unpaid))}
-
-
-
-
-
-
- <%!-- Contribution Type Change --%>
-
-
-
- {gettext("Change Contribution Type")}:
-
- {@member.contribution_type} (60,00 €, {gettext("Yearly")})
- {gettext("Reduced")} (30,00 €, {gettext("Yearly")})
- {gettext("Honorary")} (0,00 €, {gettext("Yearly")})
-
-
- <.icon name="hero-question-mark-circle" class="inline size-4" />
- {gettext("Why are not all contribution types shown?")}
-
-
-
-
-
- <%!-- Bulk Actions --%>
-
-
- {ngettext(
- "%{count} period selected",
- "%{count} periods selected",
- MapSet.size(@selected_periods),
- count: MapSet.size(@selected_periods)
- )}
-
-
- <.icon name="hero-check" class="size-4" />
- {gettext("Mark as Paid")}
-
-
- <.icon name="hero-minus-circle" class="size-4" />
- {gettext("Mark as Suspended")}
-
-
- <.icon name="hero-x-circle" class="size-4" />
- {gettext("Mark as Unpaid")}
-
-
-
- <%!-- Periods Table --%>
-
-
- """
- end
-
- # Mock-up warning banner component - subtle orange style
- defp mockup_warning(assigns) do
- ~H"""
-
- <.icon name="hero-exclamation-triangle" class="size-5 shrink-0" />
-
- {gettext("Preview Mockup")}
-
- – {gettext("This page is not functional and only displays the planned features.")}
-
-
-
- """
- end
-
- # Status badge component
- attr :status, :atom, required: true
-
- defp status_badge(%{status: :paid} = assigns) do
- ~H"""
-
- <.icon name="hero-check-circle-mini" class="size-3" />
- {gettext("Paid")}
-
- """
- end
-
- defp status_badge(%{status: :unpaid} = assigns) do
- ~H"""
-
- <.icon name="hero-x-circle-mini" class="size-3" />
- {gettext("Unpaid")}
-
- """
- end
-
- defp status_badge(%{status: :suspended} = assigns) do
- ~H"""
-
- <.icon name="hero-pause-circle-mini" class="size-3" />
- {gettext("Suspended")}
-
- """
- end
-
- defp period_row_class(:unpaid), do: "bg-error/5"
- defp period_row_class(:suspended), do: "bg-base-200/50"
- defp period_row_class(_), do: ""
-
- # Mock member data
- defp mock_member do
- %{
- id: "123",
- first_name: "Maria",
- last_name: "Weber",
- email: "maria.weber@example.de",
- contribution_type: gettext("Regular"),
- joined_at: "15.03.2021",
- contribution_start: "01.01.2021"
- }
- end
-
- # Mock periods data
- defp mock_periods do
- [
- %{
- id: "p1",
- period_start: "01.01.2025",
- period_end: "31.12.2025",
- interval: :yearly,
- amount: Decimal.new("60.00"),
- status: :unpaid,
- notes: nil,
- is_current: true
- },
- %{
- id: "p2",
- period_start: "01.01.2024",
- period_end: "31.12.2024",
- interval: :yearly,
- amount: Decimal.new("60.00"),
- status: :paid,
- notes: gettext("Paid via bank transfer"),
- is_current: false
- },
- %{
- id: "p3",
- period_start: "01.01.2023",
- period_end: "31.12.2023",
- interval: :yearly,
- amount: Decimal.new("50.00"),
- status: :paid,
- notes: nil,
- is_current: false
- },
- %{
- id: "p4",
- period_start: "01.01.2022",
- period_end: "31.12.2022",
- interval: :yearly,
- amount: Decimal.new("50.00"),
- status: :paid,
- notes: nil,
- is_current: false
- },
- %{
- id: "p5",
- period_start: "01.01.2021",
- period_end: "31.12.2021",
- interval: :yearly,
- amount: Decimal.new("50.00"),
- status: :suspended,
- notes: gettext("Joining year - reduced to 0"),
- is_current: false
- }
- ]
- end
-
- defp format_currency(%Decimal{} = amount) do
- "#{Decimal.to_string(amount)} €"
- end
-
- defp format_interval(:monthly), do: gettext("Monthly")
- defp format_interval(:quarterly), do: gettext("Quarterly")
- defp format_interval(:half_yearly), do: gettext("Half-yearly")
- defp format_interval(:yearly), do: gettext("Yearly")
-end
diff --git a/lib/mv_web/live/contribution_type_live/index.ex b/lib/mv_web/live/contribution_type_live/index.ex
deleted file mode 100644
index 3e2f04c..0000000
--- a/lib/mv_web/live/contribution_type_live/index.ex
+++ /dev/null
@@ -1,205 +0,0 @@
-defmodule MvWeb.ContributionTypeLive.Index do
- @moduledoc """
- Mock-up LiveView for Contribution Types Management (Admin).
-
- This is a preview-only page that displays the planned UI for managing
- contribution types. It shows static mock data and is not functional.
-
- ## Planned Features (Future Implementation)
- - List all contribution types
- - Display: Name, Amount, Interval, Member count
- - Create new contribution types
- - Edit existing contribution types (name, amount, description - NOT interval)
- - Delete contribution types (if no members assigned)
-
- ## Note
- This page is intentionally non-functional and serves as a UI mockup
- for the upcoming Membership Contributions feature.
- """
- use MvWeb, :live_view
-
- @impl true
- def mount(_params, _session, socket) do
- {:ok,
- socket
- |> assign(:page_title, gettext("Contribution Types"))
- |> assign(:contribution_types, mock_contribution_types())}
- end
-
- @impl true
- def render(assigns) do
- ~H"""
-
- <.mockup_warning />
-
- <.header>
- {gettext("Contribution Types")}
- <:subtitle>
- {gettext("Manage contribution types for membership fees.")}
-
- <:actions>
-
- <.icon name="hero-plus" /> {gettext("New Contribution Type")}
-
-
-
-
- <.table id="contribution_types" rows={@contribution_types} row_id={fn ct -> "ct-#{ct.id}" end}>
- <:col :let={ct} label={gettext("Name")}>
- {ct.name}
- {ct.description}
-
-
- <:col :let={ct} label={gettext("Amount")}>
- {format_currency(ct.amount)}
-
-
- <:col :let={ct} label={gettext("Interval")}>
- {format_interval(ct.interval)}
-
-
- <:col :let={ct} label={gettext("Members")}>
- {ct.member_count}
-
-
- <:action :let={_ct}>
-
- <.icon name="hero-pencil" class="size-4" />
-
-
-
- <:action :let={ct}>
- 0,
- do: gettext("Cannot delete - members assigned"),
- else: gettext("Delete")
- }
- >
- <.icon name="hero-trash" class="size-4" />
-
-
-
-
- <.info_card />
-
- """
- end
-
- # Mock-up warning banner component - subtle orange style
- defp mockup_warning(assigns) do
- ~H"""
-
- <.icon name="hero-exclamation-triangle" class="size-5 shrink-0" />
-
- {gettext("Preview Mockup")}
-
- – {gettext("This page is not functional and only displays the planned features.")}
-
-
-
- """
- end
-
- # Info card explaining the contribution type concept
- defp info_card(assigns) do
- ~H"""
-
-
-
- <.icon name="hero-information-circle" class="size-5" />
- {gettext("About Contribution Types")}
-
-
-
- {gettext(
- "Contribution types define different membership fee structures. Each type has a fixed cycle (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation."
- )}
-
-
-
- {gettext("Name & Amount")}
- - {gettext("Can be changed at any time. Amount changes affect future periods only.")}
-
-
- {gettext("Interval")}
- - {gettext(
- "Fixed after creation. Members can only switch between types with the same interval."
- )}
-
-
- {gettext("Deletion")}
- - {gettext("Only possible if no members are assigned to this type.")}
-
-
-
-
-
- """
- end
-
- # Mock data for demonstration
- defp mock_contribution_types do
- [
- %{
- id: "1",
- name: gettext("Regular"),
- description: gettext("Standard membership fee for regular members"),
- amount: Decimal.new("60.00"),
- interval: :yearly,
- member_count: 45
- },
- %{
- id: "2",
- name: gettext("Reduced"),
- description: gettext("Reduced fee for unemployed, pensioners, or low income"),
- amount: Decimal.new("30.00"),
- interval: :yearly,
- member_count: 12
- },
- %{
- id: "3",
- name: gettext("Student"),
- description: gettext("Monthly fee for students and trainees"),
- amount: Decimal.new("5.00"),
- interval: :monthly,
- member_count: 8
- },
- %{
- id: "4",
- name: gettext("Family"),
- description: gettext("Quarterly fee for family memberships"),
- amount: Decimal.new("25.00"),
- interval: :quarterly,
- member_count: 15
- },
- %{
- id: "5",
- name: gettext("Supporting Member"),
- description: gettext("Half-yearly contribution for supporting members"),
- amount: Decimal.new("100.00"),
- interval: :half_yearly,
- member_count: 3
- },
- %{
- id: "6",
- name: gettext("Honorary"),
- description: gettext("No fee for honorary members"),
- amount: Decimal.new("0.00"),
- interval: :yearly,
- member_count: 2
- }
- ]
- end
-
- defp format_currency(%Decimal{} = amount) do
- "#{Decimal.to_string(amount)} €"
- end
-
- defp format_interval(:monthly), do: gettext("Monthly")
- defp format_interval(:quarterly), do: gettext("Quarterly")
- defp format_interval(:half_yearly), do: gettext("Half-yearly")
- defp format_interval(:yearly), do: gettext("Yearly")
-end
diff --git a/lib/mv_web/live/custom_field_value_live/form.ex b/lib/mv_web/live/custom_field_value_live/form.ex
deleted file mode 100644
index 599ce1d..0000000
--- a/lib/mv_web/live/custom_field_value_live/form.ex
+++ /dev/null
@@ -1,300 +0,0 @@
-defmodule MvWeb.CustomFieldValueLive.Form do
- @moduledoc """
- LiveView form for creating and editing custom field values.
-
- ## Features
- - Create new custom field values with member and type selection
- - Edit existing custom field values
- - Value input adapts to custom field type (string, integer, boolean, date, email)
- - Real-time validation
-
- ## Form Fields
- **Required:**
- - member - Select which member owns this custom field value
- - custom_field - Select the type (defines value type)
- - value - The actual value (input type depends on custom field type)
-
- ## Value Types
- The form dynamically renders appropriate inputs based on custom field type:
- - String: text input
- - Integer: number input
- - Boolean: checkbox
- - Date: date picker
- - Email: email input with validation
-
- ## Events
- - `validate` - Real-time form validation
- - `save` - Submit form (create or update custom field value)
-
- ## Note
- Custom field values are typically managed through the member edit form,
- not through this standalone form.
- """
- use MvWeb, :live_view
-
- on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded}
- import MvWeb.LiveHelpers, only: [current_actor: 1, submit_form: 3]
-
- @impl true
- def render(assigns) do
- ~H"""
-
- <.header>
- {@page_title}
- <:subtitle>
- {gettext("Use this form to manage Custom Field Value records in your database.")}
-
-
-
- <.form for={@form} id="custom_field_value-form" phx-change="validate" phx-submit="save">
-
- <.input
- field={@form[:custom_field_id]}
- type="select"
- label={gettext("Custom field")}
- options={custom_field_options(@custom_fields)}
- prompt={gettext("Choose a custom field")}
- />
-
-
- <.input
- field={@form[:member_id]}
- type="select"
- label={gettext("Member")}
- options={member_options(@members)}
- prompt={gettext("Choose a member")}
- />
-
-
- <%= if @selected_custom_field do %>
- <.union_value_input form={@form} custom_field={@selected_custom_field} />
- <% else %>
-
- {gettext("Please select a custom field first")}
-
- <% end %>
-
- <.button phx-disable-with={gettext("Saving...")} variant="primary">
- {gettext("Save Custom Field Value")}
-
- <.button navigate={return_path(@return_to, @custom_field_value)}>{gettext("Cancel")}
-
-
- """
- end
-
- # Helper function for Union-Value Input
- defp union_value_input(assigns) do
- # Extract the current value from the CustomFieldValue
- current_value = extract_current_value(assigns.form.data, assigns.custom_field.value_type)
- assigns = assign(assigns, :current_value, current_value)
-
- ~H"""
-
-
- {gettext("Value")}
-
-
- <%= case @custom_field.value_type do %>
- <% :string -> %>
- <.inputs_for :let={value_form} field={@form[:value]}>
- <.input field={value_form[:value]} type="text" label="" value={@current_value} />
-
-
- <% :integer -> %>
- <.inputs_for :let={value_form} field={@form[:value]}>
- <.input field={value_form[:value]} type="number" label="" value={@current_value} />
-
-
- <% :boolean -> %>
- <.inputs_for :let={value_form} field={@form[:value]}>
- <.input field={value_form[:value]} type="checkbox" label="" checked={@current_value} />
-
-
- <% :date -> %>
- <.inputs_for :let={value_form} field={@form[:value]}>
- <.input
- field={value_form[:value]}
- type="date"
- label=""
- value={format_date_value(@current_value)}
- />
-
-
- <% :email -> %>
- <.inputs_for :let={value_form} field={@form[:value]}>
- <.input field={value_form[:value]} type="email" label="" value={@current_value} />
-
-
- <% _ -> %>
-
- {gettext("Unsupported value type: %{type}", type: @custom_field.value_type)}
-
- <% end %>
-
- """
- end
-
- # Helper function to extract the current value from the CustomFieldValue
- defp extract_current_value(
- %Mv.Membership.CustomFieldValue{value: %Ash.Union{value: value}},
- _value_type
- ) do
- value
- end
-
- defp extract_current_value(_data, _value_type) do
- nil
- end
-
- # Helper function to format Date values for HTML input
- defp format_date_value(%Date{} = date) do
- Date.to_iso8601(date)
- end
-
- defp format_date_value(nil), do: ""
-
- defp format_date_value(date) when is_binary(date) do
- case Date.from_iso8601(date) do
- {:ok, parsed_date} -> Date.to_iso8601(parsed_date)
- _ -> ""
- end
- end
-
- defp format_date_value(_), do: ""
-
- @impl true
- def mount(params, _session, socket) do
- custom_field_value =
- case params["id"] do
- nil -> nil
- id -> Ash.get!(Mv.Membership.CustomFieldValue, id) |> Ash.load!([:custom_field])
- end
-
- action = if is_nil(custom_field_value), do: "New", else: "Edit"
- page_title = action <> " " <> "Custom field value"
-
- # Load all CustomFields and Members for the selection fields
- actor = current_actor(socket)
- custom_fields = Ash.read!(Mv.Membership.CustomField, actor: actor)
- members = Ash.read!(Mv.Membership.Member, actor: actor)
-
- {:ok,
- socket
- |> assign(:return_to, return_to(params["return_to"]))
- |> assign(custom_field_value: custom_field_value)
- |> assign(:page_title, page_title)
- |> assign(:custom_fields, custom_fields)
- |> assign(:members, members)
- |> assign(:selected_custom_field, custom_field_value && custom_field_value.custom_field)
- |> assign_form()}
- end
-
- defp return_to("show"), do: "show"
- defp return_to(_), do: "index"
-
- @impl true
- def handle_event("validate", %{"custom_field_value" => custom_field_value_params}, socket) do
- # Find the selected CustomField
- selected_custom_field =
- case custom_field_value_params["custom_field_id"] do
- "" -> nil
- nil -> nil
- id -> Enum.find(socket.assigns.custom_fields, &(&1.id == id))
- end
-
- # Set the Union type based on the selected CustomField
- updated_params =
- if selected_custom_field do
- union_type = to_string(selected_custom_field.value_type)
- put_in(custom_field_value_params, ["value", "_union_type"], union_type)
- else
- custom_field_value_params
- end
-
- {:noreply,
- socket
- |> assign(:selected_custom_field, selected_custom_field)
- |> assign(form: AshPhoenix.Form.validate(socket.assigns.form, updated_params))}
- end
-
- def handle_event("save", %{"custom_field_value" => custom_field_value_params}, socket) do
- # Set the Union type based on the selected CustomField
- updated_params =
- if socket.assigns.selected_custom_field do
- union_type = to_string(socket.assigns.selected_custom_field.value_type)
- put_in(custom_field_value_params, ["value", "_union_type"], union_type)
- else
- custom_field_value_params
- end
-
- actor = current_actor(socket)
-
- case submit_form(socket.assigns.form, updated_params, actor) do
- {:ok, custom_field_value} ->
- notify_parent({:saved, custom_field_value})
-
- action =
- case socket.assigns.form.source.type do
- :create -> gettext("create")
- :update -> gettext("update")
- other -> to_string(other)
- end
-
- socket =
- socket
- |> put_flash(
- :info,
- gettext("Custom field value %{action} successfully", action: action)
- )
- |> push_navigate(to: return_path(socket.assigns.return_to, custom_field_value))
-
- {:noreply, socket}
-
- {:error, form} ->
- {:noreply, assign(socket, form: form)}
- end
- end
-
- defp notify_parent(msg), do: send(self(), {__MODULE__, msg})
-
- defp assign_form(%{assigns: %{custom_field_value: custom_field_value}} = socket) do
- form =
- if custom_field_value do
- # Determine the Union type based on the custom_field
- union_type = custom_field_value.custom_field && custom_field_value.custom_field.value_type
-
- params =
- if union_type do
- %{"value" => %{"_union_type" => to_string(union_type)}}
- else
- %{}
- end
-
- AshPhoenix.Form.for_update(custom_field_value, :update,
- as: "custom_field_value",
- params: params
- )
- else
- AshPhoenix.Form.for_create(Mv.Membership.CustomFieldValue, :create,
- as: "custom_field_value"
- )
- end
-
- assign(socket, form: to_form(form))
- end
-
- defp return_path("index", _custom_field_value), do: ~p"/custom_field_values"
-
- defp return_path("show", custom_field_value),
- do: ~p"/custom_field_values/#{custom_field_value.id}"
-
- # Helper functions for selection options
- defp custom_field_options(custom_fields) do
- Enum.map(custom_fields, &{&1.name, &1.id})
- end
-
- defp member_options(members) do
- Enum.map(members, &{MvWeb.Helpers.MemberHelpers.display_name(&1), &1.id})
- end
-end
diff --git a/lib/mv_web/live/custom_field_value_live/index.ex b/lib/mv_web/live/custom_field_value_live/index.ex
deleted file mode 100644
index eea578e..0000000
--- a/lib/mv_web/live/custom_field_value_live/index.ex
+++ /dev/null
@@ -1,157 +0,0 @@
-defmodule MvWeb.CustomFieldValueLive.Index do
- @moduledoc """
- LiveView for displaying and managing custom field values.
-
- ## Features
- - List all custom field values with their values and types
- - Show which member each custom field value belongs to
- - Display custom field information
- - Navigate to custom field value details and edit forms
- - Delete custom field values
-
- ## Relationships
- Each custom field value is linked to:
- - A member (the custom field value owner)
- - A custom field (defining value type and behavior)
-
- ## Events
- - `delete` - Remove a custom field value from the database
-
- ## Note
- Custom field values are typically managed through the member edit form.
- This view provides a global overview of all custom field values.
- """
- use MvWeb, :live_view
-
- on_mount {MvWeb.LiveHelpers, :ensure_user_role_loaded}
- import MvWeb.LiveHelpers, only: [current_actor: 1]
-
- @impl true
- def render(assigns) do
- ~H"""
-
- <.header>
- Listing Custom field values
- <:actions>
- <.button variant="primary" navigate={~p"/custom_field_values/new"}>
- <.icon name="hero-plus" /> New Custom field value
-
-
-
-
- <.table
- id="custom_field_values"
- rows={@streams.custom_field_values}
- row_click={
- fn {_id, custom_field_value} ->
- JS.navigate(~p"/custom_field_values/#{custom_field_value}")
- end
- }
- >
- <:col :let={{_id, custom_field_value}} label="Id">{custom_field_value.id}
-
- <:action :let={{_id, custom_field_value}}>
-
- <.link navigate={~p"/custom_field_values/#{custom_field_value}"}>Show
-
-
- <.link navigate={~p"/custom_field_values/#{custom_field_value}/edit"}>Edit
-
-
- <:action :let={{id, custom_field_value}}>
- <.link
- phx-click={JS.push("delete", value: %{id: custom_field_value.id}) |> hide("##{id}")}
- data-confirm="Are you sure?"
- >
- Delete
-
-
-
-
- """
- end
-
- @impl true
- def mount(_params, _session, socket) do
- actor = current_actor(socket)
-
- # Early return if no actor (prevents exceptions in unauthenticated tests)
- if is_nil(actor) do
- {:ok,
- socket
- |> assign(:page_title, "Listing Custom field values")
- |> stream(:custom_field_values, [])}
- else
- case Ash.read(Mv.Membership.CustomFieldValue, actor: actor) do
- {:ok, custom_field_values} ->
- {:ok,
- socket
- |> assign(:page_title, "Listing Custom field values")
- |> stream(:custom_field_values, custom_field_values)}
-
- {:error, %Ash.Error.Forbidden{}} ->
- {:ok,
- socket
- |> assign(:page_title, "Listing Custom field values")
- |> stream(:custom_field_values, [])
- |> put_flash(:error, gettext("You do not have permission to view custom field values"))}
-
- {:error, error} ->
- {:ok,
- socket
- |> assign(:page_title, "Listing Custom field values")
- |> stream(:custom_field_values, [])
- |> put_flash(:error, format_error(error))}
- end
- end
- end
-
- @impl true
- def handle_event("delete", %{"id" => id}, socket) do
- actor = MvWeb.LiveHelpers.current_actor(socket)
-
- case Ash.get(Mv.Membership.CustomFieldValue, id, actor: actor) do
- {:ok, custom_field_value} ->
- case Ash.destroy(custom_field_value, actor: actor) do
- :ok ->
- {:noreply,
- socket
- |> stream_delete(:custom_field_values, custom_field_value)
- |> put_flash(:info, gettext("Custom field value deleted successfully"))}
-
- {:error, %Ash.Error.Forbidden{}} ->
- {:noreply,
- put_flash(
- socket,
- :error,
- gettext("You do not have permission to delete this custom field value")
- )}
-
- {:error, error} ->
- {:noreply, put_flash(socket, :error, format_error(error))}
- end
-
- {:error, %Ash.Error.Query.NotFound{}} ->
- {:noreply, put_flash(socket, :error, gettext("Custom field value not found"))}
-
- {:error, %Ash.Error.Forbidden{} = _error} ->
- {:noreply,
- put_flash(
- socket,
- :error,
- gettext("You do not have permission to access this custom field value")
- )}
-
- {:error, error} ->
- {:noreply, put_flash(socket, :error, format_error(error))}
- end
- end
-
- defp format_error(%Ash.Error.Invalid{errors: errors}) do
- Enum.map_join(errors, ", ", fn %{message: message} -> message end)
- end
-
- defp format_error(error) do
- inspect(error)
- end
-end
diff --git a/lib/mv_web/live/custom_field_value_live/show.ex b/lib/mv_web/live/custom_field_value_live/show.ex
deleted file mode 100644
index 7a3f678..0000000
--- a/lib/mv_web/live/custom_field_value_live/show.ex
+++ /dev/null
@@ -1,67 +0,0 @@
-defmodule MvWeb.CustomFieldValueLive.Show do
- @moduledoc """
- LiveView for displaying a single custom field value's details.
-
- ## Features
- - Display custom field value and type
- - Show linked member
- - Show custom field definition
- - Navigate to edit form
- - Return to custom field value list
-
- ## Displayed Information
- - Custom field value (formatted based on type)
- - Custom field name and description
- - Member information (who owns this custom field value)
- - Custom field value metadata (ID, timestamps if added)
-
- ## Navigation
- - Back to custom field value list
- - Edit custom field value
- """
- use MvWeb, :live_view
-
- @impl true
- def render(assigns) do
- ~H"""
-
- <.header>
- Data field value {@custom_field_value.id}
- <:subtitle>This is a custom_field_value record from your database.
-
- <:actions>
- <.button navigate={~p"/custom_field_values"}>
- <.icon name="hero-arrow-left" />
-
- <.button
- variant="primary"
- navigate={~p"/custom_field_values/#{@custom_field_value}/edit?return_to=show"}
- >
- <.icon name="hero-pencil-square" /> Edit Custom field value
-
-
-
-
- <.list>
- <:item title="Id">{@custom_field_value.id}
-
-
- """
- end
-
- @impl true
- def mount(_params, _session, socket) do
- {:ok, socket}
- end
-
- @impl true
- def handle_params(%{"id" => id}, _, socket) do
- {:noreply,
- socket
- |> assign(:page_title, page_title(socket.assigns.live_action))
- |> assign(:custom_field_value, Ash.get!(Mv.Membership.CustomFieldValue, id))}
- end
-
- defp page_title(:show), do: "Show data field value"
- defp page_title(:edit), do: "Edit data field value"
-end
diff --git a/lib/mv_web/live/member_live/form.ex b/lib/mv_web/live/member_live/form.ex
index b319fa1..395198a 100644
--- a/lib/mv_web/live/member_live/form.ex
+++ b/lib/mv_web/live/member_live/form.ex
@@ -13,7 +13,7 @@ defmodule MvWeb.MemberLive.Form do
## Form Sections
- Personal Data: Name, address, contact information, membership dates, notes
- Custom Fields: Dynamic fields in uniform grid layout (displayed sorted by name)
- - Payment Data: Mockup section (not editable)
+ - Membership Fee: Selection of membership fee type with interval validation
## Events
- `validate` - Real-time form validation
@@ -355,55 +355,72 @@ defmodule MvWeb.MemberLive.Form do
# Extracts a user-friendly error message from form errors
defp extract_error_message(form) do
- # Try to extract message from source errors first
source_errors = get_source_errors(form)
- case source_errors do
- [%Ash.Error.Invalid{errors: errors} | _] when is_list(errors) ->
- # Extract first error message
- case List.first(errors) do
- %{message: message} when is_binary(message) ->
- gettext("Validation failed: %{message}", message: message)
+ cond do
+ has_invalid_error?(source_errors) ->
+ extract_invalid_error_message(source_errors)
- %{field: field, message: message} when is_binary(message) ->
- gettext("Validation failed: %{field} %{message}", field: field, message: message)
+ has_other_error?(source_errors) ->
+ extract_other_error_message(source_errors)
- _ ->
- gettext("Validation failed. Please check your input.")
- end
+ has_form_errors?(form) ->
+ gettext("Please correct the errors in the form and try again.")
- [error | _] ->
- # Try to extract message from other error types
- case error do
- %{message: message} when is_binary(message) ->
- message
+ true ->
+ gettext("Failed to save member. Please try again.")
+ end
+ end
- error when is_struct(error) ->
- # Try to use Ash.ErrorKind protocol if available
- try do
- Ash.ErrorKind.message(error)
- rescue
- Protocol.UndefinedError -> gettext("Failed to save member. Please try again.")
- end
+ # Checks if source errors contain an Ash.Error.Invalid
+ defp has_invalid_error?([%Ash.Error.Invalid{errors: errors} | _]) when is_list(errors), do: true
+ defp has_invalid_error?(_), do: false
- _ ->
- gettext("Failed to save member. Please try again.")
- end
+ # Extracts message from Ash.Error.Invalid
+ defp extract_invalid_error_message([%Ash.Error.Invalid{errors: errors} | _]) do
+ case List.first(errors) do
+ %{message: message} when is_binary(message) ->
+ gettext("Validation failed: %{message}", message: message)
+
+ %{field: field, message: message} when is_binary(message) ->
+ gettext("Validation failed: %{field} %{message}", field: field, message: message)
_ ->
- # Check if there are any field errors in the form
- if has_form_errors?(form) do
- gettext("Please correct the errors in the form and try again.")
- else
- gettext("Failed to save member. Please try again.")
- end
+ gettext("Validation failed. Please check your input.")
+ end
+ end
+
+ # Checks if source errors contain other error types
+ defp has_other_error?([_ | _]), do: true
+ defp has_other_error?(_), do: false
+
+ # Extracts message from other error types
+ defp extract_other_error_message([error | _]) do
+ cond do
+ Map.has_key?(error, :message) and is_binary(error.message) ->
+ error.message
+
+ is_struct(error) ->
+ extract_struct_error_message(error)
+
+ true ->
+ gettext("Failed to save member. Please try again.")
+ end
+ end
+
+ # Extracts message from struct error using Ash.ErrorKind protocol
+ defp extract_struct_error_message(error) do
+ try do
+ Ash.ErrorKind.message(error)
+ rescue
+ Protocol.UndefinedError -> gettext("Failed to save member. Please try again.")
end
end
# Checks if form has any errors
defp has_form_errors?(form) do
case Map.get(form, :errors) do
- errors when is_list(errors) and length(errors) > 0 -> true
+ errors when is_list(errors) and errors != [] -> true
_ -> false
end
end
diff --git a/lib/mv_web/router.ex b/lib/mv_web/router.ex
index 682b672..79f4791 100644
--- a/lib/mv_web/router.ex
+++ b/lib/mv_web/router.ex
@@ -58,12 +58,6 @@ defmodule MvWeb.Router do
live "/members/:id", MemberLive.Show, :show
live "/members/:id/show/edit", MemberLive.Show, :edit
- live "/custom_field_values", CustomFieldValueLive.Index, :index
- live "/custom_field_values/new", CustomFieldValueLive.Form, :new
- live "/custom_field_values/:id/edit", CustomFieldValueLive.Form, :edit
- live "/custom_field_values/:id", CustomFieldValueLive.Show, :show
- live "/custom_field_values/:id/show/edit", CustomFieldValueLive.Show, :edit
-
live "/users", UserLive.Index, :index
live "/users/new", UserLive.Form, :new
live "/users/:id/edit", UserLive.Form, :edit
@@ -80,10 +74,6 @@ defmodule MvWeb.Router do
live "/membership_fee_types/new", MembershipFeeTypeLive.Form, :new
live "/membership_fee_types/:id/edit", MembershipFeeTypeLive.Form, :edit
- # Contribution Management (Mock-ups)
- live "/contribution_types", ContributionTypeLive.Index, :index
- live "/contributions/member/:id", ContributionPeriodLive.Show, :show
-
# Role Management (Admin only)
live "/admin/roles", RoleLive.Index, :index
live "/admin/roles/new", RoleLive.Form, :new
diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po
index f386236..fa5cf54 100644
--- a/priv/gettext/de/LC_MESSAGES/default.po
+++ b/priv/gettext/de/LC_MESSAGES/default.po
@@ -11,7 +11,6 @@ msgstr ""
"Language: de\n"
#: lib/mv_web/components/core_components.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Actions"
msgstr "Aktionen"
@@ -37,7 +36,6 @@ msgstr "Verbindung wird wiederhergestellt"
msgid "City"
msgstr "Stadt"
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_live/index.html.heex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
@@ -47,7 +45,6 @@ msgstr "Stadt"
msgid "Delete"
msgstr "Löschen"
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/index_component.ex
#: lib/mv_web/live/member_live/index.html.heex
@@ -65,7 +62,6 @@ msgstr "Bearbeiten"
msgid "Edit Member"
msgstr "Mitglied bearbeiten"
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/index.html.heex
#: lib/mv_web/live/member_live/show.ex
@@ -141,7 +137,6 @@ msgstr "Austrittsdatum"
msgid "House Number"
msgstr "Hausnummer"
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/translations/member_fields.ex
@@ -150,7 +145,6 @@ msgid "Notes"
msgstr "Notizen"
#: lib/mv_web/live/components/payment_filter_component.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/member_live/index/membership_fee_status.ex
@@ -171,7 +165,6 @@ msgid "Save Member"
msgstr "Mitglied speichern"
#: lib/mv_web/live/custom_field_live/form_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/global_settings_live.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#: lib/mv_web/live/member_live/form.ex
@@ -214,14 +207,12 @@ msgid "Yes"
msgstr "Ja"
#: lib/mv_web/live/custom_field_live/form_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/member_live/form.ex
#, elixir-autogen, elixir-format
msgid "create"
msgstr "erstellt"
#: lib/mv_web/live/custom_field_live/form_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/member_live/form.ex
#, elixir-autogen, elixir-format
msgid "update"
@@ -264,7 +255,6 @@ msgstr "Ihr Passwort wurde erfolgreich zurückgesetzt"
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
@@ -275,11 +265,6 @@ msgstr "Ihr Passwort wurde erfolgreich zurückgesetzt"
msgid "Cancel"
msgstr "Abbrechen"
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Choose a member"
-msgstr "Mitglied auswählen"
-
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
@@ -313,13 +298,7 @@ msgstr "Abmelden"
msgid "Listing Users"
msgstr "Benutzer*innen auflisten"
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Member"
-msgstr "Mitglied"
-
#: lib/mv_web/components/layouts/sidebar.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/index.ex
#: lib/mv_web/live/member_live/index.html.heex
#: lib/mv_web/live/membership_fee_type_live/index.ex
@@ -327,7 +306,6 @@ msgstr "Mitglied"
msgid "Members"
msgstr "Mitglieder"
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
@@ -351,7 +329,6 @@ msgstr "Neue*r Benutzer*in"
msgid "Not enabled"
msgstr "Nicht aktiviert"
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format
msgid "Note"
@@ -401,11 +378,6 @@ msgstr "Benutzer*in anzeigen"
msgid "This is a user record from your database."
msgstr "Dies ist ein Benutzer*innen-Datensatz aus Ihrer Datenbank."
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Unsupported value type: %{type}"
-msgstr "Nicht unterstützter Wertetyp: %{type}"
-
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format
msgid "Use this form to manage user records in your database."
@@ -417,11 +389,6 @@ msgstr "Verwenden Sie dieses Formular, um Benutzer*innen-Datensätze zu verwalte
msgid "User"
msgstr "Benutzer*in"
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Value"
-msgstr "Wert"
-
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#, elixir-autogen, elixir-format
@@ -611,37 +578,12 @@ msgstr "E-Mail kann nicht aktualisiert werden: Diese E-Mail-Adresse ist bereits
msgid "This email is already linked to a different OIDC account. Cannot link multiple OIDC providers to the same account."
msgstr "Diese E-Mail-Adresse ist bereits mit einem anderen OIDC-Konto verknüpft. Es können nicht mehrere OIDC-Provider mit demselben Konto verknüpft werden."
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Choose a custom field"
-msgstr "Wähle ein Benutzerdefiniertes Feld"
-
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Custom field"
-msgstr "Benutzerdefinierte Felder"
-
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Custom field value %{action} successfully"
-msgstr "Benutzerdefinierter Feldwert erfolgreich %{action}"
-
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Please select a custom field first"
-msgstr "Bitte wähle zuerst ein Benutzerdefiniertes Feld"
-
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Custom Fields"
msgstr "Benutzerdefinierte Felder"
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Use this form to manage Custom Field Value records in your database."
-msgstr "Verwende dieses Formular, um Benutzerdefinierte Feldwerte in deiner Datenbank zu verwalten."
-
#: lib/mv_web/live/custom_field_live/index_component.ex
#, elixir-autogen, elixir-format
msgid "%{count} member has a value assigned for this custom field."
@@ -866,20 +808,6 @@ msgstr "Speichern"
msgid "Create Member"
msgstr "Mitglied erstellen"
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "%{count} period selected"
-msgid_plural "%{count} periods selected"
-msgstr[0] "%{count} Zyklus ausgewählt"
-msgstr[1] "%{count} Zyklen ausgewählt"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "About Contribution Types"
-msgstr "Über Beitragsarten"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
@@ -887,54 +815,16 @@ msgstr "Über Beitragsarten"
msgid "Amount"
msgstr "Betrag"
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#, elixir-autogen, elixir-format
msgid "Back to Settings"
msgstr "Zurück zu den Einstellungen"
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Can be changed at any time. Amount changes affect future periods only."
msgstr "Kann jederzeit geändert werden. Änderungen des Betrags betreffen nur zukünftige Zyklen."
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Cannot delete - members assigned"
-msgstr "Löschen nicht möglich – es sind Mitglieder zugewiesen"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Change Contribution Type"
-msgstr "Beitragsart ändern"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Contribution Start"
-msgstr "Beitragsbeginn"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Contribution Types"
-msgstr "Beitragsarten"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Contribution type"
-msgstr "Beitragsart"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Contributions for %{name}"
-msgstr "Beiträge für %{name}"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Current"
-msgstr "Aktuell"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Deletion"
@@ -945,12 +835,6 @@ msgstr "Löschen"
msgid "Examples"
msgstr "Beispiele"
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Family"
-msgstr "Familie"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Fixed after creation. Members can only switch between types with the same interval."
@@ -962,27 +846,12 @@ msgid "Global Settings"
msgstr "Globale Einstellungen"
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format
msgid "Half-yearly"
msgstr "Halbjährlich"
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Half-yearly contribution for supporting members"
-msgstr "Halbjährlicher Beitrag für Fördermitglieder"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Honorary"
-msgstr "Ehrenamtlich"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
@@ -995,36 +864,6 @@ msgstr "Intervall"
msgid "Joining date"
msgstr "Beitrittsdatum"
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Joining year - reduced to 0"
-msgstr "Beitrittsjahr – auf 0 reduziert"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Manage contribution types for membership fees."
-msgstr "Beitragsarten für Mitgliedsbeiträge verwalten."
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Mark as Paid"
-msgstr "Als bezahlt markieren"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Mark as Suspended"
-msgstr "Als pausiert markieren"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Mark as Unpaid"
-msgstr "Als unbezahlt markieren"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Member Contributions"
-msgstr "Mitgliedsbeiträge"
-
#: lib/mv_web/live/membership_fee_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Member pays for the year they joined"
@@ -1045,131 +884,35 @@ msgstr "Mitglied zahlt ab dem nächsten vollständigen Quartal"
msgid "Member pays from the next full year"
msgstr "Mitglied zahlt ab dem nächsten vollständigen Jahr"
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Member since"
-msgstr "Mitglied seit"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Members can only switch between contribution types with the same payment interval (e.g., yearly to yearly). This prevents complex period overlaps."
-msgstr "Mitglieder können nur zwischen Beitragsarten mit demselben Zahlungszyklus wechseln (z. B. jährlich zu jährlich). Dadurch werden komplexe Überlappungen vermieden."
-
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Monthly"
msgstr "Monatlich"
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Monthly fee for students and trainees"
-msgstr "Monatlicher Beitrag für Studierende und Auszubildende"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Name & Amount"
msgstr "Name & Betrag"
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "New Contribution Type"
-msgstr "Neue Beitragsart"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "No fee for honorary members"
-msgstr "Kein Beitrag für ehrenamtliche Mitglieder"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Only possible if no members are assigned to this type."
msgstr "Nur möglich, wenn diesem Typ keine Mitglieder zugewiesen sind."
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Open Contributions"
-msgstr "Offene Beiträge"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Paid via bank transfer"
-msgstr "Bezahlt durch Überweisung"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Preview Mockup"
-msgstr "Vorschau"
-
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format
msgid "Quarterly"
msgstr "Vierteljährlich"
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Quarterly fee for family memberships"
-msgstr "Vierteljährlicher Beitrag für Familienmitgliedschaften"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Reduced"
-msgstr "Reduziert"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Reduced fee for unemployed, pensioners, or low income"
-msgstr "Ermäßigter Beitrag für Arbeitslose, Rentner*innen oder Geringverdienende"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Regular"
-msgstr "Regulär"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Reopen"
-msgstr "Wieder öffnen"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Standard membership fee for regular members"
-msgstr "Regulärer Mitgliedsbeitrag für Vollmitglieder"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#, elixir-autogen, elixir-format
msgid "Status"
msgstr "Status"
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Student"
-msgstr "Student"
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Supporting Member"
-msgstr "Fördermitglied"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Suspend"
-msgstr "Pausieren"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/member_live/index/membership_fee_status.ex
@@ -1177,24 +920,7 @@ msgstr "Pausieren"
msgid "Suspended"
msgstr "Pausiert"
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "This page is not functional and only displays the planned features."
-msgstr "Diese Seite ist nicht funktionsfähig und zeigt nur geplante Funktionen."
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Time Period"
-msgstr "Zeitraum"
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Total Contributions"
-msgstr "Gesamtbeiträge"
-
#: lib/mv_web/live/components/payment_filter_component.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/member_live/index/membership_fee_status.ex
@@ -1202,14 +928,7 @@ msgstr "Gesamtbeiträge"
msgid "Unpaid"
msgstr "Unbezahlt"
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Why are not all contribution types shown?"
-msgstr "Warum werden nicht alle Beitragsarten angezeigt?"
-
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
@@ -1697,11 +1416,6 @@ msgstr "Zyklen regenerieren"
msgid "Regenerating..."
msgstr "Regeneriere..."
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Save Custom Field Value"
-msgstr "Benutzerdefinierten Feldwert speichern"
-
#: lib/mv_web/live/member_field_live/form_component.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Save Field"
@@ -1799,11 +1513,6 @@ msgstr "Jährliches Intervall – Beitrittszeitraum einbezogen"
msgid "You are about to delete all %{count} cycles for this member."
msgstr "Du bist dabei alle %{count} Zyklen für dieses Mitglied zu löschen."
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Contribution types define different membership fee structures. Each type has a fixed cycle (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation."
-msgstr "Beitragsarten definieren verschiedene Beitragsmodelle. Jede Art hat einen festen Zyklus (monatlich, vierteljährlich, halbjährlich, jährlich), der nach Erstellung nicht mehr geändert werden kann."
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Delete Membership Fee Type"
@@ -2072,16 +1781,6 @@ msgstr "Zyklus löschen"
msgid "The cycle period will be calculated based on this date and the interval."
msgstr "Der Zyklus wird basierend auf diesem Datum und dem Intervall berechnet."
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Custom field value deleted successfully"
-msgstr "Benutzerdefinierter Feldwert erfolgreich gelöscht"
-
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Custom field value not found"
-msgstr "Benutzerdefinierter Feldwert nicht gefunden"
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Membership fee type not found"
@@ -2102,11 +1801,6 @@ msgstr "Benutzer*in erfolgreich gelöscht"
msgid "User not found"
msgstr "Benutzer*in nicht gefunden"
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "You do not have permission to access this custom field value"
-msgstr "Sie haben keine Berechtigung, auf diesen benutzerdefinierten Feldwert zuzugreifen"
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to access this membership fee type"
@@ -2117,11 +1811,6 @@ msgstr "Sie haben keine Berechtigung, auf diese Mitgliedsbeitragsart zuzugreifen
msgid "You do not have permission to access this user"
msgstr "Sie haben keine Berechtigung, auf diese*n Benutzer*in zuzugreifen"
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "You do not have permission to delete this custom field value"
-msgstr "Sie haben keine Berechtigung, diesen benutzerdefinierten Feldwert zu löschen"
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to delete this membership fee type"
@@ -2167,11 +1856,6 @@ msgstr "Sie haben keine Berechtigung, auf dieses Mitglied zuzugreifen"
msgid "You do not have permission to delete this member"
msgstr "Sie haben keine Berechtigung, dieses Mitglied zu löschen"
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "You do not have permission to view custom field values"
-msgstr "Sie haben keine Berechtigung, benutzerdefinierte Feldwerte anzuzeigen"
-
#: lib/mv_web/live/member_live/form.ex
#, elixir-autogen, elixir-format
msgid "Member created successfully"
@@ -2212,7 +1896,319 @@ msgstr "Beitragstypen"
msgid "Administration"
msgstr "Administration"
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Failed to %{action} member."
+msgstr "Fehler beim %{action} des Mitglieds."
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Failed to save member. Please try again."
+msgstr "Fehler beim Speichern des Mitglieds. Bitte versuchen Sie es erneut."
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Please correct the errors in the form and try again."
+msgstr "Bitte korrigieren Sie die Fehler im Formular und versuchen Sie es erneut."
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Validation failed. Please check your input."
+msgstr "Validierung fehlgeschlagen. Bitte überprüfen Sie Ihre Eingabe."
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Validation failed: %{field} %{message}"
+msgstr "Validierung fehlgeschlagen: %{field} %{message}"
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Validation failed: %{message}"
+msgstr "Validierung fehlgeschlagen: %{message}"
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Use this form to manage Custom Field Value records in your database."
+#~ msgstr "Verwende dieses Formular, um Benutzerdefinierte Feldwerte in deiner Datenbank zu verwalten."
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Member"
+#~ msgstr "Mitglied"
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Choose a custom field"
+#~ msgstr "Wähle ein Benutzerdefiniertes Feld"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Joining year - reduced to 0"
+#~ msgstr "Beitrittsjahr – auf 0 reduziert"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Regular"
+#~ msgstr "Regulär"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Current"
+#~ msgstr "Aktuell"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Paid via bank transfer"
+#~ msgstr "Bezahlt durch Überweisung"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Mark as Unpaid"
+#~ msgstr "Als unbezahlt markieren"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Half-yearly contribution for supporting members"
+#~ msgstr "Halbjährlicher Beitrag für Fördermitglieder"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Reduced fee for unemployed, pensioners, or low income"
+#~ msgstr "Ermäßigter Beitrag für Arbeitslose, Rentner*innen oder Geringverdienende"
+
+#~ #: lib/mv_web/live/custom_field_value_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Custom field value not found"
+#~ msgstr "Benutzerdefinierter Feldwert nicht gefunden"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Supporting Member"
+#~ msgstr "Fördermitglied"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Monthly fee for students and trainees"
+#~ msgstr "Monatlicher Beitrag für Studierende und Auszubildende"
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Custom field value %{action} successfully"
+#~ msgstr "Benutzerdefinierter Feldwert erfolgreich %{action}"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Total Contributions"
+#~ msgstr "Gesamtbeiträge"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Manage contribution types for membership fees."
+#~ msgstr "Beitragsarten für Mitgliedsbeiträge verwalten."
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Change Contribution Type"
+#~ msgstr "Beitragsart ändern"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "New Contribution Type"
+#~ msgstr "Neue Beitragsart"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Time Period"
+#~ msgstr "Zeitraum"
+
+#~ #: lib/mv_web/live/custom_field_value_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Custom field value deleted successfully"
+#~ msgstr "Benutzerdefinierter Feldwert erfolgreich gelöscht"
+
+#~ #: lib/mv_web/live/custom_field_value_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "You do not have permission to access this custom field value"
+#~ msgstr "Sie haben keine Berechtigung, auf diesen benutzerdefinierten Feldwert zuzugreifen"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Cannot delete - members assigned"
+#~ msgstr "Löschen nicht möglich – es sind Mitglieder zugewiesen"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Preview Mockup"
+#~ msgstr "Vorschau"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Contribution Types"
+#~ msgstr "Beitragsarten"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "This page is not functional and only displays the planned features."
+#~ msgstr "Diese Seite ist nicht funktionsfähig und zeigt nur geplante Funktionen."
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Member since"
+#~ msgstr "Mitglied seit"
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Unsupported value type: %{type}"
+#~ msgstr "Nicht unterstützter Wertetyp: %{type}"
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Custom field"
+#~ msgstr "Benutzerdefinierte Felder"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Mark as Paid"
+#~ msgstr "Als bezahlt markieren"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Contribution type"
+#~ msgstr "Beitragsart"
+
#~ #: lib/mv_web/components/layouts/sidebar.ex
#~ #, elixir-autogen, elixir-format, fuzzy
#~ msgid "Contributions"
#~ msgstr "Beiträge"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Reduced"
+#~ msgstr "Reduziert"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "No fee for honorary members"
+#~ msgstr "Kein Beitrag für ehrenamtliche Mitglieder"
+
+#~ #: lib/mv_web/live/custom_field_value_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "You do not have permission to delete this custom field value"
+#~ msgstr "Sie haben keine Berechtigung, diesen benutzerdefinierten Feldwert zu löschen"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "%{count} period selected"
+#~ msgid_plural "%{count} periods selected"
+#~ msgstr[0] "%{count} Zyklus ausgewählt"
+#~ msgstr[1] "%{count} Zyklen ausgewählt"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Mark as Suspended"
+#~ msgstr "Als pausiert markieren"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Contribution types define different membership fee structures. Each type has a fixed cycle (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation."
+#~ msgstr "Beitragsarten definieren verschiedene Beitragsmodelle. Jede Art hat einen festen Zyklus (monatlich, vierteljährlich, halbjährlich, jährlich), der nach Erstellung nicht mehr geändert werden kann."
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Choose a member"
+#~ msgstr "Mitglied auswählen"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Suspend"
+#~ msgstr "Pausieren"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Reopen"
+#~ msgstr "Wieder öffnen"
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Value"
+#~ msgstr "Wert"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Why are not all contribution types shown?"
+#~ msgstr "Warum werden nicht alle Beitragsarten angezeigt?"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Contribution Start"
+#~ msgstr "Beitragsbeginn"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Standard membership fee for regular members"
+#~ msgstr "Regulärer Mitgliedsbeitrag für Vollmitglieder"
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Save Custom Field Value"
+#~ msgstr "Benutzerdefinierten Feldwert speichern"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Honorary"
+#~ msgstr "Ehrenamtlich"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Contributions for %{name}"
+#~ msgstr "Beiträge für %{name}"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Family"
+#~ msgstr "Familie"
+
+#~ #: lib/mv_web/live/custom_field_value_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "You do not have permission to view custom field values"
+#~ msgstr "Sie haben keine Berechtigung, benutzerdefinierte Feldwerte anzuzeigen"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Student"
+#~ msgstr "Student"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Quarterly fee for family memberships"
+#~ msgstr "Vierteljährlicher Beitrag für Familienmitgliedschaften"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Members can only switch between contribution types with the same payment interval (e.g., yearly to yearly). This prevents complex period overlaps."
+#~ msgstr "Mitglieder können nur zwischen Beitragsarten mit demselben Zahlungszyklus wechseln (z. B. jährlich zu jährlich). Dadurch werden komplexe Überlappungen vermieden."
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Please select a custom field first"
+#~ msgstr "Bitte wähle zuerst ein Benutzerdefiniertes Feld"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Open Contributions"
+#~ msgstr "Offene Beiträge"
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Member Contributions"
+#~ msgstr "Mitgliedsbeiträge"
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "About Contribution Types"
+#~ msgstr "Über Beitragsarten"
diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot
index 9df03a5..d43c1a6 100644
--- a/priv/gettext/default.pot
+++ b/priv/gettext/default.pot
@@ -12,7 +12,6 @@ msgid ""
msgstr ""
#: lib/mv_web/components/core_components.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Actions"
msgstr ""
@@ -38,7 +37,6 @@ msgstr ""
msgid "City"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_live/index.html.heex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
@@ -48,7 +46,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/index_component.ex
#: lib/mv_web/live/member_live/index.html.heex
@@ -66,7 +63,6 @@ msgstr ""
msgid "Edit Member"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/index.html.heex
#: lib/mv_web/live/member_live/show.ex
@@ -142,7 +138,6 @@ msgstr ""
msgid "House Number"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/translations/member_fields.ex
@@ -151,7 +146,6 @@ msgid "Notes"
msgstr ""
#: lib/mv_web/live/components/payment_filter_component.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/member_live/index/membership_fee_status.ex
@@ -172,7 +166,6 @@ msgid "Save Member"
msgstr ""
#: lib/mv_web/live/custom_field_live/form_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/global_settings_live.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#: lib/mv_web/live/member_live/form.ex
@@ -215,14 +208,12 @@ msgid "Yes"
msgstr ""
#: lib/mv_web/live/custom_field_live/form_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/member_live/form.ex
#, elixir-autogen, elixir-format
msgid "create"
msgstr ""
#: lib/mv_web/live/custom_field_live/form_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/member_live/form.ex
#, elixir-autogen, elixir-format
msgid "update"
@@ -265,7 +256,6 @@ msgstr ""
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
@@ -276,11 +266,6 @@ msgstr ""
msgid "Cancel"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Choose a member"
-msgstr ""
-
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
@@ -314,13 +299,7 @@ msgstr ""
msgid "Listing Users"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Member"
-msgstr ""
-
#: lib/mv_web/components/layouts/sidebar.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/index.ex
#: lib/mv_web/live/member_live/index.html.heex
#: lib/mv_web/live/membership_fee_type_live/index.ex
@@ -328,7 +307,6 @@ msgstr ""
msgid "Members"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
@@ -352,7 +330,6 @@ msgstr ""
msgid "Not enabled"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format
msgid "Note"
@@ -402,11 +379,6 @@ msgstr ""
msgid "This is a user record from your database."
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Unsupported value type: %{type}"
-msgstr ""
-
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format
msgid "Use this form to manage user records in your database."
@@ -418,11 +390,6 @@ msgstr ""
msgid "User"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Value"
-msgstr ""
-
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#, elixir-autogen, elixir-format
@@ -612,37 +579,12 @@ msgstr ""
msgid "This email is already linked to a different OIDC account. Cannot link multiple OIDC providers to the same account."
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Choose a custom field"
-msgstr ""
-
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Custom field"
-msgstr ""
-
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Custom field value %{action} successfully"
-msgstr ""
-
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Please select a custom field first"
-msgstr ""
-
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
msgid "Custom Fields"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Use this form to manage Custom Field Value records in your database."
-msgstr ""
-
#: lib/mv_web/live/custom_field_live/index_component.ex
#, elixir-autogen, elixir-format
msgid "%{count} member has a value assigned for this custom field."
@@ -867,20 +809,6 @@ msgstr ""
msgid "Create Member"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "%{count} period selected"
-msgid_plural "%{count} periods selected"
-msgstr[0] ""
-msgstr[1] ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "About Contribution Types"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
@@ -888,54 +816,16 @@ msgstr ""
msgid "Amount"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#, elixir-autogen, elixir-format
msgid "Back to Settings"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Can be changed at any time. Amount changes affect future periods only."
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Cannot delete - members assigned"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Change Contribution Type"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Contribution Start"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Contribution Types"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Contribution type"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Contributions for %{name}"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Current"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Deletion"
@@ -946,12 +836,6 @@ msgstr ""
msgid "Examples"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Family"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Fixed after creation. Members can only switch between types with the same interval."
@@ -963,27 +847,12 @@ msgid "Global Settings"
msgstr ""
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format
msgid "Half-yearly"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Half-yearly contribution for supporting members"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Honorary"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
@@ -996,36 +865,6 @@ msgstr ""
msgid "Joining date"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Joining year - reduced to 0"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Manage contribution types for membership fees."
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Mark as Paid"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Mark as Suspended"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Mark as Unpaid"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Member Contributions"
-msgstr ""
-
#: lib/mv_web/live/membership_fee_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Member pays for the year they joined"
@@ -1046,131 +885,35 @@ msgstr ""
msgid "Member pays from the next full year"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Member since"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Members can only switch between contribution types with the same payment interval (e.g., yearly to yearly). This prevents complex period overlaps."
-msgstr ""
-
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format
msgid "Monthly"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Monthly fee for students and trainees"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Name & Amount"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "New Contribution Type"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "No fee for honorary members"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Only possible if no members are assigned to this type."
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Open Contributions"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Paid via bank transfer"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Preview Mockup"
-msgstr ""
-
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format
msgid "Quarterly"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Quarterly fee for family memberships"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Reduced"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Reduced fee for unemployed, pensioners, or low income"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Regular"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Reopen"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Standard membership fee for regular members"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#, elixir-autogen, elixir-format
msgid "Status"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Student"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Supporting Member"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Suspend"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/member_live/index/membership_fee_status.ex
@@ -1178,24 +921,7 @@ msgstr ""
msgid "Suspended"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "This page is not functional and only displays the planned features."
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Time Period"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Total Contributions"
-msgstr ""
-
#: lib/mv_web/live/components/payment_filter_component.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/member_live/index/membership_fee_status.ex
@@ -1203,14 +929,7 @@ msgstr ""
msgid "Unpaid"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Why are not all contribution types shown?"
-msgstr ""
-
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format
@@ -1698,11 +1417,6 @@ msgstr ""
msgid "Regenerating..."
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Save Custom Field Value"
-msgstr ""
-
#: lib/mv_web/live/member_field_live/form_component.ex
#, elixir-autogen, elixir-format
msgid "Save Field"
@@ -1800,11 +1514,6 @@ msgstr ""
msgid "You are about to delete all %{count} cycles for this member."
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Contribution types define different membership fee structures. Each type has a fixed cycle (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation."
-msgstr ""
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Delete Membership Fee Type"
@@ -2073,16 +1782,6 @@ msgstr ""
msgid "The cycle period will be calculated based on this date and the interval."
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Custom field value deleted successfully"
-msgstr ""
-
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Custom field value not found"
-msgstr ""
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Membership fee type not found"
@@ -2103,11 +1802,6 @@ msgstr ""
msgid "User not found"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "You do not have permission to access this custom field value"
-msgstr ""
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to access this membership fee type"
@@ -2118,11 +1812,6 @@ msgstr ""
msgid "You do not have permission to access this user"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "You do not have permission to delete this custom field value"
-msgstr ""
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "You do not have permission to delete this membership fee type"
@@ -2168,11 +1857,6 @@ msgstr ""
msgid "You do not have permission to delete this member"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "You do not have permission to view custom field values"
-msgstr ""
-
#: lib/mv_web/live/member_live/form.ex
#, elixir-autogen, elixir-format
msgid "Member created successfully"
@@ -2191,6 +1875,7 @@ msgstr ""
#: lib/mv/membership/import/member_csv.ex
#, elixir-autogen, elixir-format
msgid "Email is required."
+msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
@@ -2211,3 +1896,33 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "Administration"
msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Failed to %{action} member."
+msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Failed to save member. Please try again."
+msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Please correct the errors in the form and try again."
+msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Validation failed. Please check your input."
+msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Validation failed: %{field} %{message}"
+msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Validation failed: %{message}"
+msgstr ""
diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po
index 6b4830b..a6d8fc2 100644
--- a/priv/gettext/en/LC_MESSAGES/default.po
+++ b/priv/gettext/en/LC_MESSAGES/default.po
@@ -12,7 +12,6 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: lib/mv_web/components/core_components.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Actions"
msgstr ""
@@ -38,7 +37,6 @@ msgstr ""
msgid "City"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_live/index.html.heex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
@@ -48,7 +46,6 @@ msgstr ""
msgid "Delete"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/index_component.ex
#: lib/mv_web/live/member_live/index.html.heex
@@ -66,7 +63,6 @@ msgstr ""
msgid "Edit Member"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/index.html.heex
#: lib/mv_web/live/member_live/show.ex
@@ -142,7 +138,6 @@ msgstr ""
msgid "House Number"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/translations/member_fields.ex
@@ -151,7 +146,6 @@ msgid "Notes"
msgstr ""
#: lib/mv_web/live/components/payment_filter_component.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/member_live/index/membership_fee_status.ex
@@ -172,7 +166,6 @@ msgid "Save Member"
msgstr ""
#: lib/mv_web/live/custom_field_live/form_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/global_settings_live.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#: lib/mv_web/live/member_live/form.ex
@@ -215,14 +208,12 @@ msgid "Yes"
msgstr ""
#: lib/mv_web/live/custom_field_live/form_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/member_live/form.ex
#, elixir-autogen, elixir-format
msgid "create"
msgstr ""
#: lib/mv_web/live/custom_field_live/form_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/member_live/form.ex
#, elixir-autogen, elixir-format
msgid "update"
@@ -265,7 +256,6 @@ msgstr ""
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
-#: lib/mv_web/live/custom_field_value_live/form.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
@@ -276,11 +266,6 @@ msgstr ""
msgid "Cancel"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Choose a member"
-msgstr ""
-
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
@@ -314,13 +299,7 @@ msgstr ""
msgid "Listing Users"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Member"
-msgstr ""
-
#: lib/mv_web/components/layouts/sidebar.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/index.ex
#: lib/mv_web/live/member_live/index.html.heex
#: lib/mv_web/live/membership_fee_type_live/index.ex
@@ -328,7 +307,6 @@ msgstr ""
msgid "Members"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
@@ -352,7 +330,6 @@ msgstr ""
msgid "Not enabled"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Note"
@@ -402,11 +379,6 @@ msgstr ""
msgid "This is a user record from your database."
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Unsupported value type: %{type}"
-msgstr ""
-
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Use this form to manage user records in your database."
@@ -418,11 +390,6 @@ msgstr ""
msgid "User"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Value"
-msgstr ""
-
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#, elixir-autogen, elixir-format
@@ -612,37 +579,12 @@ msgstr ""
msgid "This email is already linked to a different OIDC account. Cannot link multiple OIDC providers to the same account."
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Choose a custom field"
-msgstr ""
-
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Custom field"
-msgstr ""
-
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Custom field value %{action} successfully"
-msgstr ""
-
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format
-msgid "Please select a custom field first"
-msgstr ""
-
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Custom Fields"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Use this form to manage Custom Field Value records in your database."
-msgstr ""
-
#: lib/mv_web/live/custom_field_live/index_component.ex
#, elixir-autogen, elixir-format
msgid "%{count} member has a value assigned for this custom field."
@@ -867,20 +809,6 @@ msgstr ""
msgid "Create Member"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "%{count} period selected"
-msgid_plural "%{count} periods selected"
-msgstr[0] ""
-msgstr[1] ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "About Contribution Types"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
@@ -888,54 +816,16 @@ msgstr ""
msgid "Amount"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_field_live/form_component.ex
#, elixir-autogen, elixir-format
msgid "Back to Settings"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Can be changed at any time. Amount changes affect future periods only."
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Cannot delete - members assigned"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Change Contribution Type"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Contribution Start"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Contribution Types"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Contribution type"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Contributions for %{name}"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Current"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Deletion"
@@ -946,12 +836,6 @@ msgstr ""
msgid "Examples"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Family"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Fixed after creation. Members can only switch between types with the same interval."
@@ -963,27 +847,12 @@ msgid "Global Settings"
msgstr ""
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format
msgid "Half-yearly"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Half-yearly contribution for supporting members"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Honorary"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
@@ -996,36 +865,6 @@ msgstr ""
msgid "Joining date"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Joining year - reduced to 0"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Manage contribution types for membership fees."
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Mark as Paid"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Mark as Suspended"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Mark as Unpaid"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Member Contributions"
-msgstr ""
-
#: lib/mv_web/live/membership_fee_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Member pays for the year they joined"
@@ -1046,131 +885,35 @@ msgstr ""
msgid "Member pays from the next full year"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Member since"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Members can only switch between contribution types with the same payment interval (e.g., yearly to yearly). This prevents complex period overlaps."
-msgstr ""
-
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format
msgid "Monthly"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Monthly fee for students and trainees"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Name & Amount"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "New Contribution Type"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "No fee for honorary members"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Only possible if no members are assigned to this type."
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Open Contributions"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Paid via bank transfer"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Preview Mockup"
-msgstr ""
-
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format
msgid "Quarterly"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Quarterly fee for family memberships"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Reduced"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Reduced fee for unemployed, pensioners, or low income"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Regular"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Reopen"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Standard membership fee for regular members"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#, elixir-autogen, elixir-format
msgid "Status"
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Student"
-msgstr ""
-
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "Supporting Member"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Suspend"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/member_live/index/membership_fee_status.ex
@@ -1178,24 +921,7 @@ msgstr ""
msgid "Suspended"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format
-msgid "This page is not functional and only displays the planned features."
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Time Period"
-msgstr ""
-
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Total Contributions"
-msgstr ""
-
#: lib/mv_web/live/components/payment_filter_component.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#: lib/mv_web/member_live/index/membership_fee_status.ex
@@ -1203,14 +929,7 @@ msgstr ""
msgid "Unpaid"
msgstr ""
-#: lib/mv_web/live/contribution_period_live/show.ex
-#, elixir-autogen, elixir-format
-msgid "Why are not all contribution types shown?"
-msgstr ""
-
#: lib/mv_web/helpers/membership_fee_helpers.ex
-#: lib/mv_web/live/contribution_period_live/show.ex
-#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#: lib/mv_web/live/membership_fee_type_live/form.ex
#, elixir-autogen, elixir-format
@@ -1698,11 +1417,6 @@ msgstr ""
msgid "Regenerating..."
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/form.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Save Custom Field Value"
-msgstr ""
-
#: lib/mv_web/live/member_field_live/form_component.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Save Field"
@@ -1800,11 +1514,6 @@ msgstr ""
msgid "You are about to delete all %{count} cycles for this member."
msgstr ""
-#: lib/mv_web/live/contribution_type_live/index.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Contribution types define different membership fee structures. Each type has a fixed cycle (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation."
-msgstr ""
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Delete Membership Fee Type"
@@ -2073,16 +1782,6 @@ msgstr ""
msgid "The cycle period will be calculated based on this date and the interval."
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Custom field value deleted successfully"
-msgstr ""
-
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "Custom field value not found"
-msgstr ""
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Membership fee type not found"
@@ -2103,11 +1802,6 @@ msgstr ""
msgid "User not found"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "You do not have permission to access this custom field value"
-msgstr ""
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "You do not have permission to access this membership fee type"
@@ -2118,11 +1812,6 @@ msgstr ""
msgid "You do not have permission to access this user"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "You do not have permission to delete this custom field value"
-msgstr ""
-
#: lib/mv_web/live/membership_fee_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "You do not have permission to delete this membership fee type"
@@ -2168,11 +1857,6 @@ msgstr ""
msgid "You do not have permission to delete this member"
msgstr ""
-#: lib/mv_web/live/custom_field_value_live/index.ex
-#, elixir-autogen, elixir-format, fuzzy
-msgid "You do not have permission to view custom field values"
-msgstr ""
-
#: lib/mv_web/live/member_live/form.ex
#, elixir-autogen, elixir-format
msgid "Member created successfully"
@@ -2213,12 +1897,324 @@ msgstr ""
msgid "Administration"
msgstr ""
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Failed to %{action} member."
+msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Failed to save member. Please try again."
+msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Please correct the errors in the form and try again."
+msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Validation failed. Please check your input."
+msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Validation failed: %{field} %{message}"
+msgstr ""
+
+#: lib/mv_web/live/member_live/form.ex
+#, elixir-autogen, elixir-format
+msgid "Validation failed: %{message}"
+msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Use this form to manage Custom Field Value records in your database."
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Member"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Choose a custom field"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Joining year - reduced to 0"
+#~ msgstr ""
+
#~ #: lib/mv_web/components/layouts/sidebar.ex
#~ #, elixir-autogen, elixir-format, fuzzy
#~ msgid "Admin"
#~ msgstr ""
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Regular"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Current"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Paid via bank transfer"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Mark as Unpaid"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Half-yearly contribution for supporting members"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Reduced fee for unemployed, pensioners, or low income"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/index.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Custom field value not found"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Supporting Member"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Monthly fee for students and trainees"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Custom field value %{action} successfully"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Total Contributions"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Manage contribution types for membership fees."
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Change Contribution Type"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "New Contribution Type"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Time Period"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/index.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Custom field value deleted successfully"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/index.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "You do not have permission to access this custom field value"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Cannot delete - members assigned"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Preview Mockup"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Contribution Types"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "This page is not functional and only displays the planned features."
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Member since"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Unsupported value type: %{type}"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Custom field"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Mark as Paid"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Contribution type"
+#~ msgstr ""
+
#~ #: lib/mv_web/components/layouts/sidebar.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Contributions"
#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Reduced"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "No fee for honorary members"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/index.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "You do not have permission to delete this custom field value"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "%{count} period selected"
+#~ msgid_plural "%{count} periods selected"
+#~ msgstr[0] ""
+#~ msgstr[1] ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Mark as Suspended"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Contribution types define different membership fee structures. Each type has a fixed cycle (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation."
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Choose a member"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Suspend"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Reopen"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Value"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Why are not all contribution types shown?"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Contribution Start"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Standard membership fee for regular members"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "Save Custom Field Value"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Honorary"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Contributions for %{name}"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Family"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/index.ex
+#~ #, elixir-autogen, elixir-format, fuzzy
+#~ msgid "You do not have permission to view custom field values"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Student"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Quarterly fee for family memberships"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Members can only switch between contribution types with the same payment interval (e.g., yearly to yearly). This prevents complex period overlaps."
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/custom_field_value_live/form.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Please select a custom field first"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Open Contributions"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_period_live/show.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "Member Contributions"
+#~ msgstr ""
+
+#~ #: lib/mv_web/live/contribution_type_live/index.ex
+#~ #, elixir-autogen, elixir-format
+#~ msgid "About Contribution Types"
+#~ msgstr ""
diff --git a/test/membership_fees/membership_fee_type_integration_test.exs b/test/membership_fees/membership_fee_type_integration_test.exs
index b70f47c..681bd02 100644
--- a/test/membership_fees/membership_fee_type_integration_test.exs
+++ b/test/membership_fees/membership_fee_type_integration_test.exs
@@ -158,10 +158,8 @@ defmodule Mv.MembershipFees.MembershipFeeTypeIntegrationTest do
|> Ash.update!()
# Create a member without explicitly setting membership_fee_type_id
- # Note: This test assumes that the Member resource automatically assigns
- # the default_membership_fee_type_id during creation. If this is not yet
- # implemented, this test will fail initially (which is expected in TDD).
- # For now, we skip this test as the auto-assignment feature is not yet implemented.
+ # The Member resource automatically assigns the default_membership_fee_type_id
+ # during creation via SetDefaultMembershipFeeType change.
{:ok, member} =
Ash.create(Member, %{
first_name: "Test",
@@ -169,10 +167,8 @@ defmodule Mv.MembershipFees.MembershipFeeTypeIntegrationTest do
email: "test.member.#{System.unique_integer([:positive])}@example.com"
})
- # TODO: When auto-assignment is implemented, uncomment this assertion
- # assert member.membership_fee_type_id == fee_type.id
- # For now, we just verify the member was created successfully
- assert %Member{} = member
+ # Verify that the default membership fee type was automatically assigned
+ assert member.membership_fee_type_id == fee_type.id
end
test "include_joining_cycle is used during cycle generation" do
diff --git a/test/mv/membership/import/member_csv_test.exs b/test/mv/membership/import/member_csv_test.exs
index b5af238..98943d5 100644
--- a/test/mv/membership/import/member_csv_test.exs
+++ b/test/mv/membership/import/member_csv_test.exs
@@ -404,7 +404,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do
assert chunk_result.inserted == 0
assert chunk_result.failed == 10
- assert length(chunk_result.errors) == 0
+ assert chunk_result.errors == []
end
test "error capping with mixed success and failure" do
diff --git a/test/mv_web/live/profile_navigation_test.exs b/test/mv_web/live/profile_navigation_test.exs
index 849d229..cac6802 100644
--- a/test/mv_web/live/profile_navigation_test.exs
+++ b/test/mv_web/live/profile_navigation_test.exs
@@ -146,8 +146,6 @@ defmodule MvWeb.ProfileNavigationTest do
"/",
"/members",
"/members/new",
- "/custom_field_values",
- "/custom_field_values/new",
"/users",
"/users/new"
]
diff --git a/test/mv_web/live/role_live/show_test.exs b/test/mv_web/live/role_live/show_test.exs
new file mode 100644
index 0000000..2c56347
--- /dev/null
+++ b/test/mv_web/live/role_live/show_test.exs
@@ -0,0 +1,274 @@
+defmodule MvWeb.RoleLive.ShowTest do
+ @moduledoc """
+ Tests for the role show page.
+
+ Tests cover:
+ - Displaying role information
+ - System role badge display
+ - User count display
+ - Navigation
+ - Error handling
+ - Delete functionality
+ """
+ use MvWeb.ConnCase, async: false
+ import Phoenix.LiveViewTest
+ require Ash.Query
+ use Gettext, backend: MvWeb.Gettext
+
+ alias Mv.Authorization
+ alias Mv.Authorization.Role
+
+ # Helper to create a role
+ defp create_role(attrs \\ %{}) do
+ default_attrs = %{
+ name: "Test Role #{System.unique_integer([:positive])}",
+ description: "Test description",
+ permission_set_name: "read_only"
+ }
+
+ attrs = Map.merge(default_attrs, attrs)
+
+ case Authorization.create_role(attrs) do
+ {:ok, role} -> role
+ {:error, error} -> raise "Failed to create role: #{inspect(error)}"
+ end
+ end
+
+ # Helper to create admin user with admin role
+ defp create_admin_user(conn) do
+ # Create admin role
+ admin_role =
+ case Authorization.list_roles() do
+ {:ok, roles} ->
+ case Enum.find(roles, &(&1.name == "Admin")) do
+ nil ->
+ # Create admin role if it doesn't exist
+ create_role(%{
+ name: "Admin",
+ description: "Administrator with full access",
+ permission_set_name: "admin"
+ })
+
+ role ->
+ role
+ end
+
+ _ ->
+ # Create admin role if list_roles fails
+ create_role(%{
+ name: "Admin",
+ description: "Administrator with full access",
+ permission_set_name: "admin"
+ })
+ end
+
+ # Create user
+ {:ok, user} =
+ Mv.Accounts.User
+ |> Ash.Changeset.for_create(:register_with_password, %{
+ email: "admin#{System.unique_integer([:positive])}@mv.local",
+ password: "testpassword123"
+ })
+ |> Ash.create()
+
+ # Assign admin role using manage_relationship
+ {:ok, user} =
+ user
+ |> Ash.Changeset.for_update(:update, %{})
+ |> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
+ |> Ash.update()
+
+ # Load role for authorization checks (must be loaded for can?/3 to work)
+ user_with_role = Ash.load!(user, :role, domain: Mv.Accounts)
+
+ # Store user with role in session for LiveView
+ conn = conn_with_password_user(conn, user_with_role)
+ {conn, user_with_role, admin_role}
+ end
+
+ describe "mount and display" do
+ setup %{conn: conn} do
+ {conn, _user, _admin_role} = create_admin_user(conn)
+ %{conn: conn}
+ end
+
+ test "mounts successfully with valid role ID", %{conn: conn} do
+ role = create_role()
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
+
+ assert html =~ role.name
+ end
+
+ test "displays role name", %{conn: conn} do
+ role = create_role(%{name: "Test Role Name"})
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
+
+ assert html =~ "Test Role Name"
+ assert html =~ gettext("Name")
+ end
+
+ test "displays role description when present", %{conn: conn} do
+ role = create_role(%{description: "This is a test description"})
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
+
+ assert html =~ "This is a test description"
+ assert html =~ gettext("Description")
+ end
+
+ test "displays 'No description' when description is missing", %{conn: conn} do
+ role = create_role(%{description: nil})
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
+
+ assert html =~ gettext("No description")
+ end
+
+ test "displays permission set name", %{conn: conn} do
+ role = create_role(%{permission_set_name: "read_only"})
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
+
+ assert html =~ "read_only"
+ assert html =~ gettext("Permission Set")
+ end
+
+ test "displays system role badge when is_system_role is true", %{conn: conn} do
+ system_role =
+ Role
+ |> Ash.Changeset.for_create(:create_role, %{
+ name: "System Role",
+ permission_set_name: "own_data"
+ })
+ |> Ash.Changeset.force_change_attribute(:is_system_role, true)
+ |> Ash.create!()
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{system_role.id}")
+
+ assert html =~ gettext("System Role")
+ assert html =~ gettext("Yes")
+ end
+
+ test "displays non-system role badge when is_system_role is false", %{conn: conn} do
+ role = create_role()
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
+
+ assert html =~ gettext("System Role")
+ assert html =~ gettext("No")
+ end
+
+ test "displays user count", %{conn: conn} do
+ role = create_role()
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
+
+ # User count should be displayed (might be 0 or more)
+ assert html =~ gettext("User") || html =~ "0" || html =~ "users"
+ end
+ end
+
+ describe "navigation" do
+ setup %{conn: conn} do
+ {conn, _user, _admin_role} = create_admin_user(conn)
+ %{conn: conn}
+ end
+
+ test "back button navigates to role list", %{conn: conn} do
+ role = create_role()
+
+ {:ok, view, _html} = live(conn, "/admin/roles/#{role.id}")
+
+ assert {:error, {:live_redirect, %{to: to}}} =
+ view
+ |> element(
+ "a[aria-label='#{gettext("Back to roles list")}'], button[aria-label='#{gettext("Back to roles list")}']"
+ )
+ |> render_click()
+
+ assert to == "/admin/roles"
+ end
+
+ test "edit button navigates to edit form", %{conn: conn} do
+ role = create_role()
+
+ {:ok, view, _html} = live(conn, "/admin/roles/#{role.id}")
+
+ assert {:error, {:live_redirect, %{to: to}}} =
+ view
+ |> element(
+ "a[href='/admin/roles/#{role.id}/edit'], button[href='/admin/roles/#{role.id}/edit']"
+ )
+ |> render_click()
+
+ assert to == "/admin/roles/#{role.id}/edit"
+ end
+ end
+
+ describe "error handling" do
+ setup %{conn: conn} do
+ {conn, _user, _admin_role} = create_admin_user(conn)
+ %{conn: conn}
+ end
+
+ test "redirects to role list with error for invalid role ID", %{conn: conn} do
+ invalid_id = Ecto.UUID.generate()
+
+ # Should redirect to index with error message
+ result = live(conn, "/admin/roles/#{invalid_id}")
+
+ assert match?({:error, {:redirect, %{to: "/admin/roles"}}}, result) or
+ match?({:error, {:live_redirect, %{to: "/admin/roles"}}}, result)
+ end
+ end
+
+ describe "delete functionality" do
+ setup %{conn: conn} do
+ {conn, _user, _admin_role} = create_admin_user(conn)
+ %{conn: conn}
+ end
+
+ test "delete button is not shown for system roles", %{conn: conn} do
+ system_role =
+ Role
+ |> Ash.Changeset.for_create(:create_role, %{
+ name: "System Role",
+ permission_set_name: "own_data"
+ })
+ |> Ash.Changeset.force_change_attribute(:is_system_role, true)
+ |> Ash.create!()
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{system_role.id}")
+
+ # Delete button should not be visible for system roles
+ refute html =~ ~r/Delete.*Role.*#{system_role.id}/i
+ end
+
+ test "delete button is shown for non-system roles", %{conn: conn} do
+ role = create_role()
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
+
+ # Delete button should be visible for non-system roles
+ assert html =~ gettext("Delete Role") || html =~ "delete"
+ end
+ end
+
+ describe "page title" do
+ setup %{conn: conn} do
+ {conn, _user, _admin_role} = create_admin_user(conn)
+ %{conn: conn}
+ end
+
+ test "sets correct page title", %{conn: conn} do
+ role = create_role()
+
+ {:ok, _view, html} = live(conn, "/admin/roles/#{role.id}")
+
+ # Check that page title is set (might be in title tag or header)
+ assert html =~ gettext("Show Role") || html =~ role.name
+ end
+ end
+end
diff --git a/test/mv_web/live/user_live/show_test.exs b/test/mv_web/live/user_live/show_test.exs
new file mode 100644
index 0000000..054640c
--- /dev/null
+++ b/test/mv_web/live/user_live/show_test.exs
@@ -0,0 +1,155 @@
+defmodule MvWeb.UserLive.ShowTest do
+ @moduledoc """
+ Tests for the user show page.
+
+ Tests cover:
+ - Displaying user information
+ - Authentication status display
+ - Linked member display
+ - Navigation
+ - Error handling
+ """
+ use MvWeb.ConnCase, async: true
+ import Phoenix.LiveViewTest
+ require Ash.Query
+ use Gettext, backend: MvWeb.Gettext
+
+ alias Mv.Membership.Member
+
+ setup do
+ # Create test user
+ user = create_test_user(%{email: "test@example.com", oidc_id: "test123"})
+ %{user: user}
+ end
+
+ describe "mount and display" do
+ test "mounts successfully with valid user ID", %{conn: conn, user: user} do
+ conn = conn_with_oidc_user(conn)
+ {:ok, _view, html} = live(conn, ~p"/users/#{user.id}")
+
+ assert html =~ to_string(user.email)
+ end
+
+ test "displays user email", %{conn: conn, user: user} do
+ conn = conn_with_oidc_user(conn)
+ {:ok, _view, html} = live(conn, ~p"/users/#{user.id}")
+
+ assert html =~ to_string(user.email)
+ assert html =~ gettext("Email")
+ end
+
+ test "displays password authentication status when enabled", %{conn: conn} do
+ user = create_test_user(%{email: "password-user@example.com", password: "test123"})
+ conn = conn_with_oidc_user(conn)
+ {:ok, _view, html} = live(conn, ~p"/users/#{user.id}")
+
+ assert html =~ gettext("Password Authentication")
+ assert html =~ gettext("Enabled")
+ end
+
+ test "displays password authentication status when not enabled", %{conn: conn} do
+ # User without password (only OIDC) - create user with OIDC only
+ user =
+ create_test_user(%{
+ email: "oidc-only#{System.unique_integer([:positive])}@example.com",
+ oidc_id: "oidc#{System.unique_integer([:positive])}",
+ hashed_password: nil
+ })
+
+ conn = conn_with_oidc_user(conn)
+ {:ok, _view, html} = live(conn, ~p"/users/#{user.id}")
+
+ assert html =~ gettext("Password Authentication")
+ assert html =~ gettext("Not enabled")
+ end
+
+ test "displays linked member when present", %{conn: conn} do
+ # Create member
+ {:ok, member} =
+ Member
+ |> Ash.Changeset.for_create(:create_member, %{
+ first_name: "Alice",
+ last_name: "Smith",
+ email: "alice@example.com"
+ })
+ |> Ash.create()
+
+ # Create user and link to member
+ user = create_test_user(%{email: "user@example.com"})
+
+ {:ok, _updated_user} =
+ user
+ |> Ash.Changeset.for_update(:update, %{})
+ |> Ash.Changeset.manage_relationship(:member, member, type: :append_and_remove)
+ |> Ash.update()
+
+ conn = conn_with_oidc_user(conn)
+ {:ok, _view, html} = live(conn, ~p"/users/#{user.id}")
+
+ assert html =~ gettext("Linked Member")
+ assert html =~ "Alice Smith"
+ assert html =~ ~r/href="[^"]*\/members\/#{member.id}"/
+ end
+
+ test "displays 'No member linked' when no member is linked", %{conn: conn, user: user} do
+ conn = conn_with_oidc_user(conn)
+ {:ok, _view, html} = live(conn, ~p"/users/#{user.id}")
+
+ assert html =~ gettext("Linked Member")
+ assert html =~ gettext("No member linked")
+ end
+ end
+
+ describe "navigation" do
+ test "back button navigates to user list", %{conn: conn, user: user} do
+ conn = conn_with_oidc_user(conn)
+ {:ok, view, _html} = live(conn, ~p"/users/#{user.id}")
+
+ assert {:error, {:live_redirect, %{to: to}}} =
+ view
+ |> element(
+ "a[aria-label='#{gettext("Back to users list")}'], button[aria-label='#{gettext("Back to users list")}']"
+ )
+ |> render_click()
+
+ assert to == "/users"
+ end
+
+ test "edit button navigates to edit form", %{conn: conn, user: user} do
+ conn = conn_with_oidc_user(conn)
+ {:ok, view, _html} = live(conn, ~p"/users/#{user.id}")
+
+ assert {:error, {:live_redirect, %{to: to}}} =
+ view
+ |> element(
+ "a[href='/users/#{user.id}/edit?return_to=show'], button[href='/users/#{user.id}/edit?return_to=show']"
+ )
+ |> render_click()
+
+ assert to == "/users/#{user.id}/edit?return_to=show"
+ end
+ end
+
+ describe "error handling" do
+ test "raises exception for invalid user ID", %{conn: conn} do
+ invalid_id = Ecto.UUID.generate()
+ conn = conn_with_oidc_user(conn)
+
+ # The mount function uses Ash.get! which will raise an exception
+ # This is expected behavior - the LiveView doesn't handle this case
+ assert_raise Ash.Error.Invalid, fn ->
+ live(conn, ~p"/users/#{invalid_id}")
+ end
+ end
+ end
+
+ describe "page title" do
+ test "sets correct page title", %{conn: conn, user: user} do
+ conn = conn_with_oidc_user(conn)
+ {:ok, _view, html} = live(conn, ~p"/users/#{user.id}")
+
+ # Check that page title is set (might be in title tag or header)
+ assert html =~ gettext("Show User") || html =~ to_string(user.email)
+ end
+ end
+end