mirror of
https://github.com/guyg1474/hcrb.git
synced 2026-10-16 07:13:28 +02:00
Erste Version: HCRB Spieltag-Kalender und Fahrtplaner
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
10400eee59
30 files changed
+3771
No files matched your search
@@ -0,0 +1,69 @@
|
||||
import { $, api, esc, showError, renderHeader, renderFooter } from './common.js';
|
||||
|
||||
renderHeader('statistik');
|
||||
renderFooter();
|
||||
|
||||
let stats = [];
|
||||
let canEdit = false; // angemeldet und laufendes Jahr
|
||||
|
||||
function detail(s) {
|
||||
if (!s.manual) return '';
|
||||
const sign = s.manual > 0 ? '+' : '−';
|
||||
return `<span class="meta">${s.calendar} aus Kalender ${sign} ${Math.abs(s.manual)} manuell</span>`;
|
||||
}
|
||||
|
||||
function render() {
|
||||
$('#stats-empty').hidden = stats.length > 0;
|
||||
$('#stats-edit-hint').hidden = !canEdit;
|
||||
// Gleiche Anzahl → gleicher Platz
|
||||
const rank = (s) => 1 + stats.filter((x) => x.total > s.total).length;
|
||||
$('#stats-list').innerHTML = stats.map((s) => `
|
||||
<li>
|
||||
<span class="rank">${rank(s)}.</span>
|
||||
<span class="name">${esc(s.name)}</span>
|
||||
${detail(s)}
|
||||
<span class="actions">
|
||||
${canEdit ? `
|
||||
<button class="small" data-step="-1" data-id="${s.id}" ${s.total ? '' : 'disabled'} aria-label="Ein Spiel weniger">−</button>` : ''}
|
||||
<span class="stat-total">${s.total}</span>
|
||||
${canEdit ? `
|
||||
<button class="small" data-step="1" data-id="${s.id}" aria-label="Ein Spiel mehr">+</button>` : ''}
|
||||
</span>
|
||||
</li>`).join('');
|
||||
}
|
||||
|
||||
$('#stats-list').addEventListener('click', async (e) => {
|
||||
const { step, id } = e.target.dataset;
|
||||
if (!step) return;
|
||||
const s = stats.find((x) => x.id === id);
|
||||
try {
|
||||
const { manual } = await api('PUT', `/members/${id}/plays-manual`, { manual: Math.max(s.manual, -s.calendar) + Number(step) });
|
||||
s.manual = manual;
|
||||
s.total = Math.max(0, s.calendar + manual);
|
||||
stats.sort((a, b) => b.total - a.total || a.name.localeCompare(b.name, 'de'));
|
||||
render();
|
||||
} catch (err) {
|
||||
showError(err);
|
||||
}
|
||||
});
|
||||
|
||||
let loggedIn = false;
|
||||
|
||||
async function load(year) {
|
||||
const data = await api('GET', `/stats${year ? `?year=${year}` : ''}`);
|
||||
stats = data.entries;
|
||||
canEdit = loggedIn && data.live;
|
||||
$('#stats-year').innerHTML = data.years
|
||||
.map((y, i) => `<option value="${y}" ${y === data.year ? 'selected' : ''}>${y}${i === 0 ? ' (laufend)' : ''}</option>`).join('');
|
||||
$('#stats-info').textContent = data.live
|
||||
? `Gezählt werden die Spieltage seit dem 1. Januar ${data.year}, bei denen jemand zugesagt hat. `
|
||||
+ 'Zu Neujahr wird das Jahr gespeichert und die Zählung beginnt von vorn. Externe werden nicht aufgeführt.'
|
||||
: `Endstand ${data.year}, gespeichert am ${new Date(data.savedAt).toLocaleDateString('de-DE')}.`;
|
||||
render();
|
||||
}
|
||||
|
||||
$('#stats-year').addEventListener('change', (e) => load(e.target.value).catch(showError));
|
||||
|
||||
api('GET', '/me')
|
||||
.then(({ user }) => { loggedIn = !!user; return load(); })
|
||||
.catch(showError);
|
||||
Reference in new issue
Block a user