Files

245 lines
11 KiB
HTML

<!DOCTYPE html>
<!--
dokumenti.html — Lista dokumenata: godišnjaci, publikacije, izdanja
Author: Damir Radulić | v1.0 | 05.05.2026
-->
<html lang="hr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>📚 Dokumenti — PGŽ Sport</title>
<link rel="icon" href="/favicon.ico">
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font:14px system-ui;background:#06080d;color:#e0e0e0;padding:0}
header{background:#0a0e15;padding:12px 20px;border-bottom:1px solid #2a2a2e;display:flex;justify-content:space-between;align-items:center}
header h1{font-size:20px;color:#5fb6ff}
header a{color:#888;text-decoration:none;margin-left:16px;font-size:14px}
header a:hover{color:#fff}
.container{padding:20px;max-width:1400px;margin:0 auto}
.filters{background:#0c1016;padding:16px;border-radius:8px;margin-bottom:20px;display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.filters label{font-size:12px;color:#888}
.filters select, .filters input {
background:#1a1a1e;border:1px solid #2a2a2e;color:#fff;padding:8px 12px;border-radius:5px;font-size:13px
}
.filters input{min-width:240px}
.toolbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;gap:12px;flex-wrap:wrap}
.stats{font-size:13px;color:#888}
.stats b{color:#5fb6ff;font-weight:600}
.view-toggle{display:inline-flex;background:#0c1016;border:1px solid #2a2a2e;border-radius:6px;overflow:hidden}
.view-toggle button{background:transparent;border:0;color:#888;padding:6px 12px;font-size:12px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;font-family:inherit}
.view-toggle button.active{background:#1e3a5f;color:#5fb6ff}
.view-toggle button:hover:not(.active){color:#fff}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px}
.card{background:#0c1016;border:1px solid #1a1a1e;border-radius:8px;padding:14px;cursor:pointer;transition:all .2s;display:flex;gap:12px;align-items:flex-start}
.card:hover{border-color:#5fb6ff;transform:translateY(-2px);box-shadow:0 6px 20px rgba(95,182,255,.2)}
.card-thumb{flex:0 0 56px;width:56px;height:72px;border-radius:4px;background:linear-gradient(160deg,#1e3a5f 0%,#0c1016 100%);border:1px solid #2a2a2e;display:flex;align-items:center;justify-content:center;font-size:24px}
.card-body{flex:1;min-width:0}
.card-title{font-size:13px;font-weight:600;margin-bottom:6px;color:#fff;line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.card-org{font-size:11px;color:#888;margin-bottom:6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.card-meta{font-size:10px;color:#666;display:flex;gap:6px;flex-wrap:wrap}
.card-meta span{background:#1a1a1e;padding:2px 6px;border-radius:3px}
table.docs{width:100%;border-collapse:collapse;background:#0c1016;border:1px solid #1a1a1e;border-radius:8px;overflow:hidden}
table.docs th, table.docs td{padding:8px 12px;text-align:left;font-size:12px;border-bottom:1px solid #1a1a1e}
table.docs th{background:#0a0e15;color:#888;font-weight:600;text-transform:uppercase;font-size:10px;letter-spacing:.5px;white-space:nowrap}
table.docs tr{cursor:pointer;transition:background .15s}
table.docs tbody tr:hover{background:#11161f}
table.docs td.t-title{color:#fff;font-weight:500;max-width:480px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
table.docs td.t-num{font-variant-numeric:tabular-nums;color:#aaa;text-align:right;white-space:nowrap}
table.docs td.t-tag{color:#888}
.empty{text-align:center;padding:40px;color:#666;background:#0c1016;border:1px solid #1a1a1e;border-radius:8px}
.badge-godisnjak{background:#1e3a5f;color:#5fb6ff;padding:2px 6px;border-radius:3px;font-size:10px;font-weight:600}
</style>
<script src="/static/shared/sortable.js" defer></script>
</head>
<body>
<header>
<h1><a href="/" style="color:#5fb6ff;text-decoration:none">📚 Dokumenti</a></h1>
<div>
<a href="/">🏠 Home</a>
<a href="/app">📊 App</a>
<a href="/admin/users">👥 Admin</a>
<a href="/erp/full">💼 ERP</a>
<a href="/crm/v2">📝 CRM</a>
</div>
</header>
<div class="container">
<div class="filters">
<div>
<label>Vrsta</label><br>
<select id="f-vrsta" onchange="loadDocs()">
<option value="">Sve</option>
<option value="godisnjak">Godišnjak</option>
<option value="manifestacija">Manifestacija</option>
<option value="natjecaj">Natječaj</option>
<option value="izvjestaj">Izvještaj</option>
</select>
</div>
<div>
<label>Izdavatelj</label><br>
<select id="f-org" onchange="loadDocs()">
<option value="">Svi</option>
<option value="Zajednica športskih saveza PGŽ">ZSP PGŽ</option>
<option value="Riječki sportski savez">RSS</option>
<option value="Grad Rijeka">Grad Rijeka</option>
<option value="HOO">HOO</option>
<option value="Grad/Općina">JLS</option>
</select>
</div>
<div>
<label>Sport</label><br>
<select id="f-sport" onchange="loadDocs()">
<option value="">Svi</option>
<option value="nogomet">Nogomet</option>
<option value="košarka">Košarka</option>
<option value="rukomet">Rukomet</option>
<option value="odbojka">Odbojka</option>
<option value="vaterpolo">Vaterpolo</option>
</select>
</div>
<div>
<label>Godina</label><br>
<select id="f-godina" onchange="loadDocs()">
<option value="">Sve godine</option>
<option value="2026">2026</option>
<option value="2025">2025</option>
<option value="2024">2024</option>
<option value="2023">2023</option>
<option value="2022">2022</option>
<option value="2021">2021</option>
<option value="2020">2020</option>
<option value="2019">2019</option>
<option value="2018">2018</option>
<option value="2017">2017</option>
<option value="2016">2016</option>
<option value="2015">2015</option>
<option value="2014">2014</option>
<option value="2013">2013</option>
<option value="2012">2012</option>
<option value="2011">2011</option>
<option value="2010">2010</option>
</select>
</div>
<div>
<label>Pretraga</label><br>
<input type="text" id="f-q" placeholder="Naziv, opis…" onkeyup="if(event.key==='Enter') loadDocs()">
</div>
<button onclick="loadDocs()" style="background:#5fb6ff;color:#000;border:none;padding:10px 16px;border-radius:5px;font-weight:600;cursor:pointer">🔍 Pretraži</button>
</div>
<div class="toolbar">
<div class="stats" id="stats">Učitavanje…</div>
<div class="view-toggle" role="tablist" aria-label="Pogled">
<button id="view-card" type="button" onclick="setView('card')" title="Kartice"><span aria-hidden="true"></span> Cards</button>
<button id="view-table" type="button" onclick="setView('table')" title="Tablica"><span aria-hidden="true"></span> Table</button>
</div>
</div>
<div id="docs-out">
<div class="empty">Učitavanje dokumenata…</div>
</div>
</div>
<script>
const VIEW_KEY = 'pgz_dok_view';
let _docsCache = [];
let _view = (function(){
const saved = localStorage.getItem(VIEW_KEY);
if (saved === 'card' || saved === 'table') return saved;
return (window.matchMedia && window.matchMedia('(max-width: 760px)').matches) ? 'card' : 'table';
})();
function fmtSize(chars){
if (!chars) return '—';
const kb = chars / 1024;
return kb < 1024 ? Math.round(kb)+' KB' : (kb/1024).toFixed(1)+' MB';
}
function fmtDate(iso){
if (!iso) return '—';
try { return new Date(iso).toLocaleDateString('hr-HR'); } catch(_) { return '—'; }
}
function rowDate(r){ return r.izdano_datum || r.scraped_at || null; }
function rowUrl(r){ return r.izvor_url || ('/sport/api/v2/dokumenti/'+r.id); }
function esc(s){ return String(s ?? '').replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c])); }
function renderCards(rows){
return '<div class="grid">' + rows.map(r => {
const isGod = r.vrsta === 'godisnjak';
return `<div class="card" onclick="window.open('${esc(rowUrl(r))}', '_blank', 'noopener')">
<div class="card-thumb" aria-hidden="true">${isGod ? '📖' : '📄'}</div>
<div class="card-body">
<div class="card-title">${esc(r.title || 'Dokument')}</div>
<div class="card-org">${esc(r.organizacija || '—')}</div>
<div class="card-meta">
${isGod ? '<span class="badge-godisnjak">GODIŠNJAK</span>' : ''}
${r.vrsta ? '<span>'+esc(r.vrsta)+'</span>' : ''}
${r.godina ? '<span>'+esc(r.godina)+'</span>' : ''}
<span>${fmtSize(r.chars)}</span>
<span>${fmtDate(rowDate(r))}</span>
</div>
</div>
</div>`;
}).join('') + '</div>';
}
function renderTable(rows){
return `<table class="docs">
<thead><tr>
<th>Title</th><th>Type</th><th>Year</th><th style="text-align:right">Size</th><th>Date</th>
</tr></thead>
<tbody>${rows.map(r => `
<tr onclick="window.open('${esc(rowUrl(r))}', '_blank', 'noopener')">
<td class="t-title">${esc(r.title || 'Dokument')}${r.vrsta==='godisnjak' ? ' <span class="badge-godisnjak">G</span>' : ''}</td>
<td class="t-tag">${esc(r.vrsta || '—')}</td>
<td class="t-num">${esc(r.godina || '—')}</td>
<td class="t-num">${fmtSize(r.chars)}</td>
<td class="t-tag">${fmtDate(rowDate(r))}</td>
</tr>`).join('')}</tbody>
</table>`;
}
function paint(){
const out = document.getElementById('docs-out');
document.getElementById('view-card').classList.toggle('active', _view === 'card');
document.getElementById('view-table').classList.toggle('active', _view === 'table');
if (!_docsCache.length){ out.innerHTML = '<div class="empty">Nema dokumenata po filtru</div>'; return; }
out.innerHTML = _view === 'card' ? renderCards(_docsCache) : renderTable(_docsCache);
}
function setView(v){
if (v !== 'card' && v !== 'table') return;
_view = v;
try { localStorage.setItem(VIEW_KEY, v); } catch(_) {}
paint();
}
async function loadDocs(){
const vrsta = document.getElementById('f-vrsta').value;
const org = document.getElementById('f-org').value;
const sport = document.getElementById('f-sport').value;
const godina = document.getElementById('f-godina').value;
const q = document.getElementById('f-q').value;
const params = new URLSearchParams();
if(vrsta) params.set('vrsta', vrsta);
if(sport) params.set('sport', sport);
if(godina) params.set('godina', godina);
if(q) params.set('q', q);
if(org) params.set('organizacija', org);
params.set('limit', '500');
document.getElementById('docs-out').innerHTML = '<div class="empty">Učitavanje…</div>';
try {
const r = await fetch('/sport/api/v2/dokumenti?'+params.toString());
const d = await r.json();
_docsCache = d.rows || d.dokumenti || [];
document.getElementById('stats').innerHTML =
`<b>${_docsCache.length}</b> dokumenata po filtru (filter: ${[vrsta,sport,godina,org,q].filter(Boolean).join(', ') || 'bez filtera'})`;
paint();
} catch(e) {
document.getElementById('docs-out').innerHTML = '<div class="empty">Greška: '+esc(e.message)+'</div>';
}
}
loadDocs();
</script>
<script src="/static/_ai_widget.js" defer></script>
</body>
</html>