164 lines
5.8 KiB
HTML
164 lines
5.8 KiB
HTML
|
|
{% extends "v2/base.html" %}
|
||
|
|
|
||
|
|
{% block title %}Meine Abos — GWÖ-Antragsprüfer{% endblock %}
|
||
|
|
|
||
|
|
{% set v2_active_nav = "abos" %}
|
||
|
|
|
||
|
|
{% block head_extra %}
|
||
|
|
<style>
|
||
|
|
.abo-form {
|
||
|
|
display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-end;
|
||
|
|
margin-bottom: 24px; max-width: 760px;
|
||
|
|
padding: 12px 14px; border: 1px solid var(--ecg-border);
|
||
|
|
border-radius: 4px; background: var(--ecg-bg-subtle);
|
||
|
|
}
|
||
|
|
.abo-form label {
|
||
|
|
display: block; font-family: var(--font-mono); font-size: 11px;
|
||
|
|
text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.7;
|
||
|
|
margin-bottom: 4px;
|
||
|
|
}
|
||
|
|
.abo-form select, .abo-form input[type="text"] {
|
||
|
|
font-family: var(--font-mono); font-size: 13px;
|
||
|
|
padding: 6px 8px; border: 1px solid var(--ecg-border);
|
||
|
|
border-radius: 4px; background: var(--ecg-card-bg); color: var(--ecg-dark);
|
||
|
|
}
|
||
|
|
.abo-form .submit {
|
||
|
|
font-family: var(--font-display); font-size: 12px; font-weight: 700;
|
||
|
|
padding: 7px 14px; background: var(--ecg-teal); color: #fff;
|
||
|
|
border: none; border-radius: 4px; cursor: pointer; letter-spacing: 0.04em;
|
||
|
|
}
|
||
|
|
.abo-row {
|
||
|
|
display: flex; align-items: center; gap: 14px;
|
||
|
|
padding: 10px 0; border-bottom: 1px solid var(--ecg-border);
|
||
|
|
font-size: 13px;
|
||
|
|
}
|
||
|
|
.abo-row:last-child { border-bottom: none; }
|
||
|
|
.abo-tag {
|
||
|
|
font-family: var(--font-mono); font-size: 11px;
|
||
|
|
padding: 3px 7px; border: 1px solid var(--ecg-border); border-radius: 3px;
|
||
|
|
background: var(--ecg-card-bg);
|
||
|
|
}
|
||
|
|
.abo-del {
|
||
|
|
font-family: var(--font-mono); font-size: 11px;
|
||
|
|
padding: 4px 10px; background: none; border: 1px solid var(--ecg-border);
|
||
|
|
border-radius: 3px; cursor: pointer; color: var(--redline-contra, #c00);
|
||
|
|
}
|
||
|
|
.abo-del:hover { background: var(--redline-contra-bg, #f9e6e6); }
|
||
|
|
</style>
|
||
|
|
{% endblock %}
|
||
|
|
|
||
|
|
{% block main %}
|
||
|
|
<div style="padding:0 0 1rem;">
|
||
|
|
<h1 style="font-family:var(--font-display);font-size:22px;color:var(--ecg-teal);margin:0 0 4px;">Meine E-Mail-Abos</h1>
|
||
|
|
<p style="font-size:12px;font-family:var(--font-mono);color:var(--ecg-dark);opacity:0.6;">
|
||
|
|
Tägliche Zusammenfassung neuer Bewertungen — gefiltert nach Bundesland und/oder Partei.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<form class="abo-form" onsubmit="aboCreate(event)">
|
||
|
|
<div>
|
||
|
|
<label for="abo-bl">Bundesland</label>
|
||
|
|
<select id="abo-bl">
|
||
|
|
<option value="">— alle —</option>
|
||
|
|
{% for bl in v2_bundeslaender %}<option value="{{ bl.code }}">{{ bl.code }} — {{ bl.name }}</option>{% endfor %}
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="abo-partei">Partei</label>
|
||
|
|
<input type="text" id="abo-partei" placeholder="z.B. SPD oder leer = alle" autocomplete="off">
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label for="abo-freq">Frequenz</label>
|
||
|
|
<select id="abo-freq">
|
||
|
|
<option value="daily">täglich</option>
|
||
|
|
<option value="weekly">wöchentlich</option>
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
<button type="submit" class="submit">Abo anlegen</button>
|
||
|
|
</form>
|
||
|
|
|
||
|
|
<div id="abo-status" style="margin-bottom:8px;font-family:var(--font-mono);font-size:12px;opacity:0.7;"></div>
|
||
|
|
<div id="abo-list">Lade …</div>
|
||
|
|
|
||
|
|
{% endblock %}
|
||
|
|
|
||
|
|
{% block body_scripts %}
|
||
|
|
<script>
|
||
|
|
async function aboLoad() {
|
||
|
|
var listEl = document.getElementById('abo-list');
|
||
|
|
try {
|
||
|
|
var r = await fetch('/api/subscriptions');
|
||
|
|
if (r.status === 401) {
|
||
|
|
listEl.innerHTML = '<p style="color:var(--ecg-dark);opacity:0.7;">Bitte erst anmelden.</p>';
|
||
|
|
if (window.v2AuthModalOpen) window.v2AuthModalOpen();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var subs = await r.json();
|
||
|
|
if (!subs || !subs.length) {
|
||
|
|
listEl.innerHTML = '<p style="opacity:0.6;font-style:italic;">Du hast noch keine Abos. Lege oben eines an.</p>';
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
listEl.innerHTML = subs.map(function(s) {
|
||
|
|
var bl = s.bundesland || '—';
|
||
|
|
var p = s.partei || '—';
|
||
|
|
var f = s.frequency || 'daily';
|
||
|
|
var ls = s.last_sent ? ('zuletzt: ' + s.last_sent.substring(0,10)) : 'noch nie versandt';
|
||
|
|
return '<div class="abo-row">'
|
||
|
|
+ '<span class="abo-tag">BL ' + escHtml(bl) + '</span>'
|
||
|
|
+ '<span class="abo-tag">Partei ' + escHtml(p) + '</span>'
|
||
|
|
+ '<span class="abo-tag">' + escHtml(f) + '</span>'
|
||
|
|
+ '<span style="flex:1;opacity:0.6;font-family:var(--font-mono);font-size:11px;">' + escHtml(ls) + '</span>'
|
||
|
|
+ '<button class="abo-del" onclick="aboDelete(' + s.id + ')">✕ Löschen</button>'
|
||
|
|
+ '</div>';
|
||
|
|
}).join('');
|
||
|
|
} catch (e) {
|
||
|
|
listEl.innerHTML = '<p style="color:#c00;">Fehler: ' + escHtml(e.message) + '</p>';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function aboCreate(e) {
|
||
|
|
e.preventDefault();
|
||
|
|
var bl = document.getElementById('abo-bl').value;
|
||
|
|
var part = document.getElementById('abo-partei').value.trim();
|
||
|
|
var freq = document.getElementById('abo-freq').value;
|
||
|
|
var fd = new FormData();
|
||
|
|
if (bl) fd.append('bundesland', bl);
|
||
|
|
if (part) fd.append('partei', part);
|
||
|
|
fd.append('frequency', freq);
|
||
|
|
var r = await fetch('/api/subscriptions', { method: 'POST', body: fd });
|
||
|
|
if (r.status === 401) {
|
||
|
|
if (window.v2AuthModalOpen) window.v2AuthModalOpen();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (!r.ok) {
|
||
|
|
var err = await r.json().catch(()=>({detail:'Fehler'}));
|
||
|
|
setStatus('Fehler: ' + (err.detail || r.status), true);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
setStatus('Abo angelegt.');
|
||
|
|
document.getElementById('abo-partei').value = '';
|
||
|
|
aboLoad();
|
||
|
|
}
|
||
|
|
|
||
|
|
async function aboDelete(id) {
|
||
|
|
if (!confirm('Abo wirklich löschen?')) return;
|
||
|
|
var r = await fetch('/api/subscriptions/' + id, { method: 'DELETE' });
|
||
|
|
if (r.ok) { setStatus('Abo gelöscht.'); aboLoad(); }
|
||
|
|
else { setStatus('Löschen fehlgeschlagen.', true); }
|
||
|
|
}
|
||
|
|
|
||
|
|
function setStatus(msg, isErr) {
|
||
|
|
var el = document.getElementById('abo-status');
|
||
|
|
el.textContent = msg;
|
||
|
|
el.style.color = isErr ? '#c00' : 'var(--ecg-teal)';
|
||
|
|
setTimeout(function(){ el.textContent=''; }, 4000);
|
||
|
|
}
|
||
|
|
|
||
|
|
function escHtml(s) {
|
||
|
|
return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
||
|
|
}
|
||
|
|
|
||
|
|
document.addEventListener('DOMContentLoaded', aboLoad);
|
||
|
|
</script>
|
||
|
|
{% endblock %}
|