Compare commits

..

5 commits

Author SHA1 Message Date
18641bb6ea Merge pull request 'UX - Avoid opening member by clicking the checkbox closes #233' (#250) from feature/223_member_checkbox into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #250
Reviewed-by: carla <carla@noreply.git.local-it.org>
2025-12-08 12:11:47 +01:00
c3e95ca711 formatting
All checks were successful
continuous-integration/drone/push Build is passing
2025-12-08 11:51:45 +01:00
1b06f885bf Merge branch 'main' into feature/223_member_checkbox
Some checks failed
continuous-integration/drone/push Build is failing
2025-12-08 11:43:54 +01:00
6b0ec28d9b
fix checkbox tests 2025-12-03 14:34:31 +01:00
8e4f1ba674 feat: add col_click attribute to table component for checkbox column
- Add col_click slot attribute to table component that overrides row_click
- Clicking anywhere in the checkbox column now toggles the checkbox
- Clicking other columns still navigates to member details

Closes #223
2025-12-03 14:24:10 +01:00
12 changed files with 270 additions and 420 deletions

View file

@ -153,7 +153,7 @@ defmodule MvWeb.CoreComponents do
aria-haspopup="menu"
aria-expanded={@open}
aria-controls={@id}
class="btn"
class="btn btn-ghost"
phx-click="toggle_dropdown"
phx-target={@phx_target}
data-testid="dropdown-button"
@ -236,30 +236,6 @@ defmodule MvWeb.CoreComponents do
"""
end
@doc """
Renders a section in with a border similar to cards.
## Examples
<.form_section title={gettext("Personal Data")}>
<p>input</p>
</form_section>
"""
attr :title, :string, required: true
slot :inner_block, required: true
def form_section(assigns) do
~H"""
<section class="mb-6">
<h2 class="text-lg font-semibold mb-3">{@title}</h2>
<div class="border border-base-300 rounded-lg p-4 bg-base-100">
{render_slot(@inner_block)}
</div>
</section>
"""
end
@doc """
Renders an input with label and error messages.
@ -458,7 +434,7 @@ defmodule MvWeb.CoreComponents do
~H"""
<header class={[@actions != [] && "flex items-center justify-between gap-6", "pb-4", @class]}>
<div>
<h1 class="text-xl font-semibold leading-8">
<h1 class="text-lg font-semibold leading-8">
{render_slot(@inner_block)}
</h1>
<p :if={@subtitle != []} class="text-sm text-base-content/70">
@ -498,7 +474,7 @@ defmodule MvWeb.CoreComponents do
slot :col, required: true do
attr :label, :string
attr :class, :string
attr :col_click, :any, doc: "optional column-specific click handler that overrides row_click"
end
slot :action, doc: "the slot for showing user actions in the last table column"
@ -514,7 +490,7 @@ defmodule MvWeb.CoreComponents do
<table class="table table-zebra">
<thead>
<tr>
<th :for={col <- @col} class={Map.get(col, :class)}>{col[:label]}</th>
<th :for={col <- @col}>{col[:label]}</th>
<th :for={dyn_col <- @dynamic_cols}>
<.live_component
module={MvWeb.Components.SortHeaderComponent}
@ -534,34 +510,11 @@ defmodule MvWeb.CoreComponents do
<tr :for={row <- @rows} id={@row_id && @row_id.(row)}>
<td
:for={col <- @col}
phx-click={@row_click && @row_click.(row)}
class={
col_class = Map.get(col, :class)
classes = ["max-w-xs"]
classes =
if col_class == nil || (col_class && !String.contains?(col_class, "text-center")) do
["truncate" | classes]
else
classes
end
classes =
if @row_click do
["hover:cursor-pointer" | classes]
else
classes
end
classes =
if col_class do
[col_class | classes]
else
classes
end
Enum.join(classes, " ")
phx-click={
(col[:col_click] && col[:col_click].(@row_item.(row))) ||
(@row_click && @row_click.(row))
}
class={["max-w-xs truncate", (col[:col_click] || @row_click) && "hover:cursor-pointer"]}
>
{render_slot(col, @row_item.(row))}
</td>

View file

@ -44,7 +44,7 @@ defmodule MvWeb.Components.PaymentFilterComponent do
<button
type="button"
class={[
"btn gap-2",
"btn btn-ghost gap-2",
@paid_filter && "btn-active"
]}
phx-click="toggle_dropdown"

View file

@ -14,26 +14,20 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
@impl true
def render(assigns) do
assigns = assign(assigns, :field_type_label, &MvWeb.Translations.FieldTypes.label/1)
~H"""
<div id={@id}>
<.form_section title={gettext("Custom Fields")}>
<div class="flex">
<p class="text-sm text-base-content/70">
<.header>
{gettext("Custom Fields")}
<:subtitle>
{gettext("These will appear in addition to other data when adding new members.")}
</p>
<div class="ml-auto">
<.button
class="ml-auto"
variant="primary"
phx-click="new_custom_field"
phx-target={@myself}
>
</:subtitle>
<:actions>
<.button variant="primary" phx-click="new_custom_field" phx-target={@myself}>
<.icon name="hero-plus" /> {gettext("New Custom field")}
</.button>
</div>
</div>
</:actions>
</.header>
<%!-- Show form when creating or editing --%>
<div :if={@show_form} class="mb-8">
<.live_component
@ -61,18 +55,14 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
<:col :let={{_id, custom_field}} label={gettext("Name")}>{custom_field.name}</:col>
<:col :let={{_id, custom_field}} label={gettext("Value Type")}>
{@field_type_label.(custom_field.value_type)}
{custom_field.value_type}
</:col>
<:col :let={{_id, custom_field}} label={gettext("Description")}>
{custom_field.description}
</:col>
<:col
:let={{_id, custom_field}}
label={gettext("Show in overview")}
class="max-w-[9.375rem] text-center"
>
<:col :let={{_id, custom_field}} label={gettext("Show in Overview")}>
<span :if={custom_field.show_in_overview} class="badge badge-success">
{gettext("Yes")}
</span>
@ -90,9 +80,7 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
</:action>
<:action :let={{_id, custom_field}}>
<.link phx-click={
JS.push("prepare_delete", value: %{id: custom_field.id}, target: @myself)
}>
<.link phx-click={JS.push("prepare_delete", value: %{id: custom_field.id}, target: @myself)}>
{gettext("Delete")}
</.link>
</:action>
@ -162,7 +150,6 @@ defmodule MvWeb.CustomFieldLive.IndexComponent do
</div>
</div>
</dialog>
</.form_section>
</div>
"""
end

View file

@ -46,22 +46,22 @@ defmodule MvWeb.GlobalSettingsLive do
</.header>
<%!-- Club Settings Section --%>
<.form_section title={gettext("Club Settings")}>
<.header>
{gettext("Club Settings")}
</.header>
<.form for={@form} id="settings-form" phx-change="validate" phx-submit="save">
<div class="w-100">
<.input
field={@form[:club_name]}
type="text"
label={gettext("Association Name")}
required
/>
</div>
<.button phx-disable-with={gettext("Saving...")} variant="primary">
{gettext("Save Settings")}
</.button>
</.form>
</.form_section>
<%!-- Custom Fields Section --%>
<.live_component
module={MvWeb.CustomFieldLive.IndexComponent}

View file

@ -348,6 +348,25 @@ defmodule MvWeb.MemberLive.Form do
defp return_path("show", nil), do: ~p"/members"
defp return_path("show", member), do: ~p"/members/#{member.id}"
# -----------------------------------------------------------------
# Helper Components
# -----------------------------------------------------------------
# Renders a form section box with border and title.
attr :title, :string, required: true
slot :inner_block, required: true
defp form_section(assigns) do
~H"""
<section class="mb-6">
<h2 class="text-lg font-semibold mb-3">{@title}</h2>
<div class="border border-base-300 rounded-lg p-4 bg-base-100">
{render_slot(@inner_block)}
</div>
</section>
"""
end
# -----------------------------------------------------------------
# Helper Functions for Custom Fields
# -----------------------------------------------------------------

View file

@ -1082,6 +1082,16 @@ defmodule MvWeb.MemberLive.Index do
|> Enum.map(&format_member_email/1)
end
@doc """
Returns a JS command to toggle member selection when clicking the checkbox column.
Used as `col_click` handler to ensure clicking anywhere in the checkbox column
toggles the checkbox instead of navigating to the member details.
"""
def checkbox_column_click(member) do
JS.push("select_member", value: %{id: member.id})
end
# Formats a member's email in the format "First Last <email>"
# Used for copy_emails feature and mailto links to create email-client-friendly format.
def format_member_email(member) do

View file

@ -65,6 +65,7 @@
<!-- <:col :let={member} label="Id">{member.id}</:col> -->
<:col
:let={member}
col_click={&MvWeb.MemberLive.Index.checkbox_column_click/1}
label={
~H"""
<.input
@ -81,11 +82,7 @@
<.input
type="checkbox"
name={member.id}
phx-click="select_member"
phx-value-id={member.id}
checked={MapSet.member?(@selected_members, member.id)}
phx-capture-click
phx-stop-propagation
aria-label={gettext("Select member")}
role="checkbox"
/>

View file

@ -1,21 +0,0 @@
defmodule MvWeb.Translations.FieldTypes do
@moduledoc """
Helper module to dynamically translate field types.
## Features
- Can be used in templates to dynamically translate technical field type words to human friendly text
## Example
assigns = assign(assigns, :field_type_label, &MvWeb.Translations.FieldTypes.label/1)
In template:
<%= @field_type_label.(custom_field.value_type) %>
"""
use Gettext, backend: MvWeb.Gettext
@spec label(atom()) :: String.t()
def label(:string), do: gettext("Text")
def label(:integer), do: gettext("Number")
def label(:boolean), do: gettext("Yes/No-Selection")
def label(:date), do: gettext("Date")
def label(:email), do: gettext("E-Mail")
end

View file

@ -48,7 +48,7 @@ msgstr "Löschen"
#: lib/mv_web/live/user_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Edit"
msgstr "Bearbeiten"
msgstr "Bearbeite"
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
@ -214,7 +214,7 @@ msgstr "Falsche E-Mail oder Passwort"
#: lib/mv_web/live/member_live/form.ex
#, elixir-autogen, elixir-format
msgid "Member %{action} successfully"
msgstr "Mitglied erfolgreich %{action}"
msgstr "Mitglied %{action} erfolgreich"
#: lib/mv_web/controllers/auth_controller.ex
#, elixir-autogen, elixir-format
@ -419,8 +419,8 @@ msgstr "Administrator*innen-Hinweis"
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format
msgid "As an administrator, you can directly set a new password for this user."
msgstr "Als Administrator*in können Sie direkt ein neues Passwort für diese*n Benutzer*in setzen."
msgid "As an administrator, you can directly set a new password for this user using the same secure Ash Authentication system."
msgstr "Als Administrator*in können Sie direkt ein neues Passwort für diese*n Benutzer*in setzen, wobei das gleiche sichere Ash Authentication System verwendet wird."
#: lib/mv_web/live/user_live/form.ex
#, elixir-autogen, elixir-format
@ -658,7 +658,7 @@ msgstr "Um die Löschung zu bestätigen, gib bitte folgenden Text ein:"
#: lib/mv_web/live/custom_field_live/form_component.ex
#, elixir-autogen, elixir-format
msgid "Show in overview"
msgstr "In Übersicht anzeigen"
msgstr "In der Mitglieder-Übersicht anzeigen"
#: lib/mv_web/live/global_settings_live.ex
#, elixir-autogen, elixir-format
@ -904,96 +904,96 @@ msgstr "Mitglied erstellen"
#, 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"
msgstr[0] ""
msgstr[1] ""
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "About Contribution Types"
msgstr "Über Beitragsarten"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Amount"
msgstr "Betrag"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Back to Settings"
msgstr "Zurück zu den Einstellungen"
msgstr ""
#: lib/mv_web/live/contribution_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."
msgstr ""
#: 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"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Change Contribution Type"
msgstr "Beitragsart ändern"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Configure global settings for membership contributions."
msgstr "Globale Einstellungen für Mitgliedsbeiträge konfigurieren."
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Contribution Settings"
msgstr "Beitragseinstellungen"
msgstr "Beitrag"
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Contribution Start"
msgstr "Beitragsbeginn"
msgstr "Beitrag"
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Contribution Types"
msgstr "Beitragsarten"
msgstr "Beitrag"
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Contribution start"
msgstr "Beitragsbeginn"
msgstr "Beitrag"
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Contribution type"
msgstr "Beitragsart"
msgstr "Beitrag"
#: 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 interval (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."
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Contributions"
msgstr "Beiträge"
msgstr "Beitrag"
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Contributions for %{name}"
msgstr "Beiträge für %{name}"
msgstr "Beitrag"
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Current"
msgstr "Aktuell"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Default Contribution Type"
msgstr "Standard-Beitragsart"
msgstr ""
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
@ -1003,28 +1003,28 @@ msgstr "Löschen"
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Example: Member Contribution View"
msgstr "Beispiel: Ansicht Mitgliedsbeiträge"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Examples"
msgstr "Beispiele"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Family"
msgstr "Familie"
msgstr ""
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Fixed after creation. Members can only switch between types with the same interval."
msgstr "Festgelegt nach der Erstellung. Mitglieder können nur zwischen Beitragsarten mit gleichem Intervall wechseln."
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Generated periods"
msgstr "Generierte Zyklen"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format, fuzzy
@ -1036,29 +1036,29 @@ msgstr "Vereinsdaten"
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Half-yearly"
msgstr "Halbjährlich"
msgstr ""
#: 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"
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 "Ehrenamtlich"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Include joining period"
msgstr "Beitrittsdatum einbeziehen"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Interval"
msgstr "Zyklus"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format, fuzzy
@ -1068,240 +1068,240 @@ 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"
msgstr ""
#: 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."
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Mark as Paid"
msgstr "Als bezahlt markieren"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Mark as Suspended"
msgstr "Als pausiert markieren"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Mark as Unpaid"
msgstr "Als unbezahlt markieren"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Member Contributions"
msgstr "Mitgliedsbeiträge"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Member pays for the year they joined"
msgstr "Mitglied zahlt für das Beitrittsjahr"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Member pays from the joining month"
msgstr "Mitglied zahlt ab Beitrittsmonat"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Member pays from the next full quarter"
msgstr "Mitglied zahlt ab dem nächsten vollständigen Quartal"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Member pays from the next full year"
msgstr "Mitglied zahlt ab dem nächsten vollständigen Jahr"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Member since"
msgstr "Mitglied seit"
msgstr "Mitglieder"
#: 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."
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/contribution_settings_live.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Monthly"
msgstr "Monatlich"
msgstr "monatlich"
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Monthly Interval - Joining Period Included"
msgstr "Monatliches Intervall Beitrittszeitraum einbezogen"
msgstr ""
#: 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"
msgstr ""
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Name & Amount"
msgstr "Name & Betrag"
msgstr ""
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "New Contribution Type"
msgstr "Neue Beitragsart"
msgstr "Beitrag"
#: 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"
msgstr ""
#: lib/mv_web/live/contribution_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."
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Open Contributions"
msgstr "Offene Beiträge"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Paid via bank transfer"
msgstr "Bezahlt durch Überweisung"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/contribution_settings_live.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Preview Mockup"
msgstr "Vorschau"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/contribution_settings_live.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Quarterly"
msgstr "Vierteljährlich"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Quarterly Interval - Joining Period Excluded"
msgstr "Vierteljährliches Intervall Beitrittszeitraum nicht einbezogen"
msgstr ""
#: 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"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/contribution_settings_live.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Reduced"
msgstr "Reduziert"
msgstr ""
#: 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"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/contribution_settings_live.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Regular"
msgstr "Regulär"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Reopen"
msgstr "Wieder öffnen"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "See how the contribution periods will be displayed for an individual member. This example shows Maria Weber with multiple contribution periods."
msgstr "Beispielhafte Anzeige der Beitragsperioden für ein einzelnes Mitglied. In diesem Beispiel wird Maria Weber mit mehreren Zyklen angezeigt."
msgstr ""
#: 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"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Status"
msgstr "Status"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Student"
msgstr "Student"
msgstr ""
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Supporting Member"
msgstr "Fördermitglied"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Suspend"
msgstr "Pausieren"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Suspended"
msgstr "Pausiert"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "This contribution type is automatically assigned to all new members. Can be changed individually per member."
msgstr "Dieser Beitragstyp wird automatisch neuen Mitgliedern zugewiesen. Kann individuell angepasst werden."
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/contribution_settings_live.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."
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Time Period"
msgstr "Zeitraum"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Total Contributions"
msgstr "Gesamtbeiträge"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#, elixir-autogen, elixir-format
msgid "Unpaid"
msgstr "Unbezahlt"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "View Example Member"
msgstr "Beispielmitglied anzeigen"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "When active: Members pay from the period of their joining."
msgstr "Wenn aktiviert: Mitglieder zahlen ab dem Zeitraum ihres Beitritts."
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "When inactive: Members pay from the next full period after joining."
msgstr "Wenn deaktiviert: Mitglieder zahlen ab dem nächsten vollen Beitragszyklus nach dem Beitritt."
msgstr ""
#: 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?"
msgstr ""
#: lib/mv_web/live/contribution_period_live/show.ex
#: lib/mv_web/live/contribution_settings_live.ex
@ -1313,12 +1313,12 @@ msgstr "jährlich"
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Yearly Interval - Joining Period Excluded"
msgstr "Jährliches Intervall Beitrittszeitraum nicht einbezogen"
msgstr ""
#: lib/mv_web/live/contribution_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Yearly Interval - Joining Period Included"
msgstr "Jährliches Intervall Beitrittszeitraum einbezogen"
msgstr ""
#: lib/mv_web/live/components/field_visibility_dropdown_component.ex
#, elixir-autogen, elixir-format
@ -1363,7 +1363,7 @@ msgstr "Zurück zur Felderliste"
#: lib/mv_web/live/global_settings_live.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Custom field deleted successfully"
msgstr "Benutzerdefiniertes Feld erfolgreich gelöscht"
msgstr "Benutzerdefiniertes Feld erfolgreich %{action}"
#: lib/mv_web/live/custom_field_live/form_component.ex
#, elixir-autogen, elixir-format, fuzzy
@ -1405,31 +1405,6 @@ msgstr "Diese Felder können zusätzlich zu den normalen Daten ausgefüllt werde
msgid "Value Type"
msgstr "Wertetyp"
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Date"
msgstr "Datum"
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "E-Mail"
msgstr "E-Mail"
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Number"
msgstr "Zahl"
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Text"
msgstr "Textfeld"
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Yes/No-Selection"
msgstr "Ja/Nein-Auswahl"
#~ #: lib/mv_web/live/custom_field_live/show.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Auto-generated identifier (immutable)"

View file

@ -1405,28 +1405,3 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "Value Type"
msgstr ""
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Date"
msgstr ""
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "E-Mail"
msgstr ""
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Number"
msgstr ""
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Text"
msgstr ""
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Yes/No-Selection"
msgstr ""

View file

@ -1406,31 +1406,6 @@ msgstr ""
msgid "Value Type"
msgstr ""
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Date"
msgstr ""
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "E-Mail"
msgstr ""
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Number"
msgstr ""
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Text"
msgstr ""
#: lib/mv_web/translations/field_types.ex
#, elixir-autogen, elixir-format
msgid "Yes/No-Selection"
msgstr ""
#~ #: lib/mv_web/live/custom_field_live/show.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Auto-generated identifier (immutable)"

View file

@ -285,14 +285,9 @@ defmodule MvWeb.MemberLive.IndexTest do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members")
# Select two members
view
|> element("[phx-click='select_member'][phx-value-id='#{member1.id}']")
|> render_click()
view
|> element("[phx-click='select_member'][phx-value-id='#{member2.id}']")
|> render_click()
# Select two members by sending the select_member event directly
render_click(view, "select_member", %{"id" => member1.id})
render_click(view, "select_member", %{"id" => member2.id})
# Trigger copy_emails event
view |> element("#copy-emails-btn") |> render_click()
@ -336,10 +331,8 @@ defmodule MvWeb.MemberLive.IndexTest do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members")
# Select member with umlauts
view
|> element("[phx-click='select_member'][phx-value-id='#{member3.id}']")
|> render_click()
# Select member with umlauts by sending the select_member event directly
render_click(view, "select_member", %{"id" => member3.id})
# Trigger copy_emails event - should not crash
view |> element("#copy-emails-btn") |> render_click()
@ -355,10 +348,8 @@ defmodule MvWeb.MemberLive.IndexTest do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members")
# Select a member
view
|> element("[phx-click='select_member'][phx-value-id='#{member1.id}']")
|> render_click()
# Select a member by sending the select_member event directly
render_click(view, "select_member", %{"id" => member1.id})
# Delete the member from the database
Ash.destroy!(member1)
@ -379,14 +370,9 @@ defmodule MvWeb.MemberLive.IndexTest do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members")
# Select two members
view
|> element("[phx-click='select_member'][phx-value-id='#{member1.id}']")
|> render_click()
view
|> element("[phx-click='select_member'][phx-value-id='#{member2.id}']")
|> render_click()
# Select two members by sending the select_member event directly
render_click(view, "select_member", %{"id" => member1.id})
render_click(view, "select_member", %{"id" => member2.id})
# Get the socket state to verify the formatted email string
state = :sys.get_state(view.pid)
@ -415,10 +401,8 @@ defmodule MvWeb.MemberLive.IndexTest do
{:ok, view, _html} = live(conn, "/members")
# Select the test member
view
|> element("[phx-click='select_member'][phx-value-id='#{test_member.id}']")
|> render_click()
# Select the test member by sending the select_member event directly
render_click(view, "select_member", %{"id" => test_member.id})
# The format should be "Test Format <test.format@example.com>"
# We verify this by checking the flash shows 1 email was copied
@ -441,10 +425,8 @@ defmodule MvWeb.MemberLive.IndexTest do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members")
# Select a member
view
|> element("[phx-click='select_member'][phx-value-id='#{member1.id}']")
|> render_click()
# Select a member by sending the select_member event directly
render_click(view, "select_member", %{"id" => member1.id})
# Button should now be visible
assert has_element?(view, "#copy-emails-btn")
@ -457,10 +439,8 @@ defmodule MvWeb.MemberLive.IndexTest do
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members")
# Select a member
view
|> element("[phx-click='select_member'][phx-value-id='#{member1.id}']")
|> render_click()
# Select a member by sending the select_member event directly
render_click(view, "select_member", %{"id" => member1.id})
# Click copy button
view |> element("#copy-emails-btn") |> render_click()