545 lines
26 KiB
Plaintext
545 lines
26 KiB
Plaintext
<!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 member-detail-page">
|
||
<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/contracts" class="nav-link">📑 Verträge</a>
|
||
<a href="/admin/billing" class="nav-link">💶 Abrechnung</a>
|
||
<a href="/admin/finance" class="nav-link">📊 Finanzen</a>
|
||
<a href="/admin/mailing" class="nav-link">📧 Mailing</a>
|
||
<a href="/dokumentation/handbuch.docx" class="nav-link" target="_blank">❓ Hilfe</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' : member.status === 'pending' ? 'warning' : 'inactive' %>">
|
||
<%= member.status === 'active' ? '✅ Aktiv' : member.status === 'paused' ? '⏸ Pausiert' : member.status === 'pending' ? '⏳ Ausstehend' : '❌ Inaktiv' %>
|
||
</span>
|
||
<% if (member.status === 'pending') { %>
|
||
<form method="POST" action="/admin/members/<%= member.id %>/confirm" style="display:inline">
|
||
<button type="submit" class="btn btn-sm btn-success">✅ Manuell bestätigen</button>
|
||
</form>
|
||
<% } %>
|
||
<% if (member.is_minor) { %>
|
||
<span class="status-badge warning">⚠️ Minderjährig</span>
|
||
<% } %>
|
||
</div>
|
||
<div class="detail-header-actions">
|
||
<button class="btn btn-outline btn-sm" onclick="toggleModal('directMailModal')">📧 E-Mail senden</button>
|
||
<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>Vereinbarter Preis/Monat <small>(vertraglich)</small></label>
|
||
<div class="input-wrap" style="border-radius:6px">
|
||
<input type="number" name="agreed_price" step="0.01" min="0"
|
||
value="<%= member.agreed_price ? Number(member.agreed_price).toFixed(2) : '' %>"
|
||
disabled class="karte-input" style="border:none;padding:5px 0">
|
||
<span style="font-size:0.8rem;color:var(--text-muted);padding-right:8px">€</span>
|
||
</div>
|
||
</div>
|
||
<div class="karte-field">
|
||
<label>Vereinbarte Laufzeit <small>(Monate)</small></label>
|
||
<input type="number" name="agreed_duration" min="1"
|
||
value="<%= member.agreed_duration || '' %>"
|
||
disabled class="karte-input">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="karte-row">
|
||
<div class="karte-field">
|
||
<label>Startpaket (€) <small>(0 = erlassen)</small></label>
|
||
<input type="number" name="start_package_price" step="0.01" min="0"
|
||
value="<%= member.start_package_price != null ? Number(member.start_package_price).toFixed(2) : '35.00' %>"
|
||
disabled class="karte-input">
|
||
</div>
|
||
<div class="karte-field">
|
||
<label>Startpaket abgerechnet</label>
|
||
<input type="text"
|
||
value="<%= member.start_package_paid ? '✅ Ja' : '❌ Nein' %>"
|
||
disabled class="karte-input karte-readonly">
|
||
</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>
|
||
|
||
|
||
<!-- ===== KARTE 5: Rechnungshistorie ===== -->
|
||
<div class="karte">
|
||
<div class="karte-header">
|
||
<span class="karte-icon">🧾</span>
|
||
<h3>Rechnungshistorie</h3>
|
||
<span class="karte-header-sub"><%= invoices.length %> Rechnung(en)</span>
|
||
</div>
|
||
<div class="karte-body" style="padding:0">
|
||
<% if (invoices.length === 0) { %>
|
||
<p class="karte-empty" style="padding:20px">Noch keine Rechnungen vorhanden.</p>
|
||
<% } else { %>
|
||
<div class="invoice-history-wrap">
|
||
<table class="invoice-history-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Nr.</th>
|
||
<th>Periode</th>
|
||
<th>Betrag</th>
|
||
<th>Status</th>
|
||
<th>Datum</th>
|
||
<th>Aktion</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<% invoices.forEach(inv => { %>
|
||
<tr class="invoice-history-row">
|
||
<td class="invoice-nr">PF24-<%= String(inv.id).padStart(6,'0') %></td>
|
||
<td><strong><%= inv.period %></strong></td>
|
||
<td>
|
||
<% if (inv.status === 'cancelled') { %>
|
||
<span style="text-decoration:line-through;color:var(--text-muted)">
|
||
<%= Number(inv.amount).toFixed(2).replace('.', ',') %> €
|
||
</span>
|
||
<% } else { %>
|
||
<strong><%= Number(inv.amount).toFixed(2).replace('.', ',') %> €</strong>
|
||
<% } %>
|
||
</td>
|
||
<td>
|
||
<span class="invoice-status <%= inv.status === 'paid' ? 'paid' : inv.status === 'cancelled' ? 'cancelled' : 'open' %>">
|
||
<%= inv.status === 'paid' ? '✅ Bezahlt' : inv.status === 'cancelled' ? '🚫 Storniert' : '🔴 Offen' %>
|
||
</span>
|
||
</td>
|
||
<td><small class="text-muted"><%= new Date(inv.created_at).toLocaleDateString('de-DE') %></small></td>
|
||
<td>
|
||
<% if (inv.status === 'cancelled') { %>
|
||
<a href="/admin/billing/export/storno-pdf/<%= inv.id %>"
|
||
class="btn btn-sm btn-storno" target="_blank">🚫 Storno-PDF</a>
|
||
<% } else { %>
|
||
<a href="/admin/billing/export/pdf/<%= inv.id %>"
|
||
class="btn btn-sm btn-outline" target="_blank">📄 Rechnung</a>
|
||
<% } %>
|
||
</td>
|
||
</tr>
|
||
<% }) %>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<% } %>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ===== KARTE 5: Zugangskarte / NFC ===== -->
|
||
<div class="karte">
|
||
<div class="karte-header">
|
||
<span class="karte-icon">🔑</span>
|
||
<h3>Zugangskarte / NFC</h3>
|
||
<% if (member.card_issued) { %>
|
||
<span class="status-badge active" style="margin-left:auto">✅ Ausgegeben</span>
|
||
<% } else { %>
|
||
<span class="status-badge inactive" style="margin-left:auto">⚠️ Nicht ausgegeben</span>
|
||
<% } %>
|
||
</div>
|
||
<div class="karte-body">
|
||
|
||
<!-- Access Token -->
|
||
<div class="karte-row">
|
||
<div class="karte-field karte-field-full">
|
||
<label>Access Token <small>(auf NFC-Karte schreiben)</small></label>
|
||
<div class="token-wrap">
|
||
<code class="token-display"><%= member.access_token || '–' %></code>
|
||
<form method="POST" action="/admin/members/<%= member.id %>/regenerate-token"
|
||
onsubmit="return confirm('Token neu generieren? Die alte Karte funktioniert dann nicht mehr!')">
|
||
<button type="submit" class="btn btn-sm btn-warning token-regen-btn"
|
||
title="Neuen Token generieren (z.B. bei Kartenverlust)">
|
||
🔄 Neu
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- NFC UID -->
|
||
<div class="karte-row">
|
||
<div class="karte-field karte-field-full">
|
||
<label>NFC Karten-UID <small>(vom Lesegerät auslesen)</small></label>
|
||
<form method="POST" action="/admin/members/<%= member.id %>/update-nfc"
|
||
id="nfcForm" style="display:flex;gap:8px;align-items:flex-start">
|
||
<input type="text" name="nfc_uid"
|
||
value="<%= member.nfc_uid || '' %>"
|
||
placeholder="z.B. A1:B2:C3:D4"
|
||
class="karte-input karte-iban"
|
||
style="text-transform:uppercase;flex:1">
|
||
<button type="submit" class="btn btn-sm btn-primary" style="white-space:nowrap;margin-top:1px">
|
||
💾 Speichern
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<% if (member.card_issued_at) { %>
|
||
<div class="karte-row">
|
||
<div class="karte-field karte-field-full">
|
||
<label>Karte ausgegeben am</label>
|
||
<input type="text"
|
||
value="<%= new Date(member.card_issued_at).toLocaleDateString('de-DE') %>"
|
||
disabled class="karte-input karte-readonly">
|
||
</div>
|
||
</div>
|
||
<% } %>
|
||
|
||
<!-- Info Box -->
|
||
<div class="nfc-info-box">
|
||
<strong>ℹ️ So wird die Karte eingerichtet:</strong>
|
||
<ol>
|
||
<li>Access Token mit NFC-Schreiber auf die Karte schreiben</li>
|
||
<li>Karten-UID mit dem Lesegerät auslesen und hier eintragen</li>
|
||
<li>Beim Zutritt: Lesegerät prüft UID + Token gegen die Datenbank</li>
|
||
</ol>
|
||
</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>
|
||
|
||
<!-- Modal: Direkte E-Mail -->
|
||
<div class="modal-overlay hidden" id="directMailModal">
|
||
<div class="modal">
|
||
<div class="modal-header">
|
||
<h3>E-Mail an <%= member.first_name %> <%= member.last_name %></h3>
|
||
<button onclick="toggleModal('directMailModal')" class="modal-close">✕</button>
|
||
</div>
|
||
<form method="POST" action="/admin/mailing/send-one">
|
||
<input type="hidden" name="membership_id" value="<%= member.id %>">
|
||
<div class="form-group">
|
||
<label>Empfänger</label>
|
||
<input type="text" value="<%= member.email %>" class="form-control" disabled>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Betreff *</label>
|
||
<input type="text" name="subject" class="form-control" required placeholder="Betreff">
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Nachricht *</label>
|
||
<textarea name="body" class="form-control" rows="8" required
|
||
placeholder="Schreibe hier deine Nachricht..."></textarea>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" onclick="toggleModal('directMailModal')" class="btn btn-outline">Abbrechen</button>
|
||
<button type="submit" class="btn btn-primary">📧 Senden</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</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>
|