allow final usertype changes; Fixes #954
Some checks failed
CI/CD Pipeline / test (push) Has started running
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled

This commit is contained in:
2025-05-03 18:26:19 +02:00
parent 7bd863ddf1
commit e6895c8cf1
7 changed files with 408 additions and 176 deletions

View File

@ -4,8 +4,7 @@
{% block content %}
<div class="max-w-screen-lg w-full">
{% if "admin" in loggedin_user.roles or "Vorstand" in loggedin_user.roles %}
<a href="/admin/user"
class="link link-primary link-no-underline">&larr; Userverwaltung</a>
<a href="/admin/user" class="link link-primary link-no-underline">&larr; Userverwaltung</a>
{% endif %}
<h1 class="h1">{{ user.name }}</h1>
<div class="grid sm:grid-cols-2 gap-3">
@ -82,7 +81,8 @@
</div>
<div class="py-3">
{% if user.membership_pdf %}
<a href="/admin/user/{{ user.id }}/membership" class="link link-primary link-no-underline">Beitrittserklärung herunterladen &darr;</a>
<a href="/admin/user/{{ user.id }}/membership"
class="link link-primary link-no-underline">Beitrittserklärung herunterladen &darr;</a>
{% else %}
⚠️ Aktuell gibt's keine Beitrittserklärung 😢
{% if allowed_to_edit %}
@ -103,8 +103,8 @@
<div class="py-3">
<div class="mt-3 text-right">
<button type="button"
onclick="document.getElementById('change-member-type').showModal()"
class="btn btn-dark">Mitgliedsstatus ändern</button>
onclick="document.getElementById('change-member-type').showModal()"
class="btn btn-dark">Mitgliedsstatus ändern</button>
<a href="/admin/user/{{ user.id }}/delete"
class="btn btn-alert"
onclick="return confirm('Ist {{ user.name }} wirklich aus dem Verein ausgetreten?');">
@ -113,119 +113,158 @@
</a>
</div>
</div>
<dialog id="change-member-type"
class="max-w-screen-sm w-full dark:bg-primary-600 dark:text-white rounded-md"
onclick="document.getElementById('change-member-type').close()">
<div onclick="event.stopPropagation();" class="p-3">
<button type="button"
onclick="document.getElementById('change-member-type').close()"
title="Schließen"
class="sidebar-close border-0 bg-primary-100 focus:bg-primary-50 text-black flex items-center justify-center transform rotate-45 absolute right-0 mr-3">
<svg class="inline h-5 w-5"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"></path>
</svg>
</button>
<div class="mt-8">
<form action="/admin/user/{{ user.id }}/change-membertype"
method="post"
enctype="multipart/form-data"
class="grid gap-3">
<div>
<label for="membertype" class="text-sm text-gray-600 dark:text-gray-100">Mitgliedsstatus</label>
<select name="membertype" id="membertype" class="input rounded-md ">
<option selected="" value="regular">Reguläres Vereinsmitglied</option>
<option value="unterstuetzend">Unterstützendes Vereinsmitglied</option>
<option value="foerdernd">Förderndes Vereinsmitglied</option>
</select>
</div>
<input value="Ändern"
type="submit"
class="btn btn-primary" />
</form>
<dialog id="change-member-type"
class="max-w-screen-sm w-full dark:bg-primary-600 dark:text-white rounded-md"
onclick="document.getElementById('change-member-type').close()">
<div onclick="event.stopPropagation();" class="p-3">
<button type="button"
onclick="document.getElementById('change-member-type').close()"
title="Schließen"
class="sidebar-close border-0 bg-primary-100 focus:bg-primary-50 text-black flex items-center justify-center transform rotate-45 absolute right-0 mr-3">
<svg class="inline h-5 w-5"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"></path>
</svg>
</button>
<div class="mt-8">
<form action="/admin/user/{{ user.id }}/change-membertype"
method="post"
enctype="multipart/form-data"
class="grid gap-3">
<div>
<label for="membertype" class="text-sm text-gray-600 dark:text-gray-100">Mitgliedsstatus</label>
<select name="membertype" id="membertype" class="input rounded-md ">
<option selected="" value="regular">Reguläres Vereinsmitglied</option>
<option value="unterstuetzend">Unterstützendes Vereinsmitglied</option>
<option value="foerdernd">Förderndes Vereinsmitglied</option>
</select>
</div>
<input value="Ändern" type="submit" class="btn btn-primary" />
</form>
</div>
</div>
</div>
</dialog>
</dialog>
{% endif %}
{% elif "Scheckbuch" in member %}
{% if allowed_to_edit %}
<div class="grid gap-3 pb-3">
<div class="max-h-60 overflow-y-scroll">
{% for log in logbook %}
{{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index, allowed_to_edit=false) }}
{% endfor %}
<div class="grid gap-3 pb-3">
<div class="max-h-60 overflow-y-scroll">
{% for log in logbook %}
{{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index, allowed_to_edit=false) }}
{% endfor %}
</div>
</div>
{% endif %}
{% elif "SchnupperInterest" in member %}
{% if allowed_to_edit %}
<div class="grid pt-3">
<a href="/admin/user/{{ user.id }}/schnupperinterest-to-scheckbuch"
class="btn btn-dark"
onclick="return confirm('Willst du \'{{ user.name }}\' wirklich auf ein Scheckbuch umwandeln?');">In Scheckbuch umwandeln</a>
</div>
<div class="grid pt-3">
<a href="/admin/user/{{ user.id }}/schnupperinterest-to-schnupperant"
class="btn btn-dark"
onclick="return confirm('Hat sich \'{{ user.name }}\' wirklich zum Kurs angemeldet?');">Zum Schnupperkurs angemeldet</a>
</div>
<div class="grid pt-3">
<a href="/admin/user/{{ user.id }}/delete"
class="btn btn-alert"
onclick="return confirm('Ist {{ user.name }} wirklich nicht mehr am Schnupperkurs interessiert?');">
{% include "includes/delete-icon" %}
Daten löschen
</a>
</div>
</div>
{% endif %}
{% elif "Schnupperant" in member %}
{% if allowed_to_edit %}
<div class="grid pt-3">
<a href="/admin/user/{{ user.id }}/schnupperant-to-scheckbuch" class="btn btn-dark"
onclick="return confirm('Willst du \'{{ user.name }}\' wirklich auf ein Scheckbuch umwandeln?');">In Scheckbuch umwandeln</a>
</div>
{% endif %}
{% endif %}
{% if "Scheckbuch" in member or "Schnupperant" in member %}
{% if allowed_to_edit %}
<div class="grid gap-3 pb-3 mt-3">
<button type="button"
onclick="document.getElementById('call-for-action').showModal()"
class="btn btn-primary">Zu Vereinsmitglied umwandeln</button>
</div>
<dialog id="call-for-action"
class="max-w-screen-sm w-full dark:bg-primary-600 dark:text-white rounded-md"
onclick="document.getElementById('call-for-action').close()">
<div onclick="event.stopPropagation();" class="p-3">
<button type="button"
onclick="document.getElementById('call-for-action').close()"
title="Schließen"
class="sidebar-close border-0 bg-primary-100 focus:bg-primary-50 text-black flex items-center justify-center transform rotate-45 absolute right-0 mr-3">
<svg class="inline h-5 w-5"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"></path>
</svg>
</button>
<div class="mt-8">
{% if "Scheckbuch" in member %}
{% set action = 'scheckbook-to-regular' %}
{% elif "Schnupperant" in member %}
{% set action = 'schnupperant-to-regular' %}
{% endif %}
<form action="/admin/user/{{ user.id }}/{{ action }}"
method="post"
enctype="multipart/form-data"
class="grid gap-3">
<div>
<label for="membertype" class="text-sm text-gray-600 dark:text-gray-100">Mitgliedstyp</label>
<select name="membertype" id="membertype" class="input rounded-md ">
<option selected="" value="regular">Reguläres Vereinsmitglied</option>
<option value="unterstuetzend">Unterstützendes Vereinsmitglied</option>
<option value="foerdernd">Förderndes Vereinsmitglied</option>
</select>
</div>
{{ macros::input(label='Mitglied seit', name='member_since', type="date", value=now() | date(), required=true) }}
{{ macros::input(label='Geburtsdatum', name='birthdate', type="date", value=user.birthdate, required=true) }}
{{ macros::input(label='Telefonnummer', name='phone', type="text", value=user.phone, required=true) }}
{{ macros::input(label='Adresse', name='address', type="text", value=user.address, required=true) }}
{{ macros::input(label='Beitrittserklärung', name='membership_pdf', type="file", accept='application/pdf', required=true) }}
<input value="Als neues, reguläres Mitglied anlegen"
type="submit"
class="btn btn-primary" />
</form>
</div>
<div class="grid pt-3">
<a href="/admin/user/{{ user.id }}/schnupperant-to-schnupperinterest"
class="btn btn-dark"
onclick="return confirm('Hat sich \'{{ user.name }}\' wirklich vom Schnupperkurs abgemeldet?');">Vom Kurs abgemeldet</a>
</div>
<div class="grid pt-3">
<a href="/admin/user/{{ user.id }}/schnupperant-to-scheckbuch"
class="btn btn-dark"
onclick="return confirm('Willst du \'{{ user.name }}\' wirklich auf ein Scheckbuch umwandeln?');">In Scheckbuch umwandeln</a>
</div>
<div class="grid pt-3">
<a href="/admin/user/{{ user.id }}/delete"
class="btn btn-alert"
onclick="return confirm('Ist {{ user.name }} wirklich nicht mehr am Schnupperkurs interessiert?');">
{% include "includes/delete-icon" %}
Daten löschen
</a>
</div>
</dialog>
{% endif %}
{% endif %}
</div>
{% if "Scheckbuch" in member or "Schnupperant" in member %}
{% if allowed_to_edit %}
<div class="grid gap-3 pb-3 mt-3">
<button type="button"
onclick="document.getElementById('call-for-action').showModal()"
class="btn btn-primary">Zu Vereinsmitglied umwandeln</button>
</div>
<dialog id="call-for-action"
class="max-w-screen-sm w-full dark:bg-primary-600 dark:text-white rounded-md"
onclick="document.getElementById('call-for-action').close()">
<div onclick="event.stopPropagation();" class="p-3">
<button type="button"
onclick="document.getElementById('call-for-action').close()"
title="Schließen"
class="sidebar-close border-0 bg-primary-100 focus:bg-primary-50 text-black flex items-center justify-center transform rotate-45 absolute right-0 mr-3">
<svg class="inline h-5 w-5"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"></path>
</svg>
</button>
<div class="mt-8">
{% if "Scheckbuch" in member %}
{% set action = "scheckbook-to-regular" %}
{% elif "Schnupperant" in member %}
{% set action = "schnupperant-to-regular" %}
{% endif %}
<form action="/admin/user/{{ user.id }}/{{ action }}"
method="post"
enctype="multipart/form-data"
class="grid gap-3">
<div>
<label for="membertype" class="text-sm text-gray-600 dark:text-gray-100">Mitgliedstyp</label>
<select name="membertype" id="membertype" class="input rounded-md ">
<option selected="" value="regular">Reguläres Vereinsmitglied</option>
<option value="unterstuetzend">Unterstützendes Vereinsmitglied</option>
<option value="foerdernd">Förderndes Vereinsmitglied</option>
</select>
</div>
{{ macros::input(label='Mitglied seit', name='member_since', type="date", value=now() | date(), required=true) }}
{{ macros::input(label='Geburtsdatum', name='birthdate', type="date", value=user.birthdate, required=true) }}
{{ macros::input(label='Telefonnummer', name='phone', type="text", value=user.phone, required=true) }}
{{ macros::input(label='Adresse', name='address', type="text", value=user.address, required=true) }}
{{ macros::input(label='Beitrittserklärung', name='membership_pdf', type="file", accept='application/pdf', required=true) }}
<input value="Als neues, reguläres Mitglied anlegen"
type="submit"
class="btn btn-primary" />
</form>
</div>
</div>
</dialog>
<div class="grid pt-3">
<a href="/admin/user/{{ user.id }}/delete"
class="btn btn-alert"
onclick="return confirm('Willst du die Daten von {{ user.name }} wirklich? Seine restlichen Scheckbuch-Ausfahrten entfallen damit...');">
{% include "includes/delete-icon" %}
Daten löschen
</a>
</div>
{% endif %}
{% endif %}
</div>
</div>
{% if is_clubmember %}
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5">

View File

@ -199,8 +199,8 @@ function setChoiceByLabel(choicesInstance, label) {
readonly />
{% if allowed_to_edit %}
<button type="button" class="btn btn-dark rounded-l-none-important edit-js">
{% include "includes/pencil" %}
<span class="sr-only">Bearbeiten</span>
{% include "includes/pencil" %}
<span class="sr-only">Bearbeiten</span>
</button>
<input value="x"
type="reset"
@ -248,8 +248,8 @@ function setChoiceByLabel(choicesInstance, label) {
</select>
{% if allowed_to_edit %}
<button type="button" class="btn btn-dark rounded-l-none-important edit-js">
{% include "includes/pencil" %}
<span class="sr-only">Bearbeiten</span>
{% include "includes/pencil" %}
<span class="sr-only">Bearbeiten</span>
</button>
<input value="x"
type="reset"