189 lines
7.9 KiB
Plaintext
189 lines
7.9 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 – Mailing</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">👥 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 active">📧 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">
|
||
<h1 class="finance-title">📧 Mailing</h1>
|
||
|
||
<% if (success) { %><div class="alert alert-success"><%= success %></div><% } %>
|
||
<% if (error) { %><div class="alert alert-error"><%= error %></div><% } %>
|
||
|
||
<div class="finance-tabs">
|
||
<button class="ftab active" onclick="showTab('bulk', this)">📢 An alle aktiven Mitglieder</button>
|
||
<button class="ftab" onclick="showTab('single', this)">👤 An einzelnes Mitglied</button>
|
||
<button class="ftab" onclick="showTab('log', this)">
|
||
📋 Versandprotokoll
|
||
<% if (log.length > 0) { %><span style="margin-left:6px;background:#e0e7ff;color:var(--primary);padding:1px 7px;border-radius:10px;font-size:0.75rem"><%= log.length %></span><% } %>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- ===== TAB: AN ALLE ===== -->
|
||
<div class="ftab-content active" id="tab-bulk">
|
||
<div class="mailing-layout">
|
||
|
||
<!-- Formular -->
|
||
<div class="finance-card" style="flex:1">
|
||
<h3>E-Mail an alle aktiven Mitglieder (<%= members.length %>)</h3>
|
||
<form method="POST" action="/admin/mailing/send-all"
|
||
onsubmit="return confirm('E-Mail an <%= members.length %> aktive Mitglieder senden?')">
|
||
<div class="form-group" style="margin-top:16px">
|
||
<label>Betreff *</label>
|
||
<input type="text" name="subject" class="form-control"
|
||
placeholder="z.B. Wichtige Information zu deiner Mitgliedschaft" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>
|
||
<input type="checkbox" name="include_name" value="1" checked style="margin-right:6px">
|
||
Persönliche Anrede ("Hallo Max Mustermann,") einfügen
|
||
</label>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Nachricht *</label>
|
||
<textarea name="body" class="form-control mail-textarea" rows="10"
|
||
placeholder="Schreibe hier deine Nachricht..." required></textarea>
|
||
</div>
|
||
<div class="mail-preview-hint">
|
||
💡 Zeilenumbrüche werden automatisch als Absätze formatiert.
|
||
</div>
|
||
<div style="display:flex;gap:10px;margin-top:16px">
|
||
<button type="submit" class="btn btn-primary">📢 Jetzt an alle senden</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- Empfängerliste -->
|
||
<div class="finance-card mail-recipients">
|
||
<h3>Empfänger (<%= members.length %>)</h3>
|
||
<div class="recipients-list">
|
||
<% members.forEach(m => { %>
|
||
<div class="recipient-row">
|
||
<span class="recipient-name"><%= m.last_name %>, <%= m.first_name %></span>
|
||
<span class="recipient-email"><%= m.email %></span>
|
||
</div>
|
||
<% }) %>
|
||
<% if (members.length === 0) { %>
|
||
<p class="karte-empty">Keine aktiven Mitglieder.</p>
|
||
<% } %>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== TAB: EINZELN ===== -->
|
||
<div class="ftab-content" id="tab-single">
|
||
<div class="finance-card" style="max-width:680px">
|
||
<h3>E-Mail an einzelnes Mitglied</h3>
|
||
<form method="POST" action="/admin/mailing/send-one" style="margin-top:16px">
|
||
<div class="form-group">
|
||
<label>Mitglied *</label>
|
||
<select name="membership_id" class="form-control" required>
|
||
<option value="">– Mitglied wählen –</option>
|
||
<% members.forEach(m => { %>
|
||
<option value="<%= m.id %>"><%= m.last_name %>, <%= m.first_name %> · <%= m.email %></option>
|
||
<% }) %>
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Betreff *</label>
|
||
<input type="text" name="subject" class="form-control"
|
||
placeholder="Betreff der E-Mail" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Nachricht *</label>
|
||
<textarea name="body" class="form-control mail-textarea" rows="10"
|
||
placeholder="Schreibe hier deine Nachricht..." required></textarea>
|
||
</div>
|
||
<button type="submit" class="btn btn-primary">📧 E-Mail senden</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ===== TAB: LOG ===== -->
|
||
<div class="ftab-content" id="tab-log">
|
||
<div class="finance-card">
|
||
<h3>Versandprotokoll (letzte 50)</h3>
|
||
<% if (log.length === 0) { %>
|
||
<p class="karte-empty">Noch keine E-Mails gesendet.</p>
|
||
<% } else { %>
|
||
<div class="table-wrap" style="margin-top:12px">
|
||
<table class="admin-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Datum</th>
|
||
<th>Mitglied</th>
|
||
<th>Empfänger</th>
|
||
<th>Betreff</th>
|
||
<th>Typ</th>
|
||
<th>Status</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<% log.forEach(entry => { %>
|
||
<tr>
|
||
<td><small><%= new Date(entry.sent_at).toLocaleString('de-DE') %></small></td>
|
||
<td><%= entry.first_name ? entry.last_name + ', ' + entry.first_name : '–' %></td>
|
||
<td><small class="text-muted"><%= entry.recipient %></small></td>
|
||
<td><%= entry.subject %></td>
|
||
<td>
|
||
<span class="mail-type-badge mail-type-<%= entry.type %>">
|
||
<%= entry.type === 'bulk' ? '📢 Rundmail' : entry.type === 'direct' ? '👤 Direkt' : entry.type === 'renewal' ? '🔄 Verlängerung' : entry.type === 'renewal_auto' ? '⏰ Auto' : '📧 ' + entry.type %>
|
||
</span>
|
||
</td>
|
||
<td>
|
||
<span class="invoice-status <%= entry.status === 'sent' ? 'paid' : 'open' %>">
|
||
<%= entry.status === 'sent' ? '✅ Gesendet' : '❌ Fehler' %>
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
<% }) %>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<% } %>
|
||
</div>
|
||
</div>
|
||
|
||
</main>
|
||
</div>
|
||
|
||
<script>
|
||
function showTab(name, el) {
|
||
document.querySelectorAll('.ftab-content').forEach(t => t.classList.remove('active'));
|
||
document.querySelectorAll('.ftab').forEach(t => t.classList.remove('active'));
|
||
document.getElementById('tab-' + name).classList.add('active');
|
||
if (el) el.classList.add('active');
|
||
}
|
||
const hash = window.location.hash.replace('#','');
|
||
if (hash && document.getElementById('tab-' + hash)) showTab(hash);
|
||
</script>
|
||
</body>
|
||
</html>
|