95 lines
3.6 KiB
HTML
95 lines
3.6 KiB
HTML
|
|
{% extends "base.html" %}
|
||
|
|
{% block title %}Admin — Serier{% endblock %}
|
||
|
|
{% block content %}
|
||
|
|
<h1>📦 Administrér serier</h1>
|
||
|
|
<p style="color:var(--text-muted);margin-bottom:16px;">Opret og slet Pokémon TCG serier/sets.</p>
|
||
|
|
|
||
|
|
<div class="card" style="margin-bottom:24px;">
|
||
|
|
<h2>Opret ny serie</h2>
|
||
|
|
<form id="create-set-form" style="display:flex;gap:8px;flex-wrap:wrap;margin-top:12px;">
|
||
|
|
<input type="text" name="code" placeholder="Kode (f.eks. CRI)" required style="max-width:120px;text-transform:uppercase;">
|
||
|
|
<input type="text" name="name" placeholder="Navn (f.eks. Chaos Rising)" required style="max-width:280px;">
|
||
|
|
<input type="text" name="release_date" placeholder="Udgivelsesdato" style="max-width:160px;">
|
||
|
|
<button type="submit" class="btn btn-primary">Opret</button>
|
||
|
|
</form>
|
||
|
|
<p id="set-msg" style="font-size:0.85rem;margin-top:8px;"></p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<h2>Eksisterende serier</h2>
|
||
|
|
<div id="set-list"></div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
async function loadSets() {
|
||
|
|
try {
|
||
|
|
const res = await fetch('/api/admin/sets');
|
||
|
|
const sets = await res.json();
|
||
|
|
const container = document.getElementById('set-list');
|
||
|
|
|
||
|
|
if (sets.length === 0) {
|
||
|
|
container.innerHTML = '<div class="card"><p style="color:var(--text-muted);">Ingen serier endnu.</p></div>';
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
let html = '<div style="overflow-x:auto;"><table><thead><tr><th>Kode</th><th>Navn</th><th>Udgivet</th><th style="width:100px;"></th></tr></thead><tbody>';
|
||
|
|
sets.forEach(s => {
|
||
|
|
html += '<tr>' +
|
||
|
|
'<td><span class="tag">' + s.code + '</span></td>' +
|
||
|
|
'<td><a href="/admin/cards/' + s.code + '" style="color:var(--text);">' + s.name + '</a></td>' +
|
||
|
|
'<td>' + (s.release_date || '—') + '</td>' +
|
||
|
|
'<td><button class="btn btn-danger btn-sm" onclick="deleteSet(' + s.id + ', \'' + s.code + '\')">Slet</button></td>' +
|
||
|
|
'</tr>';
|
||
|
|
});
|
||
|
|
html += '</tbody></table></div>';
|
||
|
|
container.innerHTML = html;
|
||
|
|
} catch(e) {
|
||
|
|
document.getElementById('set-list').innerHTML = '<p style="color:var(--accent);">Kunne ikke indlæse serier</p>';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function deleteSet(id, code) {
|
||
|
|
if (!confirm('Slet serien ' + code + '? Alle kort i serien slettes også.')) return;
|
||
|
|
try {
|
||
|
|
const res = await fetch('/api/admin/sets/' + id, { method: 'DELETE' });
|
||
|
|
if (res.ok) {
|
||
|
|
loadSets();
|
||
|
|
} else {
|
||
|
|
alert('Kunne ikke slette');
|
||
|
|
}
|
||
|
|
} catch(e) {
|
||
|
|
alert('Fejl ved sletning');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
document.getElementById('create-set-form').addEventListener('submit', async (e) => {
|
||
|
|
e.preventDefault();
|
||
|
|
const form = e.target;
|
||
|
|
const msg = document.getElementById('set-msg');
|
||
|
|
try {
|
||
|
|
const res = await fetch('/api/admin/sets', {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify({
|
||
|
|
code: form.code.value,
|
||
|
|
name: form.name.value,
|
||
|
|
release_date: form.release_date.value || null,
|
||
|
|
}),
|
||
|
|
});
|
||
|
|
if (res.ok) {
|
||
|
|
form.reset();
|
||
|
|
msg.style.color = 'var(--text)';
|
||
|
|
msg.textContent = '✅ Serie oprettet';
|
||
|
|
loadSets();
|
||
|
|
} else {
|
||
|
|
const err = await res.json();
|
||
|
|
msg.style.color = 'var(--accent)';
|
||
|
|
msg.textContent = '❌ ' + (err.detail || 'Fejl');
|
||
|
|
}
|
||
|
|
} catch(e) {
|
||
|
|
msg.style.color = 'var(--accent)';
|
||
|
|
msg.textContent = '❌ Kunne ikke forbinde';
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
loadSets();
|
||
|
|
</script>
|
||
|
|
{% endblock %}
|