Vertragsverwaltung_Plusfit24/views/admin/member-detail.ejs
2026-03-27 12:02:39 +00:00

337 lines
16 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PlusFit24 Mitglied #<%= member.id %></title>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/style.css">
</head>
<body class="admin-body">
<div class="admin-layout">
<aside class="admin-sidebar">
<div class="logo admin-logo">Plusfit<span>24</span></div>
<nav class="admin-nav">
<a href="/admin" class="nav-link">📋 Tarife</a>
<a href="/admin#kategorien" class="nav-link">🏷️ Kategorien</a>
<a href="/admin#mitglieder" class="nav-link active">👥 Mitglieder</a>
<a href="/admin#einstellungen" class="nav-link">⚙️ Einstellungen</a>
</nav>
<div class="sidebar-footer">
<span>👤 <%= admin %></span>
<a href="/admin/logout" class="logout-link">Abmelden</a>
</div>
</aside>
<main class="admin-main">
<div class="detail-header">
<a href="/admin#mitglieder" class="btn btn-outline btn-sm">← Zurück</a>
<div class="detail-header-title">
<h1><%= member.first_name %> <%= member.last_name %></h1>
<span class="member-id-badge">Mitglied #<%= member.id %></span>
<span class="status-badge <%= member.status === 'active' ? 'active' : (member.status === 'paused' ? 'warning' : 'inactive') %>">
<%= member.status === 'active' ? '✅ Aktiv' : member.status === 'paused' ? '⏸ Pausiert' : '❌ Inaktiv' %>
</span>
<% if (member.is_minor) { %>
<span class="status-badge warning">⚠️ Minderjährig</span>
<% } %>
</div>
<div class="detail-header-actions">
<button class="btn btn-primary" id="editBtn" onclick="enableEdit()">✏️ Bearbeiten</button>
<button class="btn btn-success hidden" id="saveBtn" form="memberForm">💾 Speichern</button>
<button class="btn btn-outline hidden" id="cancelBtn" onclick="cancelEdit()">✕ Abbrechen</button>
</div>
</div>
<% if (success) { %><div class="alert alert-success"><%= success %></div><% } %>
<% if (error) { %><div class="alert alert-error"><%= error %></div><% } %>
<form method="POST" action="/admin/members/<%= member.id %>/update" id="memberForm">
<div class="karteikarte-grid">
<!-- ===== KARTE 1: Persönliche Daten ===== -->
<div class="karte">
<div class="karte-header"><span class="karte-icon">👤</span><h3>Persönliche Daten</h3></div>
<div class="karte-body">
<div class="karte-row">
<div class="karte-field">
<label>Anrede</label>
<select name="salutation" disabled class="karte-input">
<option value="Herr" <%= member.salutation === 'Herr' ? 'selected' : '' %>>Herr</option>
<option value="Frau" <%= member.salutation === 'Frau' ? 'selected' : '' %>>Frau</option>
<option value="Keine Angabe"<%= member.salutation === 'Keine Angabe'? 'selected' : '' %>>Keine Angabe</option>
</select>
</div>
<div class="karte-field">
<label>Titel</label>
<input type="text" name="title" value="<%= member.title || '' %>" disabled class="karte-input">
</div>
</div>
<div class="karte-row">
<div class="karte-field">
<label>Vorname</label>
<input type="text" name="first_name" value="<%= member.first_name %>" disabled class="karte-input">
</div>
<div class="karte-field">
<label>Nachname</label>
<input type="text" name="last_name" value="<%= member.last_name %>" disabled class="karte-input">
</div>
</div>
<div class="karte-row">
<div class="karte-field">
<label>Geburtsdatum</label>
<input type="date" name="birth_date" value="<%= member.birth_date ? new Date(member.birth_date).toISOString().split('T')[0] : '' %>" disabled class="karte-input">
</div>
<div class="karte-field">
<label>Telefon</label>
<input type="tel" name="phone" value="<%= member.phone || '' %>" disabled class="karte-input">
</div>
</div>
<div class="karte-row">
<div class="karte-field karte-field-full">
<label>E-Mail</label>
<input type="email" name="email" value="<%= member.email %>" disabled class="karte-input">
</div>
</div>
</div>
</div>
<!-- ===== KARTE 2: Adresse ===== -->
<div class="karte">
<div class="karte-header"><span class="karte-icon">📍</span><h3>Adresse</h3></div>
<div class="karte-body">
<div class="karte-row">
<div class="karte-field karte-field-full">
<label>Straße, Hausnummer</label>
<input type="text" name="street" value="<%= member.street %>" disabled class="karte-input">
</div>
</div>
<div class="karte-row">
<div class="karte-field karte-field-full">
<label>Adresszusatz</label>
<input type="text" name="address_addition" value="<%= member.address_addition || '' %>" disabled class="karte-input">
</div>
</div>
<div class="karte-row">
<div class="karte-field" style="max-width:140px">
<label>PLZ</label>
<input type="text" name="zip" value="<%= member.zip %>" disabled class="karte-input">
</div>
<div class="karte-field">
<label>Ort</label>
<input type="text" name="city" value="<%= member.city %>" disabled class="karte-input">
</div>
</div>
</div>
</div>
<!-- ===== KARTE 3: Vertrag ===== -->
<div class="karte">
<div class="karte-header"><span class="karte-icon">📄</span><h3>Vertrag</h3></div>
<div class="karte-body">
<div class="karte-row">
<div class="karte-field karte-field-full">
<label>Tarif</label>
<select name="tariff_id" disabled class="karte-input">
<% tariffs.forEach(t => { %>
<option value="<%= t.id %>" <%= member.tariff_id === t.id ? 'selected' : '' %>>
<%= t.name %> <%= Number(t.price_monthly).toFixed(2) %>€/Monat
</option>
<% }) %>
</select>
</div>
</div>
<div class="karte-row">
<div class="karte-field">
<label>Abschlussdatum</label>
<input type="text" value="<%= member.signup_date ? new Date(member.signup_date).toLocaleDateString('de-DE') : '' %>" disabled class="karte-input karte-readonly">
</div>
<div class="karte-field">
<label>Vertragsbeginn</label>
<input type="text" value="<%= member.contract_start ? new Date(member.contract_start).toLocaleDateString('de-DE') : '' %>" disabled class="karte-input karte-readonly">
</div>
</div>
<div class="karte-row">
<div class="karte-field">
<label>Vertragsende</label>
<input type="text" value="<%= member.contract_end ? new Date(member.contract_end).toLocaleDateString('de-DE') : '' %>" disabled class="karte-input karte-readonly">
</div>
<div class="karte-field">
<label>Eff. Ende <small>(inkl. Auszeit)</small></label>
<input type="text" value="<%= member.effective_end ? new Date(member.effective_end).toLocaleDateString('de-DE') : '' %>" disabled class="karte-input karte-readonly">
</div>
</div>
<div class="karte-row">
<div class="karte-field">
<label>Erste Zahlung am</label>
<input type="text" value="<%= member.first_payment_date ? new Date(member.first_payment_date).toLocaleDateString('de-DE') : '' %>" disabled class="karte-input karte-readonly">
</div>
<div class="karte-field">
<label>Erster Betrag</label>
<input type="text" value="<%= member.first_payment_amt ? Number(member.first_payment_amt).toFixed(2) + ' €' : '' %>" disabled class="karte-input karte-readonly">
</div>
</div>
<div class="karte-row">
<div class="karte-field">
<label>Status</label>
<select name="status" disabled class="karte-input">
<option value="active" <%= member.status === 'active' ? 'selected' : '' %>>✅ Aktiv</option>
<option value="inactive" <%= member.status === 'inactive' ? 'selected' : '' %>>❌ Inaktiv</option>
<option value="paused" <%= member.status === 'paused' ? 'selected' : '' %>>⏸ Pausiert</option>
</select>
</div>
<div class="karte-field">
<label>Auszeit gesamt</label>
<input type="text" value="<%= member.pause_months_total || 0 %> Monat(e)" disabled class="karte-input karte-readonly">
</div>
</div>
<!-- Auszeiten Tabelle -->
<div class="auszeit-section">
<div class="auszeit-header">
<span class="auszeit-title">⏸ Auszeiten</span>
</div>
<% if (pauses.length === 0) { %>
<p class="karte-empty" id="noPausesMsg">Keine Auszeiten eingetragen.</p>
<% } else { %>
<table class="pause-table">
<thead>
<tr>
<th>Von</th>
<th>Bis</th>
<th>Monate</th>
<th>Grund</th>
<th>Eingetragen am</th>
<th class="edit-only hidden">Aktion</th>
</tr>
</thead>
<tbody>
<% pauses.forEach(p => { %>
<tr>
<td><%= new Date(p.pause_start).toLocaleDateString('de-DE') %></td>
<td><%= new Date(p.pause_end).toLocaleDateString('de-DE') %></td>
<td><strong><%= p.pause_months %></strong></td>
<td><%= p.reason || '' %></td>
<td><%= new Date(p.created_at).toLocaleDateString('de-DE') %></td>
<td class="edit-only hidden">
<form method="POST" action="/admin/members/<%= member.id %>/pauses/<%= p.id %>/delete"
onsubmit="return confirm('Auszeit wirklich löschen?')">
<button type="submit" class="btn btn-sm btn-danger">🗑</button>
</form>
</td>
</tr>
<% }) %>
</tbody>
</table>
<% } %>
<!-- Neue Auszeit nur im Bearbeiten-Modus sichtbar -->
<div class="neue-auszeit hidden" id="neueAuszeit">
<div class="neue-auszeit-title">+ Neue Auszeit eintragen</div>
<div class="auszeit-form-row">
<div class="karte-field">
<label>Von *</label>
<input type="date" name="pause_start" form="auszeitForm" required class="karte-input">
</div>
<div class="karte-field">
<label>Bis *</label>
<input type="date" name="pause_end" form="auszeitForm" required class="karte-input">
</div>
<div class="karte-field">
<label>Grund</label>
<input type="text" name="reason" form="auszeitForm" class="karte-input" placeholder="z.B. Urlaub, Verletzung...">
</div>
<div class="karte-field" style="max-width:120px; justify-content:flex-end; padding-top:22px">
<button type="submit" form="auszeitForm" class="btn btn-primary">Speichern</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ===== KARTE 4: Bankdaten ===== -->
<div class="karte">
<div class="karte-header"><span class="karte-icon">🏦</span><h3>Bankdaten / SEPA</h3></div>
<div class="karte-body">
<div class="karte-row">
<div class="karte-field">
<label>Geldinstitut</label>
<input type="text" name="bank_name" value="<%= member.bank_name || '' %>" disabled class="karte-input">
</div>
<div class="karte-field">
<label>Kontoinhaber</label>
<input type="text" name="account_holder" value="<%= member.account_holder || '' %>" disabled class="karte-input">
</div>
</div>
<div class="karte-row">
<div class="karte-field">
<label>SEPA akzeptiert</label>
<input type="text" value="<%= member.sepa_accepted ? '✅ Ja' : '❌ Nein' %>" disabled class="karte-input karte-readonly">
</div>
<div class="karte-field">
<label>AGB akzeptiert</label>
<input type="text" value="<%= member.agb_accepted ? '✅ Ja' : '❌ Nein' %>" disabled class="karte-input karte-readonly">
</div>
</div>
<div class="karte-row">
<div class="karte-field karte-field-full">
<label>IBAN</label>
<input type="text" name="iban" id="ibanInput"
value="<%= member.iban ? member.iban.replace(/(.{4})/g, '$1 ').trim() : '' %>"
disabled class="karte-input karte-iban" maxlength="34" autocomplete="off">
<div class="iban-message" id="ibanMessage"></div>
</div>
</div>
<% if (member.is_minor) { %>
<div class="karte-row">
<div class="karte-field karte-field-full">
<label>Einverständniserklärung (Erziehungsberechtigte)</label>
<input type="text" value="<%= member.guardian_consent ? '✅ Vorhanden' : '❌ Fehlt' %>" disabled class="karte-input karte-readonly">
</div>
</div>
<% } %>
</div>
</div>
</div><!-- end karteikarte-grid -->
</form>
<!-- Auszeit Form (außerhalb von memberForm!) -->
<form id="auszeitForm" method="POST" action="/admin/members/<%= member.id %>/pauses/add"></form>
</main>
</div>
<script src="/js/iban.js"></script>
<script>
const editableFields = document.querySelectorAll('.karte-input:not(.karte-readonly)');
function enableEdit() {
editableFields.forEach(f => f.removeAttribute('disabled'));
document.getElementById('editBtn').classList.add('hidden');
document.getElementById('saveBtn').classList.remove('hidden');
document.getElementById('cancelBtn').classList.remove('hidden');
document.querySelectorAll('.karte').forEach(k => k.classList.add('edit-mode'));
// Auszeit-Bereich einblenden
document.getElementById('neueAuszeit').classList.remove('hidden');
document.querySelectorAll('.edit-only').forEach(el => el.classList.remove('hidden'));
// IBAN Validierung
const ibanInput = document.getElementById('ibanInput');
if (ibanInput) attachIBANValidation(ibanInput, null, document.getElementById('ibanMessage'));
}
function cancelEdit() {
window.location.reload();
}
</script>
</body>
</html>