122 lines
5.0 KiB
HTML
122 lines
5.0 KiB
HTML
|
|
{% extends "base.html" %}
|
||
|
|
{% block title %}Admin — {{ serie.name }}{% endblock %}
|
||
|
|
{% block content %}
|
||
|
|
<a href="/admin/series" style="color:var(--text-muted);text-decoration:none;font-size:0.9rem;">← Serier</a>
|
||
|
|
<h1 style="margin-top:12px;">📦 {{ serie.name }}</h1>
|
||
|
|
{% if serie.description %}
|
||
|
|
<p style="color:var(--text-muted);margin-bottom:16px;">{{ serie.description }}</p>
|
||
|
|
{% endif %}
|
||
|
|
|
||
|
|
<div style="display:flex;gap:24px;flex-wrap:wrap;margin:20px 0;">
|
||
|
|
<div class="card" style="flex:1;min-width:280px;">
|
||
|
|
<h3>Opret sæt under {{ serie.name }}</h3>
|
||
|
|
<form onsubmit="createSet(event)" style="display:flex;flex-direction:column;gap:10px;margin-top:12px;">
|
||
|
|
<input type="hidden" id="set-serie-name" value="{{ serie.name }}">
|
||
|
|
<input type="text" id="set-code" placeholder="Kode (f.eks. EVS)" required>
|
||
|
|
<input type="text" id="set-name" placeholder="Navn (f.eks. Evolving Skies)" required>
|
||
|
|
<input type="date" id="set-date" placeholder="Udgivelsesdato">
|
||
|
|
<input type="text" id="set-desc" placeholder="Beskrivelse (valgfri)">
|
||
|
|
<button class="btn btn-primary">Opret</button>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="card" style="flex:1;min-width:280px;">
|
||
|
|
<h3>CSV-import af sæt</h3>
|
||
|
|
<p style="font-size:0.85rem;color:var(--text-muted);margin:8px 0;">
|
||
|
|
Kolonner: <code>code,name,release_date,description</code>
|
||
|
|
— <strong>{{ serie.name }}</strong> udfyldes automatisk.
|
||
|
|
<br><a href="/api/admin/templates/sets.csv" style="color:var(--accent);">Download skabelon</a>
|
||
|
|
</p>
|
||
|
|
<form onsubmit="importSets(event)" style="display:flex;flex-direction:column;gap:10px;">
|
||
|
|
<input type="file" id="sets-csv" accept=".csv" required>
|
||
|
|
<button class="btn btn-primary">Importer</button>
|
||
|
|
</form>
|
||
|
|
<div id="sets-import-result" style="margin-top:8px;"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<h2>Sæt i {{ serie.name }}</h2>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr><th>Kode</th><th>Navn</th><th>Kort</th><th>Udgivet</th><th>Handling</th></tr>
|
||
|
|
</thead>
|
||
|
|
<tbody id="sets-list">
|
||
|
|
{% for set in serie.sets %}
|
||
|
|
<tr id="set-{{ set.id }}">
|
||
|
|
<td><span class="tag">{{ set.code }}</span></td>
|
||
|
|
<td><a href="/admin/cards/{{ set.code }}" style="color:var(--text);">{{ set.name }}</a></td>
|
||
|
|
<td>{{ set.cards|length }}</td>
|
||
|
|
<td>{{ set.release_date or '—' }}</td>
|
||
|
|
<td>
|
||
|
|
<button class="btn btn-outline btn-sm" onclick="location.href='/admin/cards/{{ set.code }}'">Kort</button>
|
||
|
|
<button class="btn btn-danger btn-sm" onclick="deleteSet({{ set.id }})">Slet</button>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
{% endfor %}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
|
||
|
|
{% if serie.sets|length == 0 %}
|
||
|
|
<div class="card" style="text-align:center;color:var(--text-muted);margin-top:16px;">
|
||
|
|
<p>Ingen sæt i {{ serie.name }} endnu.</p>
|
||
|
|
</div>
|
||
|
|
{% endif %}
|
||
|
|
|
||
|
|
<script>
|
||
|
|
async function createSet(e) {
|
||
|
|
e.preventDefault();
|
||
|
|
const serieName = document.getElementById('set-serie-name').value;
|
||
|
|
const code = document.getElementById('set-code').value.trim();
|
||
|
|
const name = document.getElementById('set-name').value.trim();
|
||
|
|
if (!code || !name) return;
|
||
|
|
const release_date = document.getElementById('set-date').value || null;
|
||
|
|
const description = document.getElementById('set-desc').value.trim() || null;
|
||
|
|
const res = await fetch('/api/admin/series/' + encodeURIComponent(serieName) + '/sets', {
|
||
|
|
method: 'POST',
|
||
|
|
headers: {'Content-Type': 'application/json'},
|
||
|
|
body: JSON.stringify({code, name, release_date, description})
|
||
|
|
});
|
||
|
|
const data = await res.json();
|
||
|
|
if (data.ok) {
|
||
|
|
location.reload();
|
||
|
|
} else {
|
||
|
|
alert(data.detail || 'Fejl');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function deleteSet(id) {
|
||
|
|
if (!confirm('Slet dette sæt og alle dets kort?')) return;
|
||
|
|
const res = await fetch('/api/admin/sets/' + id, {method: 'DELETE'});
|
||
|
|
const data = await res.json();
|
||
|
|
if (data.ok) {
|
||
|
|
document.getElementById('set-' + id).remove();
|
||
|
|
} else {
|
||
|
|
alert('Fejl ved sletning');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
async function importSets(e) {
|
||
|
|
e.preventDefault();
|
||
|
|
const file = document.getElementById('sets-csv').files[0];
|
||
|
|
if (!file) return;
|
||
|
|
const form = new FormData();
|
||
|
|
form.append('file', file);
|
||
|
|
const serieName = document.getElementById('set-serie-name').value;
|
||
|
|
const res = await fetch('/api/admin/series/' + encodeURIComponent(serieName) + '/sets/import', {
|
||
|
|
method: 'POST', body: form
|
||
|
|
});
|
||
|
|
const data = await res.json();
|
||
|
|
const el = document.getElementById('sets-import-result');
|
||
|
|
if (data.ok) {
|
||
|
|
el.innerHTML = '<p style="color:green;">\u2713 ' + data.created + ' s\u00e6t oprettet</p>';
|
||
|
|
if (data.errors.length) {
|
||
|
|
el.innerHTML += '<p style="color:var(--accent);">' + data.errors.join('<br>') + '</p>';
|
||
|
|
}
|
||
|
|
setTimeout(() => location.reload(), 1500);
|
||
|
|
} else {
|
||
|
|
el.innerHTML = '<p style="color:var(--accent);">Fejl ved import</p>';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
{% endblock %}
|