Files
Sdk_TV_app/templates/modern_archive_index.html
T

296 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title data-i18n="navigation.archive">Arhiv</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/css/base.css">
<link rel="stylesheet" href="/static/css/navbar.css">
<link rel="stylesheet" href="/static/css/buttons.css">
<link rel="stylesheet" href="/static/css/components.css">
<link rel="stylesheet" href="/static/css/responsive.css">
<link rel="stylesheet" href="/static/css/pages/modern_archive_index.css">
<script src="/static/js/i18n.js"></script>
</head>
<body>
<div class="navbar">
<div class="navbar-title">📚 Arhiv</div>
<div class="navbar-controls">
<a href="/archive/player-analysis" class="nav-btn">👤 <span data-i18n="players.player_analysis">Player Analysis</span></a>
<a href="/archive" class="nav-btn active">📚 <span data-i18n="navigation.archive">Archive</span></a>
<a href="/" class="nav-btn">✕</a>
</div>
</div>
<div class="archive-layout">
<!-- LEFT -->
<div class="left-panel">
<div class="panel-header">
<div class="panel-header-title">📚 Turnirji</div>
<div class="panel-header-count" id="treeCount">0</div>
</div>
<div class="tree-sort-bar">
<input type="text" id="treeSearch" placeholder="🔍 Iskanje po datumu…" oninput="renderTree()">
<div class="filter-tabs">
<button class="filter-tab active" data-filter="all" onclick="setFilter('all')">Vsi</button>
<button class="filter-tab" data-filter="league" onclick="setFilter('league')">🎖️ Liga</button>
<button class="filter-tab" data-filter="40" onclick="setFilter('40')">💪 40</button>
<button class="filter-tab" data-filter="20" onclick="setFilter('20')">⚡ 20</button>
<button class="filter-tab" data-filter="4" onclick="setFilter('4')">🎯 4</button>
</div>
</div>
<div class="tree-list" id="treeList"></div>
</div>
<!-- RIGHT -->
<div class="right-panel" id="rightPanel">
<div class="result-placeholder" id="placeholder">
<div class="result-placeholder-icon">🏆</div>
<div class="result-placeholder-text">Izberi zapis iz drevesa</div>
</div>
<div class="loading-overlay" id="loadingOverlay" style="display:none">Nalagam…</div>
<div class="tv-container" id="tvContainer" style="display:none">
<div class="right-column">
<div class="table-header">
<h3 class="table-title" id="tableTitle">📊 Uvrstitve</h3>
</div>
<div class="table-container">
<table class="results-table">
<thead id="tableHead"></thead>
<tbody id="tableBody"></tbody>
</table>
</div>
<div class="stats-footer">
<div class="stat-item"><div class="stat-value" id="footerParticipants">0</div><div>Udeleženci</div></div>
<div class="stat-item"><div class="stat-value" id="footerHighest">0</div><div>Najvišji rezultat</div></div>
<div class="stat-item"><div class="stat-value" id="footerAverage">0</div><div>Povprečje</div></div>
<div class="stat-item"><div class="stat-value" id="footerMostTens">0</div><div>Največ desetk</div></div>
<div class="stat-item"><div class="stat-value" id="footerDate">—</div><div>Datum</div></div>
</div>
</div>
</div><!-- end tv-container -->
</div><!-- end right-panel -->
</div><!-- end archive-layout -->
<script>
const tournaments = {{ tournaments | tojson }};
const leagues = {{ leagues | tojson }};
const allItems = [
...tournaments.map(t => ({
kind: 'tournament',
type: (t.tournament_type || '20_targets').split('_')[0],
date: t.archived_at || 'Unknown',
players: t.participants_count || 0,
rounds: t.total_rounds || '?',
filename: t.filename,
apiUrl: `/api/archive/tournament/${t.filename}/standings`
})),
...leagues.map(l => ({
kind: 'league',
type: 'league',
date: l.archived_at || 'Unknown',
players: l.participants_count || 0,
progress: `${l.completed_tournaments}/${l.total_tournaments}`,
filename: l.filename,
apiUrl: `/api/archive/league/${l.filename}/standings`
}))
].sort((a, b) => new Date(b.date) - new Date(a.date));
let activeFilter = 'all';
let activeFilename = null;
const GROUP_ORDER = ['liga', 't40', 't20', 't4'];
const itemIndex = new Map(allItems.map((item, i) => [item.filename, i]));
function fmtDate(d) {
if (!d || d === 'Unknown') return 'Unknown';
const p = d.slice(0, 10).split('-');
return p.length === 3 ? `${p[2]}.${p[1]}.${p[0].slice(2)}` : d.slice(0, 10);
}
function groupOf(item) {
if (item.kind === 'league') return { key: 'liga', label: '🎖️ Lige' };
if (item.type === '40') return { key: 't40', label: '💪 40 Tarč' };
if (item.type === '20') return { key: 't20', label: '⚡ 20 Tarč' };
return { key: 't4', label: '🎯 4 Tarč' };
}
function icon(item) {
if (item.kind === 'league') return '🎖️';
if (item.type === '40') return '💪';
if (item.type === '20') return '⚡';
return '🎯';
}
function badgeHtml(item) {
if (item.kind === 'league') return `<span class="tbadge tbadge-league">Liga</span>`;
if (item.type === '40') return `<span class="tbadge tbadge-40">40T</span>`;
if (item.type === '20') return `<span class="tbadge tbadge-20">20T</span>`;
return `<span class="tbadge tbadge-4">4T</span>`;
}
function setFilter(f) {
activeFilter = f;
document.querySelectorAll('.filter-tab').forEach(t =>
t.classList.toggle('active', t.dataset.filter === f));
renderTree();
}
function renderTree() {
const search = document.getElementById('treeSearch').value.toLowerCase().trim();
const filtered = allItems.filter(item => {
const matchFilter = activeFilter === 'all'
|| item.type === activeFilter
|| (activeFilter === 'league' && item.kind === 'league');
const matchSearch = !search
|| fmtDate(item.date).toLowerCase().includes(search)
|| item.date.slice(0, 10).includes(search);
return matchFilter && matchSearch;
});
const groups = {};
filtered.forEach(item => {
const g = groupOf(item);
if (!groups[g.key]) groups[g.key] = { label: g.label, items: [] };
groups[g.key].items.push(item);
});
const treeList = document.getElementById('treeList');
document.getElementById('treeCount').textContent = filtered.length;
if (!filtered.length) {
treeList.innerHTML = '<div class="tree-empty">Ni zadetkov</div>';
return;
}
let html = '';
GROUP_ORDER.forEach(key => {
if (!groups[key]) return;
const g = groups[key];
html += `<div class="tree-group" id="grp-${key}">
<div class="tree-group-header" onclick="toggleGroup('grp-${key}')">
<span class="tree-toggle">▾</span>${g.label}
<span style="margin-left:auto;font-size:0.65rem;color:#bbb">${g.items.length}</span>
</div>
<div class="tree-group-items">`;
g.items.forEach(item => {
const active = item.filename === activeFilename ? ' active' : '';
const meta = item.kind === 'league'
? `${item.players} igralcev · ${item.progress} tur.`
: `${item.players} igralcev · ${item.rounds} krogov`;
const idx = itemIndex.get(item.filename);
const viewUrl = item.kind === 'league'
? `/archive/league/${item.filename}`
: `/archive/tournament/${item.filename}`;
html += `<div class="tree-item${active}" onclick="openItem(${idx})">
<span>${icon(item)}</span>
<div class="tree-item-info">
<span class="tree-item-date">${fmtDate(item.date)}</span>
<span class="tree-item-meta">${meta}</span>
</div>
${badgeHtml(item)}
<button class="tree-view-btn" onclick="event.stopPropagation(); window.location='${viewUrl}'" title="Celotni rezultati">⛶</button>
</div>`;
});
html += `</div></div>`;
});
treeList.innerHTML = html;
}
function toggleGroup(id) {
document.getElementById(id)?.classList.toggle('collapsed');
}
async function openItem(idx) {
const item = allItems[idx];
activeFilename = item.filename;
renderTree();
document.getElementById('placeholder').style.display = 'none';
document.getElementById('tvContainer').style.display = 'none';
document.getElementById('loadingOverlay').style.display = 'flex';
try {
const res = await fetch(item.apiUrl);
const data = await res.json();
renderResults(data, item);
} catch(e) {
document.getElementById('loadingOverlay').textContent = 'Napaka pri nalaganju.';
}
}
function renderResults(data, item) {
document.getElementById('loadingOverlay').style.display = 'none';
document.getElementById('tvContainer').style.display = 'grid';
const p = data.participants;
const isTournament = data.kind === 'tournament';
const highest = p.length ? p[0][isTournament ? 'total_score' : 'final_score'] : 0;
const mostTens = isTournament ? (p.length ? Math.max(...p.map(x => x.tens_count)) : 0) : '—';
// ── Table ────────────────────────────────────────────────────────────
if (isTournament) {
document.getElementById('tableTitle').textContent = '📊 Uvrstitve';
document.getElementById('tableHead').innerHTML = `<tr>
<th class="rank-col">Mesto</th>
<th class="player-col">Udeleženec</th>
<th class="score-col">Rezultat</th>
<th class="tens-col">Desetke</th>
</tr>`;
document.getElementById('tableBody').innerHTML = p.map(pl => {
const rankClass = pl.rank <= 3 ? `rank-${pl.rank}` : 'rank-other';
const medal = pl.rank === 1 ? '🥇' : pl.rank === 2 ? '🥈' : pl.rank === 3 ? '🥉' : '';
return `<tr>
<td class="rank-cell ${rankClass}">${pl.rank} ${medal}</td>
<td class="player-cell"><div class="player-name">${pl.name}</div></td>
<td class="score-cell">${pl.total_score}</td>
<td class="tens-cell">🎯 ${pl.tens_count}</td>
</tr>`;
}).join('');
} else {
document.getElementById('tableTitle').textContent = '📊 Ligaška lestvica';
document.getElementById('tableHead').innerHTML = `<tr>
<th class="rank-col">Mesto</th>
<th class="player-col">Udeleženec</th>
<th class="score-col">Finale</th>
<th class="tens-col">Skupaj</th>
<th>Tur.</th>
</tr>`;
document.getElementById('tableBody').innerHTML = p.map(pl => {
const rankClass = pl.rank <= 3 ? `rank-${pl.rank}` : 'rank-other';
const medal = pl.rank === 1 ? '🥇' : pl.rank === 2 ? '🥈' : pl.rank === 3 ? '🥉' : '';
return `<tr>
<td class="rank-cell ${rankClass}">${pl.rank} ${medal}</td>
<td class="player-cell"><div class="player-name">${pl.name}</div></td>
<td class="final-cell">${pl.final_score}</td>
<td class="score-cell">${pl.total_score}</td>
<td class="part-cell">${pl.tournaments_participated}</td>
</tr>`;
}).join('');
}
// ── Footer stats ─────────────────────────────────────────────────────
const scores = p.map(x => isTournament ? x.total_score : x.final_score);
const avg = scores.length ? Math.round(scores.reduce((a, b) => a + b, 0) / scores.length) : 0;
const totalShots = isTournament
? p.length * (data.tournament_type === '40_targets' ? 80 : data.tournament_type === '4_targets' ? 20 : 40)
: 0;
document.getElementById('footerParticipants').textContent = p.length;
document.getElementById('footerHighest').textContent = highest;
document.getElementById('footerAverage').textContent = avg;
document.getElementById('footerMostTens').textContent = isTournament ? mostTens : '—';
document.getElementById('footerDate').textContent = fmtDate(data.archived_at || item.date);
}
document.addEventListener('DOMContentLoaded', renderTree);
</script>
</body>
</html>