Sidebar: +ERP +CRM +Dokumenti, godišnjaci import (18 PDFs), filter helpers
- pgz nav now includes /erp/full, /crm/v2, /admin/users, /dokumenti
- 4 dokumenti endpoints: list, godišnjaci/list, godišnjak/{godina} PDF, detail
- 18 godišnjaka u pgz_sport.dokumenti (2006-2024) with savez_id=333
- PGŽ filter helpers (window._pgz_filter_priority, togglePGZFilter)
- navItemClick handler for nav items with href
This commit is contained in:
+265
-15
@@ -288,6 +288,7 @@ a.tag:hover,.tag[onclick]:hover{transform:translateY(-1px);filter:brightness(1.1
|
||||
<section id="pg-savezi" class="section"></section>
|
||||
<section id="pg-klubovi" class="section"></section>
|
||||
<section id="pg-sportasi" class="section"></section>
|
||||
<section id="pg-igraci-kat" class="section"></section>
|
||||
<section id="pg-financije" class="section"></section>
|
||||
<section id="pg-objekti" class="section"></section>
|
||||
<section id="pg-manifestacije" class="section"></section>
|
||||
@@ -315,6 +316,7 @@ const NAV_ITEMS = [
|
||||
{id:'savezi', ic:'\u{1F3C5}', label:'Savezi'},
|
||||
{id:'klubovi', ic:'⬢', label:'Klubovi'},
|
||||
{id:'sportasi', ic:'\u{1F464}', label:'Sportaši'},
|
||||
{id:'igraci-kat', ic:'\u{1F3F7}', label:'Po kategoriji'},
|
||||
{id:'financije', ic:'€', label:'Financije'},
|
||||
{id:'objekti', ic:'\u{1F4CD}', label:'Objekti'},
|
||||
{id:'manifestacije', ic:'\u{1F4C5}', label:'Manifestacije'},
|
||||
@@ -327,6 +329,7 @@ const SECTION_TITLES = {
|
||||
savezi: ['Savezi', '246 sportskih saveza'],
|
||||
klubovi: ['Klubovi', 'Sportski klubovi PGŽ'],
|
||||
sportasi: ['Sportaši', 'Registrirani članovi'],
|
||||
'igraci-kat': ['Igrači po kategoriji', 'Grupirani po dobnoj/natjecateljskoj kategoriji'],
|
||||
financije: ['Financije', 'Sufinanciranje sporta'],
|
||||
objekti: ['Sportski objekti', 'Geocodirana infrastruktura'],
|
||||
manifestacije: ['Manifestacije', 'Sportski događaji'],
|
||||
@@ -628,6 +631,7 @@ function setSort(section, key){
|
||||
case 'savezi': return applySaveziFilter();
|
||||
case 'klubovi': return applyKluboviFilter();
|
||||
case 'sportasi': return applySportasiFilter();
|
||||
case 'igraci-kat': return applyIgraciKatFilter && applyIgraciKatFilter();
|
||||
case 'objekti': return applyObjektiFilter();
|
||||
case 'manifestacije': return applyManifFilter();
|
||||
case 'financije': return refreshFinancije();
|
||||
@@ -710,6 +714,7 @@ function loadSection(id){
|
||||
case 'savezi': return loadSavezi();
|
||||
case 'klubovi': return loadKlubovi();
|
||||
case 'sportasi': return loadSportasi();
|
||||
case 'igraci-kat': return loadIgraciKat();
|
||||
case 'financije': return loadFinancije();
|
||||
case 'objekti': return loadObjekti();
|
||||
case 'manifestacije': return loadManifestacije();
|
||||
@@ -1133,9 +1138,16 @@ async function loadSavezi(){
|
||||
}
|
||||
function renderSaveziShell(){
|
||||
const root = $('#pg-savezi');
|
||||
const sports = Array.from(new Set((_cache.savezi||[]).map(s=>s.sport).filter(Boolean))).sort();
|
||||
root.innerHTML = `
|
||||
<div class="toolbar">
|
||||
<input type="search" id="sav-q" placeholder="🔍 Pretraži savez…">
|
||||
<select id="sav-sport"><option value="">Svi sportovi</option>${sports.map(s=>'<option value="'+esc(s)+'">'+esc(s)+'</option>').join('')}</select>
|
||||
<select id="sav-kat">
|
||||
<option value="">Sve razine</option>
|
||||
<option value="zupanijski">Županijski</option>
|
||||
<option value="gradski">Gradski</option>
|
||||
</select>
|
||||
<select id="sav-pgz">
|
||||
<option value="">Svi savezi</option>
|
||||
<option value="1">Samo PGŽ relevantni</option>
|
||||
@@ -1149,6 +1161,8 @@ function renderSaveziShell(){
|
||||
<div id="sav-out"></div>
|
||||
`;
|
||||
$('#sav-q').addEventListener('input', debounce(applySaveziFilter, 200));
|
||||
$('#sav-sport').addEventListener('change', applySaveziFilter);
|
||||
$('#sav-kat').addEventListener('change', applySaveziFilter);
|
||||
$('#sav-pgz').addEventListener('change', applySaveziFilter);
|
||||
}
|
||||
function setSaveziView(v){
|
||||
@@ -1160,8 +1174,13 @@ function setSaveziView(v){
|
||||
function applySaveziFilter(){
|
||||
const q = (($('#sav-q')?$('#sav-q').value:'') || '').toLowerCase().trim();
|
||||
const pgz = $('#sav-pgz') ? $('#sav-pgz').value : '';
|
||||
const fSport = $('#sav-sport') ? $('#sav-sport').value : '';
|
||||
const fKat = $('#sav-kat') ? $('#sav-kat').value : '';
|
||||
let rows = _cache.savezi || [];
|
||||
if(q) rows = rows.filter(s => (s.naziv||'').toLowerCase().includes(q) || (s.sport||'').toLowerCase().includes(q));
|
||||
if(fSport) rows = rows.filter(s => (s.sport||'')===fSport);
|
||||
if(fKat==='zupanijski') rows = rows.filter(s => /(?:zupanij|županij)/i.test(s.razina||''));
|
||||
else if(fKat==='gradski') rows = rows.filter(s => /gradsk/i.test(s.razina||''));
|
||||
if(pgz==='1') rows = rows.filter(s => s.pgz_relevant);
|
||||
if(_sort.savezi) rows = sortRows(rows, _sort.savezi.key, _sort.savezi.dir);
|
||||
$('#sav-cnt').textContent = rows.length+' saveza';
|
||||
@@ -1256,11 +1275,40 @@ async function openSavez(id){
|
||||
}
|
||||
|
||||
//=========== KLUBOVI ===========
|
||||
async function loadKlubovi(){
|
||||
async
|
||||
// === PGŽ FINANCIRANI FILTER (CRISIS V4) ===
|
||||
window._klubFilters = window._klubFilters || {financiran: false, godisnjak: false};
|
||||
|
||||
window.toggleKlubFilter = function(name){
|
||||
window._klubFilters[name] = !window._klubFilters[name];
|
||||
loadKlubovi();
|
||||
};
|
||||
|
||||
window.renderKlubFilters = function(targetEl){
|
||||
if(!targetEl) return;
|
||||
const f = window._klubFilters;
|
||||
targetEl.innerHTML = `
|
||||
<label style="margin-right:12px;cursor:pointer;color:var(--t1)">
|
||||
<input type="checkbox" ${f.financiran?'checked':''} onchange="toggleKlubFilter('financiran')" data-filter="financiran">
|
||||
💰 Samo financirani od PGŽ
|
||||
</label>
|
||||
<label style="margin-right:12px;cursor:pointer;color:var(--t1)">
|
||||
<input type="checkbox" ${f.godisnjak?'checked':''} onchange="toggleKlubFilter('godisnjak')" data-filter="godisnjak">
|
||||
📖 U godišnjaku
|
||||
</label>
|
||||
<label style="cursor:pointer;color:var(--t1)">
|
||||
<input type="checkbox" ${f.priority_only?'checked':''} onchange="toggleKlubFilter('priority_only')" data-filter="priority_only">
|
||||
⭐ Samo prioritet (financiran ili godišnjak)
|
||||
</label>
|
||||
`;
|
||||
};
|
||||
|
||||
function loadKlubovi(){
|
||||
const root = $('#pg-klubovi');
|
||||
if(!_cache.klubovi){
|
||||
root.innerHTML = '<div class="loading">Učitavanje klubova…</div>';
|
||||
const d = await api('/klubovi?limit=500');
|
||||
// request all clubs sorted by priority (financed-or-godišnjak first) from backend
|
||||
const d = await api('/klubovi?limit=2500');
|
||||
if(!d){ root.innerHTML='<div class="empty">Greška pri dohvatu</div>'; return; }
|
||||
_cache.klubovi = d.rows || [];
|
||||
}
|
||||
@@ -1276,12 +1324,20 @@ function renderKluboviShell(){
|
||||
<input type="search" id="kl-q" placeholder="🔍 Pretraži klub…">
|
||||
<select id="kl-sport"><option value="">Svi sportovi</option>${sports.map(s=>'<option value="'+esc(s)+'">'+esc(s)+'</option>').join('')}</select>
|
||||
<select id="kl-grad"><option value="">Svi gradovi</option>${grads.map(g=>'<option value="'+esc(g)+'">'+esc(g)+'</option>').join('')}</select>
|
||||
<select id="kl-kat" title="Kategorija">
|
||||
<option value="">Sve kategorije</option>
|
||||
<option value="priority">Samo PGŽ priority</option>
|
||||
<option value="financiran">Samo financirani</option>
|
||||
<option value="godisnjak">Samo u godišnjaku</option>
|
||||
</select>
|
||||
<label><input type="checkbox" id="kl-nk"> Nositelj kvalitete</label>
|
||||
<div class="toggle">
|
||||
<button id="kl-card" class="${_state.viewKlubovi==='card'?'active':''}" onclick="setKluboviView('card')">Kartice</button>
|
||||
<button id="kl-table" class="${_state.viewKlubovi==='table'?'active':''}" onclick="setKluboviView('table')">Tablica</button>
|
||||
</div>
|
||||
<button class="btn" style="margin-left:auto" onclick="enrichBulk('klub', 50, 70)">✨ Obogati sve (50)</button>
|
||||
<button class="btn" onclick="exportKlubovi('xlsx')">⬇ XLSX</button>
|
||||
<button class="btn" onclick="exportKlubovi('csv')">⬇ CSV</button>
|
||||
<button class="btn" onclick="enrichBulk('klub', 50, 70)">✨ Obogati (50)</button>
|
||||
<span class="tb-s" id="kl-cnt"></span>
|
||||
</div>
|
||||
<div id="kl-out"></div>
|
||||
@@ -1289,6 +1345,7 @@ function renderKluboviShell(){
|
||||
$('#kl-q').addEventListener('input', debounce(applyKluboviFilter, 200));
|
||||
$('#kl-sport').addEventListener('change', applyKluboviFilter);
|
||||
$('#kl-grad').addEventListener('change', applyKluboviFilter);
|
||||
$('#kl-kat').addEventListener('change', applyKluboviFilter);
|
||||
$('#kl-nk').addEventListener('change', applyKluboviFilter);
|
||||
}
|
||||
function setKluboviView(v){
|
||||
@@ -1301,12 +1358,16 @@ function applyKluboviFilter(){
|
||||
const q = (($('#kl-q')?$('#kl-q').value:'') || '').toLowerCase().trim();
|
||||
const sport = $('#kl-sport') ? $('#kl-sport').value : '';
|
||||
const grad = $('#kl-grad') ? $('#kl-grad').value : '';
|
||||
const kat = $('#kl-kat') ? $('#kl-kat').value : '';
|
||||
const nk = $('#kl-nk') ? $('#kl-nk').checked : false;
|
||||
let rows = _cache.klubovi || [];
|
||||
if(q) rows = rows.filter(k => (k.klub||'').toLowerCase().includes(q) || (k.sport||'').toLowerCase().includes(q));
|
||||
if(sport) rows = rows.filter(k => k.sport===sport);
|
||||
if(grad) rows = rows.filter(k => k.grad===grad);
|
||||
if(nk) rows = rows.filter(k => k.nositelj_kvalitete);
|
||||
if(kat==='priority') rows = rows.filter(k => k.priority);
|
||||
else if(kat==='financiran') rows = rows.filter(k => k.financiran);
|
||||
else if(kat==='godisnjak') rows = rows.filter(k => k.godisnjak);
|
||||
if(_sort.klubovi) rows = sortRows(rows, _sort.klubovi.key, _sort.klubovi.dir);
|
||||
$('#kl-cnt').textContent = rows.length+' klubova';
|
||||
const top = rows.slice(0, 300);
|
||||
@@ -1314,15 +1375,24 @@ function applyKluboviFilter(){
|
||||
if(rows.length>300){
|
||||
$('#kl-out').insertAdjacentHTML('beforeend', '<div class="empty">… i još '+(rows.length-300)+' klubova. Suzite filtre.</div>');
|
||||
}
|
||||
// Wire tickbox-all & individual checks (no-op if absent)
|
||||
const all = $('#kl-all');
|
||||
if(all){
|
||||
all.addEventListener('change', () => {
|
||||
$$('.kl-pick').forEach(cb => { cb.checked = all.checked; });
|
||||
}, {once:true});
|
||||
}
|
||||
}
|
||||
function renderKluboviGrid(rows){
|
||||
if(!rows.length) return '<div class="empty">Nema rezultata</div>';
|
||||
return '<div class="grid-club">'+rows.map(k => `
|
||||
<div class="entity" onclick="openKlub(${k.id})">
|
||||
${k.nositelj_kvalitete?'<div class="et-tag">N.K.</div>':''}
|
||||
${k.priority?'<div class="et-tag" style="background:#ffd700;color:#1a1a1a">★ PRIO</div>':(k.nositelj_kvalitete?'<div class="et-tag">N.K.</div>':'')}
|
||||
<div class="et">${esc(k.klub||k.sport||'(bez naziva)')}</div>
|
||||
<div class="es">${txt(k.razina,'')} · ${txt(k.grad,'—')}</div>
|
||||
<div class="em">
|
||||
${k.financiran?'<span class="tag gd" title="PGŽ sufinanciran">€</span>':''}
|
||||
${k.godisnjak?'<span class="tag b" title="U godišnjaku">G</span>':''}
|
||||
<span><b>${fmtNum(k.registriranih)}</b> reg.</span>
|
||||
<span><b>${fmtNum(k.trenera)}</b> trenera</span>
|
||||
<span><b>${fmtNum(k.reprezentativaca)}</b> repr.</span>
|
||||
@@ -1332,20 +1402,71 @@ function renderKluboviGrid(rows){
|
||||
function renderKluboviTable(rows){
|
||||
if(!rows.length) return '<div class="empty">Nema rezultata</div>';
|
||||
return `<div class="card" style="padding:0;overflow-x:auto"><table>
|
||||
<thead><tr>${sortHeader('klubovi','klub','Klub','')}${sortHeader('klubovi','sport','Sport','')}${sortHeader('klubovi','razina','Razina','')}${sortHeader('klubovi','grad','Grad','')}${sortHeader('klubovi','registriranih','Reg.','num')}${sortHeader('klubovi','trenera','Trenera','num')}${sortHeader('klubovi','nositelj_kvalitete','Status','')}</tr></thead>
|
||||
<thead><tr><th style="width:34px"><input type="checkbox" id="kl-all" title="Označi sve"></th><th title="PGŽ priority">★</th>${sortHeader('klubovi','klub','Klub','')}${sortHeader('klubovi','sport','Sport','')}${sortHeader('klubovi','razina','Razina','')}${sortHeader('klubovi','grad','Grad','')}${sortHeader('klubovi','registriranih','Reg.','num')}${sortHeader('klubovi','trenera','Trenera','num')}${sortHeader('klubovi','nositelj_kvalitete','Status','')}</tr></thead>
|
||||
<tbody>${rows.map(k => `
|
||||
<tr onclick="openKlub(${k.id})">
|
||||
<td><b>${esc(k.klub||k.sport||'(bez naziva)')}</b></td>
|
||||
<td>${txt(k.sport)}</td>
|
||||
<td>${txt(k.razina)}</td>
|
||||
<td>${txt(k.grad)}</td>
|
||||
<td class="num">${fmtNum(k.registriranih)}</td>
|
||||
<td class="num">${fmtNum(k.trenera)}</td>
|
||||
<td>${k.nositelj_kvalitete?'<span class="tag gd">N.K.</span>':''}${k.aktivan?'<span class="tag gr">AKT</span>':'<span class="tag rd">NK</span>'}</td>
|
||||
<tr>
|
||||
<td onclick="event.stopPropagation()"><input type="checkbox" class="kl-pick" data-id="${k.id}"></td>
|
||||
<td onclick="openKlub(${k.id})">${k.priority?'<span class="tag gd" title="financiran ili u godišnjaku">★</span>':''}</td>
|
||||
<td onclick="openKlub(${k.id})"><b>${esc(k.klub||k.sport||'(bez naziva)')}</b></td>
|
||||
<td onclick="openKlub(${k.id})">${txt(k.sport)}</td>
|
||||
<td onclick="openKlub(${k.id})">${txt(k.razina)}</td>
|
||||
<td onclick="openKlub(${k.id})">${txt(k.grad)}</td>
|
||||
<td onclick="openKlub(${k.id})" class="num">${fmtNum(k.registriranih)}</td>
|
||||
<td onclick="openKlub(${k.id})" class="num">${fmtNum(k.trenera)}</td>
|
||||
<td onclick="openKlub(${k.id})">${k.financiran?'<span class="tag gd" title="financiran">€</span>':''}${k.godisnjak?'<span class="tag b" title="godišnjak">G</span>':''}${k.nositelj_kvalitete?'<span class="tag gd">N.K.</span>':''}${k.aktivan?'<span class="tag gr">AKT</span>':'<span class="tag rd">NK</span>'}</td>
|
||||
</tr>`).join('')}</tbody>
|
||||
</table></div>`;
|
||||
}
|
||||
|
||||
// ─── Sport-aware enrichment helper (cached) ───
|
||||
const _enrichSrcCache = {};
|
||||
async function enrichSourceFor(sport){
|
||||
if(!sport) return null;
|
||||
const k = (sport||'').toLowerCase();
|
||||
if(_enrichSrcCache[k]) return _enrichSrcCache[k];
|
||||
try{
|
||||
const d = await api('/v2/enrich-sources?sport='+encodeURIComponent(sport));
|
||||
if(d && d.match){ _enrichSrcCache[k] = d.match; return d.match; }
|
||||
} catch(e){}
|
||||
return null;
|
||||
}
|
||||
async function openEnrichSourceForKlub(sport, naziv){
|
||||
const src = await enrichSourceFor(sport);
|
||||
if(!src){ window.toast && window.toast('Nema definiranog izvora za sport: '+(sport||'?'), 'warn', 3000); return; }
|
||||
const base = (src.base_url||'').replace(/\/$/,'');
|
||||
let url;
|
||||
if((src.sport||'').toLowerCase() === 'nogomet'){
|
||||
url = base + '/klubovi?q=' + encodeURIComponent(naziv||'');
|
||||
} else {
|
||||
url = base + '/?s=' + encodeURIComponent(naziv||'');
|
||||
}
|
||||
window.open(url, '_blank', 'noopener');
|
||||
}
|
||||
|
||||
// ─── Export of selected klubovi ───
|
||||
async function exportKlubovi(format){
|
||||
const ids = $$('.kl-pick').filter(cb => cb.checked).map(cb => parseInt(cb.dataset.id, 10)).filter(Boolean);
|
||||
if(!ids.length){ window.toast && window.toast('Označite najmanje jedan klub (checkbox)', 'warn', 3000); return; }
|
||||
try{
|
||||
const resp = await fetch(API + '/v2/export/klubovi', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({ids, format})
|
||||
});
|
||||
if(!resp.ok){ window.toast && window.toast('Export greška: HTTP '+resp.status, 'error', 4000); return; }
|
||||
const blob = await resp.blob();
|
||||
const cd = resp.headers.get('Content-Disposition') || '';
|
||||
const m = cd.match(/filename="?([^"]+)"?/);
|
||||
const fname = m ? m[1] : ('pgz_klubovi.' + format);
|
||||
const a = document.createElement('a');
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.download = fname;
|
||||
document.body.appendChild(a); a.click(); a.remove();
|
||||
setTimeout(() => URL.revokeObjectURL(a.href), 5000);
|
||||
window.toast && window.toast('Export gotov: '+ids.length+' klubova → '+format.toUpperCase(), 'success', 3000);
|
||||
} catch(e){ window.toast && window.toast('Export greška: '+(e.message||e), 'error', 4000); }
|
||||
}
|
||||
|
||||
async function openKlub(id){
|
||||
openPanel('Klub', '<div class="loading">Učitavanje kluba…</div>');
|
||||
const k = await api('/klubovi/'+id);
|
||||
@@ -1384,7 +1505,9 @@ async function openKlub(id){
|
||||
|
||||
<div class="tabs">
|
||||
<div class="tab active" onclick="switchKlubTab(this,'k-info')">Info</div>
|
||||
<div class="tab" onclick="switchKlubTab(this,'k-clan')">Sportaši (${clanovi.length})</div>
|
||||
<div class="tab" onclick="switchKlubTab(this,'k-clan')">Roster (${clanovi.length})</div>
|
||||
<div class="tab" onclick="switchKlubTab(this,'k-kat')">Kategorije</div>
|
||||
${(k.sport||'').toLowerCase()==='nogomet' ? '<div class="tab" onclick="switchKlubTab(this,\'k-hns\')">HNS karijera</div>' : ''}
|
||||
<div class="tab" onclick="switchKlubTab(this,'k-pot')">Potpore (${potpore.length})</div>
|
||||
</div>
|
||||
|
||||
@@ -1411,24 +1534,64 @@ async function openKlub(id){
|
||||
👥 Vidi sportaše ovog kluba (${clanovi.length})
|
||||
</a>
|
||||
${(k.web||k.web_stranica) ? '<a class="btn" href="'+esc(k.web||k.web_stranica)+'" target="_blank" style="display:inline-flex;align-items:center;gap:6px">🌐 Službena stranica</a>' : ''}
|
||||
<button class="btn" onclick="openEnrichSourceForKlub(${JSON.stringify(k.sport||'')}, ${JSON.stringify(k.naziv||'')})" style="display:inline-flex;align-items:center;gap:6px">🌐 Obogati podatke (sport-savez)</button>
|
||||
</div>
|
||||
${k.napomena ? '<div class="card" style="margin-top:14px"><div class="card-t" style="margin-bottom:6px">Napomena</div><div style="font-size:12px;color:var(--t1);line-height:1.5">'+esc(k.napomena)+'</div></div>' : ''}
|
||||
</div>
|
||||
|
||||
<div id="k-clan" class="ktab" style="display:none">
|
||||
${clanovi.length ? `<div style="overflow-x:auto;max-height:500px;overflow-y:auto"><table>
|
||||
<thead><tr><th>Sportaš</th><th>Spol</th><th>Pozicija</th><th>Tagovi</th></tr></thead>
|
||||
<thead><tr><th>Sportaš</th><th>Spol</th><th>Pozicija</th><th>Kategorija</th><th>Tagovi</th></tr></thead>
|
||||
<tbody>${clanovi.map(c => `
|
||||
<tr onclick="closePanel();setTimeout(()=>openSportas(${c.id}),250)">
|
||||
<td><b>${esc(c.ime||'')} ${esc(c.prezime||'')}</b></td>
|
||||
<td>${txt(c.spol)}</td>
|
||||
<td>${txt(c.pozicija)}</td>
|
||||
<td>${txt(c.kategorija)}</td>
|
||||
<td>${c.reprezentativac?'<span class="tag gd">REPR</span>':''}${c.kategoriziran?'<span class="tag b">KAT</span>':''}${c.stipendiran?'<span class="tag gr">STIP</span>':''}</td>
|
||||
</tr>`).join('')}
|
||||
</tbody>
|
||||
</table></div>` : '<div class="empty">Nema podataka o sportašima</div>'}
|
||||
</div>
|
||||
|
||||
<div id="k-kat" class="ktab" style="display:none">
|
||||
${(() => {
|
||||
if(!clanovi.length) return '<div class="empty">Nema podataka za grupiranje</div>';
|
||||
const groups = {};
|
||||
clanovi.forEach(c => {
|
||||
const cats = (c.kategorije && c.kategorije.length) ? c.kategorije : [c.kategorija || '(nepoznata)'];
|
||||
cats.forEach(kat => {
|
||||
const key = kat || '(nepoznata)';
|
||||
(groups[key] = groups[key] || []).push(c);
|
||||
});
|
||||
});
|
||||
return Object.keys(groups).sort().map(kat => `
|
||||
<details style="margin-bottom:8px" ${groups[kat].length<=12?'open':''}>
|
||||
<summary style="cursor:pointer;padding:8px;background:rgba(255,255,255,.04);border-radius:6px"><b>${esc(kat)}</b> · ${groups[kat].length} igrač${groups[kat].length===1?'':'a'}</summary>
|
||||
<table style="margin-top:6px"><tbody>${groups[kat].map(c => `
|
||||
<tr onclick="closePanel();setTimeout(()=>openSportas(${c.id}),250)">
|
||||
<td><b>${esc(c.ime||'')} ${esc(c.prezime||'')}</b></td>
|
||||
<td>${txt(c.spol)}</td>
|
||||
<td>${txt(c.pozicija)}</td>
|
||||
</tr>`).join('')}</tbody></table>
|
||||
</details>`).join('');
|
||||
})()}
|
||||
</div>
|
||||
|
||||
${(k.sport||'').toLowerCase()==='nogomet' ? `
|
||||
<div id="k-hns" class="ktab" style="display:none">
|
||||
<div class="card" style="padding:14px">
|
||||
<div class="card-t" style="margin-bottom:8px">⚽ HNS Semafor karijera</div>
|
||||
<div style="font-size:13px;color:var(--t1);line-height:1.6">
|
||||
Klikni na pojedinog igrača (tab "Roster") za detalje sezona, golova i utakmica iz HNS Semafora.
|
||||
${(k.naziv && k.naziv.match(/HNK|NK |GNK|RNK/i)) ? '<br><br><b>Tip:</b> Ovaj klub vjerojatno postoji na HNS Semaforu.' : ''}
|
||||
</div>
|
||||
<div style="margin-top:14px">
|
||||
<button class="btn" onclick="openEnrichSourceForKlub('nogomet', ${JSON.stringify(k.naziv||'')})">🌐 Otvori HNS Semafor pretragu</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>` : ''}
|
||||
|
||||
<div id="k-pot" class="ktab" style="display:none">
|
||||
${potpore.length ? `<div style="overflow-x:auto"><table>
|
||||
<thead><tr><th>Godina</th><th>Naziv</th><th class="num">Iznos</th></tr></thead>
|
||||
@@ -1455,6 +1618,61 @@ function switchKlubTab(el, tabId){
|
||||
if(target) target.style.display='block';
|
||||
}
|
||||
|
||||
//=========== IGRAČI PO KATEGORIJI ===========
|
||||
async function loadIgraciKat(){
|
||||
const root = $('#pg-igraci-kat');
|
||||
root.innerHTML = `
|
||||
<div class="toolbar">
|
||||
<select id="ik-sport"><option value="">Svi sportovi</option></select>
|
||||
<select id="ik-klub"><option value="">Svi klubovi</option></select>
|
||||
<button class="btn primary" onclick="reloadIgraciKat()">↻ Osvježi</button>
|
||||
<span class="tb-s" id="ik-cnt"></span>
|
||||
</div>
|
||||
<div id="ik-out"><div class="loading">Učitavanje…</div></div>
|
||||
`;
|
||||
// Populate sport dropdown from already-cached klubovi if present
|
||||
const sports = Array.from(new Set((_cache.klubovi||[]).map(k=>k.sport).filter(Boolean))).sort();
|
||||
const ss = $('#ik-sport');
|
||||
sports.forEach(s => { const o=document.createElement('option'); o.value=s; o.textContent=s; ss.appendChild(o); });
|
||||
const klubovi = (_cache.klubovi||[]).map(k => [k.id, k.klub||k.naziv]).sort((a,b)=>String(a[1]).localeCompare(String(b[1]),'hr'));
|
||||
const sk = $('#ik-klub');
|
||||
klubovi.slice(0,400).forEach(([id,n]) => { const o=document.createElement('option'); o.value=id; o.textContent=n; sk.appendChild(o); });
|
||||
$('#ik-sport').addEventListener('change', reloadIgraciKat);
|
||||
$('#ik-klub').addEventListener('change', reloadIgraciKat);
|
||||
reloadIgraciKat();
|
||||
}
|
||||
async function reloadIgraciKat(){
|
||||
const sport = $('#ik-sport') ? $('#ik-sport').value : '';
|
||||
const klub = $('#ik-klub') ? $('#ik-klub').value : '';
|
||||
const out = $('#ik-out');
|
||||
out.innerHTML = '<div class="loading">Učitavanje…</div>';
|
||||
let qs = '?limit_per_kat=200';
|
||||
if(sport) qs += '&sport=' + encodeURIComponent(sport);
|
||||
if(klub) qs += '&klub_id=' + encodeURIComponent(klub);
|
||||
const d = await api('/v2/sportasi-by-kategorija' + qs);
|
||||
if(!d || !d.groups){ out.innerHTML = '<div class="empty">Greška pri dohvatu</div>'; return; }
|
||||
$('#ik-cnt').textContent = d.total_kategorija + ' kategorija';
|
||||
if(!d.groups.length){ out.innerHTML = '<div class="empty">Nema rezultata</div>'; return; }
|
||||
out.innerHTML = d.groups.map(g => `
|
||||
<details style="margin-bottom:10px" ${g.count<=12?'open':''}>
|
||||
<summary style="cursor:pointer;padding:10px;background:rgba(255,255,255,.04);border-radius:8px;font-size:14px"><b>${esc(g.kategorija)}</b> · ${g.count} igrač${g.count===1?'':'a'}</summary>
|
||||
<div class="card" style="padding:0;margin-top:6px;overflow-x:auto"><table>
|
||||
<thead><tr><th>Igrač</th><th>Klub</th><th>Sport</th><th>Pozicija</th><th>Godina rođ.</th><th>Tagovi</th></tr></thead>
|
||||
<tbody>${(g.rows||[]).map(c => `
|
||||
<tr onclick="openSportas(${c.id})">
|
||||
<td><b>${esc((c.ime||'')+' '+(c.prezime||''))}</b></td>
|
||||
<td>${txt(c.klub_naziv)}</td>
|
||||
<td>${txt(c.sport)}</td>
|
||||
<td>${txt(c.pozicija)}</td>
|
||||
<td>${c.datum_rodenja ? String(c.datum_rodenja).slice(0,4) : '—'}</td>
|
||||
<td>${c.reprezentativac?'<span class="tag gd">REPR</span>':''}${c.kategoriziran?'<span class="tag b">KAT</span>':''}${c.stipendiran?'<span class="tag gr">STIP</span>':''}</td>
|
||||
</tr>`).join('')}</tbody>
|
||||
</table></div>
|
||||
</details>
|
||||
`).join('');
|
||||
}
|
||||
function applyIgraciKatFilter(){ /* hook for setSort; igraci-kat re-renders via reloadIgraciKat */ }
|
||||
|
||||
//=========== SPORTAŠI ===========
|
||||
async function loadSportasi(){
|
||||
const root = $('#pg-sportasi');
|
||||
@@ -1469,9 +1687,23 @@ async function loadSportasi(){
|
||||
}
|
||||
function renderSportasiShell(){
|
||||
const root = $('#pg-sportasi');
|
||||
const sports = Array.from(new Set((_cache.clanovi||[]).map(c=>c.sport).filter(Boolean))).sort();
|
||||
const klubovi = Array.from(new Map((_cache.clanovi||[]).filter(c=>c.klub_id).map(c=>[c.klub_id, c.klub_naziv_godisnjak||('Klub #'+c.klub_id)])).entries()).sort((a,b)=>String(a[1]).localeCompare(String(b[1]),'hr'));
|
||||
const kats = Array.from(new Set((_cache.clanovi||[]).flatMap(c => (c.kategorije && c.kategorije.length ? c.kategorije : [c.kategorija]).filter(Boolean)))).sort();
|
||||
root.innerHTML = `
|
||||
<div class="toolbar">
|
||||
<input type="search" id="sp-q" placeholder="🔍 Ime ili prezime…">
|
||||
<select id="sp-sport"><option value="">Svi sportovi</option>${sports.map(s=>'<option value="'+esc(s)+'">'+esc(s)+'</option>').join('')}</select>
|
||||
<select id="sp-klub"><option value="">Svi klubovi</option>${klubovi.slice(0,400).map(([id,n])=>'<option value="'+id+'">'+esc(n)+'</option>').join('')}</select>
|
||||
<select id="sp-kat"><option value="">Sve kategorije</option>${kats.map(k=>'<option value="'+esc(k)+'">'+esc(k)+'</option>').join('')}</select>
|
||||
<input type="number" id="sp-god" placeholder="Godina rođ." min="1900" max="2030" style="width:120px">
|
||||
<select id="sp-status">
|
||||
<option value="">Svi statusi</option>
|
||||
<option value="aktivan">Aktivni</option>
|
||||
<option value="reprezentativac">Reprezentativci</option>
|
||||
<option value="kategoriziran">Kategorizirani</option>
|
||||
<option value="stipendiran">Stipendirani</option>
|
||||
</select>
|
||||
<select id="sp-hoo">
|
||||
<option value="">Sve HOO kategorije</option>
|
||||
<option value="1">I. kategorija</option>
|
||||
@@ -1493,6 +1725,11 @@ function renderSportasiShell(){
|
||||
<div id="sp-out"></div>
|
||||
`;
|
||||
$('#sp-q').addEventListener('input', debounce(applySportasiFilter, 200));
|
||||
$('#sp-sport').addEventListener('change', applySportasiFilter);
|
||||
$('#sp-klub').addEventListener('change', applySportasiFilter);
|
||||
$('#sp-kat').addEventListener('change', applySportasiFilter);
|
||||
$('#sp-god').addEventListener('input', debounce(applySportasiFilter, 250));
|
||||
$('#sp-status').addEventListener('change', applySportasiFilter);
|
||||
$('#sp-hoo').addEventListener('change', applySportasiFilter);
|
||||
$('#sp-rep').addEventListener('change', applySportasiFilter);
|
||||
$('#sp-foto').addEventListener('change', applySportasiFilter);
|
||||
@@ -1574,8 +1811,21 @@ function applySportasiFilter(){
|
||||
const hoo = $('#sp-hoo') ? $('#sp-hoo').value : '';
|
||||
const rep = $('#sp-rep') ? $('#sp-rep').checked : false;
|
||||
const foto = $('#sp-foto') ? $('#sp-foto').checked : false;
|
||||
const fSport = $('#sp-sport') ? $('#sp-sport').value : '';
|
||||
const fKlub = $('#sp-klub') ? $('#sp-klub').value : '';
|
||||
const fKat = $('#sp-kat') ? $('#sp-kat').value : '';
|
||||
const fGod = $('#sp-god') ? $('#sp-god').value.trim() : '';
|
||||
const fStat = $('#sp-status') ? $('#sp-status').value : '';
|
||||
let rows = _cache.clanovi || [];
|
||||
if(q) rows = rows.filter(c => ((c.ime||'')+' '+(c.prezime||'')).toLowerCase().includes(q));
|
||||
if(fSport) rows = rows.filter(c => (c.sport||'') === fSport);
|
||||
if(fKlub) rows = rows.filter(c => String(c.klub_id||'') === String(fKlub));
|
||||
if(fKat) rows = rows.filter(c => (c.kategorije && c.kategorije.includes(fKat)) || c.kategorija === fKat);
|
||||
if(fGod) rows = rows.filter(c => String(c.datum_rodenja||c.datum_rodjenja||'').slice(0,4) === fGod);
|
||||
if(fStat === 'aktivan') rows = rows.filter(c => c.aktivan);
|
||||
else if(fStat === 'reprezentativac') rows = rows.filter(c => c.reprezentativac);
|
||||
else if(fStat === 'kategoriziran') rows = rows.filter(c => c.kategoriziran);
|
||||
else if(fStat === 'stipendiran') rows = rows.filter(c => c.stipendiran);
|
||||
if(rep) rows = rows.filter(c => c.reprezentativac);
|
||||
if(foto) rows = rows.filter(c => c.slika_url);
|
||||
if(hoo) rows = rows.filter(c => String(c.hoo_kategorija||c.kategorija_hoo||'')===hoo);
|
||||
|
||||
Reference in New Issue
Block a user