# PGŽ SPORT PLATFORM — CLAUDE CODE HANDOFF ## Datum: 2026-05-05 | Autor: Damir Radulić | dradulic@outlook.com ## URGENTNO: Prezentacija županu sutra ujutro --- ## SITUACIJA Imamo sve podatke u bazi. Trebamo **jedan funkcionalan HTML portal** koji ih prikazuje. Trenutni `sport2.html` je kaotičan - previše iteracija, bugovi se nakupljaju. **Zadatak: Napiši NOVI `sport2.html` od nule. Čist, brz, funkcionalan.** --- ## INFRASTRUKTURA ``` GPU Server: 144.76.68.5 SSH: ssh -p 5852 root@144.76.68.5 (pwd: 5852Dan1TR5852) Bridge API: POST https://api.rinet.one/bridge/exec Header: X-API-KEY: rinet-yS4ZnKlwUqsjk Body: {"cmd": "bash command here"} PostgreSQL: 10.10.0.2:6432 DB: rinet_v3, User: rinet, Pass: R1net2026!SecureDB#v7 Schema: pgz_sport.* PGŽ Sport API: https://sport.rinet.one/sport/api/ Frontend fajl: /opt/pgz-sport/static/sport2.html Service: systemctl restart pgz-sport ``` --- ## BAZA — ŠTO IMAMO (provjereni podaci) ```sql -- Tablice i broj zapisa: pgz_sport.savezi 246 -- savezi u PGŽ pgz_sport.klubovi 2244 -- klubovi (aktivan=TRUE filter) pgz_sport.clanovi 3243 -- sportaši pgz_sport.clan_sezona 689 -- sezonske statistike (pretežno nogomet) pgz_sport.utakmice_log 9267 -- log utakmica s club logovima pgz_sport.clan_godisnjak 2398 -- godišnjaci 2006-2024 pgz_sport.clan_nagrada 2028 -- nagrade pgz_sport.sportski_objekti 106 -- svi geocodirani (lat/lng popunjeni) pgz_sport.manifestacije 113 pgz_sport.sufinanciranje_sport 110 -- financije 2024-2026 pgz_sport.dokumenti 5692 -- PDF dokumenti pgz_sport.proracun 11 -- proračun po godinama -- Sportaš s najboljim podacima (test case): -- ID: 449, Josip Zec, NK OŠK Omišalj, 15 sezona, 257 nastupa, 182 gola -- Ima sliku: https://hns.family/files/images_comet/70/d/... -- Savezi imaju email (scraped iz sport-pgz.hr): -- Atletski savez PGŽ: atletskisavezpgz@gmail.com -- Bočarski savez PGŽ: info@bocarski-savez-pgz.hr -- itd. ``` --- ## API ENDPOINTI (svi rade, testirani) ```bash BASE = https://sport.rinet.one/sport/api GET /dashboard # KPIs, top savezi, proračun GET /savezi?limit=250 # Lista saveza GET /savezi/{id}/full # Detalji saveza + klubovi + clanovi + treneri GET /klubovi?limit=100&sport=X&grad=Y&nositelj=true GET /klubovi/{id} # Detalji kluba + clanovi + potpore GET /clanovi-full?limit=80&q=X&hoo=2&reprezentativac=true GET /sportas/{id}/profil # KLJUČNI endpoint - vraća sve stats # Ima: clan_sezona, utakmice, nagrade, godisnjaci, stats{} GET /sportski-objekti # 106 objekata, svi imaju lat/lng float GET /manifestacije-full # 113 manifestacija GET /sufinanciranje?limit=500&godina=2026&sport=X GET /v2/analytics/proracun-sport?godina=2026 # raspodjela po sportovima GET /v2/potpore/by-year?godina=2026 # primatelji za godinu GET /gradovi # normalizirani popis gradova GET /dokumenti?tip=X&q=Y # PDF dokumenti ``` --- ## ŠTO PORTAL MORA RADITI ### 1. NAVIGACIJA (sidebar ili top tabs) ``` 📊 Dashboard | 🏅 Savezi | ⬡ Klubovi | 👤 Sportaši | € Financije | 📍 Objekti | 📅 Manifestacije | ⚠ Forenzika ``` ### 2. DASHBOARD (prva stranica) - KPI kartice: Saveza (246), Klubova (2244), Sportaša (3243), Proračun 2026 (€8.17M) - Grafikon proračuna po godinama (2016-2026) - Top 10 saveza po broju registriranih - Klik na godinu → otvori panel s popisom primatelja novca ### 3. SAVEZI (grid kartice, klikabilne) - Filter: pretraži naziv, filter po sportu - Card/Table toggle - **KLIK NA SAVEZ → panel desno koji prikazuje:** - Ime, sport, predsjednik, tajnik, email (link), web (link) - 3 broja: Klubova / Sportaša / Trenera - Tabovi: Klubovi (tablica, klikabilna) | Sportaši (kartice, klikabilne) | Treneri ### 4. KLUBOVI (grid kartice, klikabilne) - Filteri: pretraži, sport, grad, razina, nositelj kvalitete checkbox - Card/Table toggle (OBA view puniti odmah, ne čekati klik) - **KLIK NA KLUB → panel koji prikazuje:** - Info: predsjednik, tajnik, OIB, sjedište, savez - Score baza podataka (ima li oib/predsjednika/web itd) - Tabovi: Sportaši | Potpore | Info ### 5. SPORTAŠI — HNS SEMAFOR STIL (najvažnije) - Grid kartica s fotografijom (ako postoji), imenom, sportom, klubom - Filter: pretraži ime, HOO kategorija, samo reprezentativci - Card/Table toggle - **KLIK NA SPORTAŠA → panel koji prikazuje:** ``` ┌─────────────────────────────────────────────┐ │ [FOTO 90x110] Josip Zec │ │ nogomet · Igrač · NK OŠK Omišalj │ │ [Aktivan] [#18] │ │ 📅 1994-01-01 │ ├─────────────────────────────────────────────┤ │ 257 182 0 75 39 15 │ │ NASTUPI GOLOVI ASIST. ŽUTI CRVENI SEZ. │ ├─────────────────────────────────────────────┤ │ [Sezone (15)] [Utakmice (16)] [Bio] [God.] │ ├─────────────────────────────────────────────┤ │ Sezone tab (default): │ │ SEZONA | NATJECANJE | NAS | GOL | ŽUT │ │ 2025/26 | Treća NL Zapad | 16 | 12 | 4 │ │ 2024/25 | 4. NL NS Rijeka| 21 | 11 | 10 │ │ ... │ └─────────────────────────────────────────────┘ ``` API za profil: GET /sport/api/sportas/449/profil Vraća: { ime, prezime, slika_url, sport, pozicija, klub_naziv_full, stats: { ukupno_nastupa, ukupno_pogodaka, ukupno_asistencija, ukupno_zutih, ukupno_crvenih, sezone_aktivne }, clan_sezona: [{sezona, natjecanje, nastupi, pogoci, asistencije, zuti_kartoni, crveni_kartoni, natjecanje_url}], utakmice: [{datum, klub_dom, klub_gost, klub_dom_logo, klub_gost_logo, rezultat, pogodaka, zuti_kartoni, minute}], godisnjak_godine: [2006, 2007, ...] } ### 6. FINANCIJE - Filteri: godina (2024/2025/2026), sport, naziv korisnika - KPI: Ukupno / Broj primatelja / Sportova / Razina - Pie/Bar chart po sportu - Tablica svih primatelja s linkom na izvorni PDF ### 7. SPORTSKI OBJEKTI - Card/Table toggle - Google Maps link: ako ima lat/lng → https://maps.google.com/maps?q={lat},{lng}&z=17 - Embed iframe u kartici ako ima koordinate - Filter: grad, tip (stadion/bazen/dvorana...) ### 8. MANIFESTACIJE - Card/Table toggle - Klik na karticu → otvori source_url ako postoji, inače popup s podacima - Filter: naziv, razina ### 9. FORENZIKA - Lista nalaza s severity (CRITICAL=crvena, HIGH=žuta) - Velimir Liverić profil (ručno hardkodirani jer je politički osjetljiv) ### 10. MREŽA (Network Graf) - D3 force graph - 3 search polja: Osoba | Klub/Savez | Tvrtka - Tip filter: Svi / Osobe / Klubovi / Tvrtke / Forenzički - Klik na čvor → otvori panel s informacijama - Reset gumb --- ## PANEL (desno, slide-in) ```html
Detalji
×
``` --- ## DIZAJN (obavezni CSS vars) ```css :root { --pgz-blue: #003087; --pgz-blue2: #004CC4; --pgz-gold: #F4C430; --bg0: #08090e; --bg1: #0d1021; --bg2: #111628; --bg3: #161d35; --bg4: #1c2542; --rim: #1e2a50; --rim2: #283560; --t0: #fff; --t1: #e2e6f0; --t2: #8a95b4; --t4: #4e5a7a; --green: #00e88f; --red: #ff2d55; --amber: #f59e0b; --cyan: #00c8e8; --font: 'Inter', sans-serif; --mono: 'JetBrains Mono', monospace; } ``` Fonts: Inter + JetBrains Mono (Google Fonts) Libraries: D3.js v7, Chart.js v4 (CDN cdnjs.cloudflare.com) --- ## KRITIČNA PRAVILA 1. **Nikada nemoj patchati stari fajl** — piši novi od nule 2. **Svaka JS funkcija mora biti definirana** — ne pozivaj što nisi napisao 3. **Template literals** — unutar `${}` NE koristiš `\'`, koristiš `'` 4. **Python triple quotes** — ne koristi `'''` u Python stringovima koji generiraju JS 5. **Uvijek provjeri Node.js syntax** prije deploya: `node --check file.js` 6. **Deploy metodologija** (fajl je ~100-120KB): ```python import base64 # Na serveru: python3 -c "import base64; open('/opt/...','wb').write(base64.b64decode('{b64}'))" # Za veće fajlove: split u chunkove od 30KB, append ``` --- ## DEPLOY SCRIPT ```python import subprocess, json, base64 def deploy_file(local_path, remote_path): """Deploy file to server via Bridge API""" BRIDGE = "https://api.rinet.one/bridge/exec" KEY = "rinet-yS4ZnKlwUqsjk" content = open(local_path, 'rb').read() CHUNK = 30000 chunks = [content[i:i+CHUNK] for i in range(0, len(content), CHUNK)] for i, chunk in enumerate(chunks): b64 = base64.b64encode(chunk).decode() mode = 'wb' if i == 0 else 'ab' cmd = f"python3 -c \"import base64; open('{remote_path}','{mode}').write(base64.b64decode('{b64}'))\"" r = subprocess.run(['curl','-sX','POST',BRIDGE, '-H',f'X-API-KEY: {KEY}', '-H','Content-Type: application/json', '-d',json.dumps({"cmd":cmd})], capture_output=True, text=True, timeout=30) print(f"Chunk {i+1}/{len(chunks)}: {'OK' if r.returncode==0 else 'ERR'}") # Restart service r2 = subprocess.run(['curl','-sX','POST',BRIDGE, '-H',f'X-API-KEY: {KEY}', '-H','Content-Type: application/json', '-d',json.dumps({"cmd":"systemctl restart pgz-sport && sleep 2 && curl -s http://localhost:8095/health"})], capture_output=True, text=True) print("Service:", json.loads(r2.stdout).get('stdout','')[-60:]) deploy_file('/home/claude/sport2_new.html', '/opt/pgz-sport/static/sport2.html') ``` --- ## AGENT TASK PODJELA (za tmux swarm) ### Agent W1 — HTML Skeleton + CSS + Navigation ``` Napiši potpuni HTML skeleton s: - CSS varijablama i komponentama - Sidebar navigacija (11 sekcija) - Panel HTML (desno slide-in) - Sve
sekcije prazne - initHeroCanvas() particle funkcija Spremi: /home/claude/sport2_skeleton.html ``` ### Agent W2 — Dashboard + Proračun ``` Implementiraj: - initDash() → GET /sport/api/dashboard → KPI kartice - loadProracun() → chart + klik na godinu - loadProracunDrill(god) → GET /sport/api/v2/potpore/by-year?godina=X Dodaj u skeleton ``` ### Agent W3 — Savezi + openSavez panel ``` Implementiraj: - loadSavezi() → GET /sport/api/savezi?limit=250 - renderSaveziGrid(data) s card i table mode - openSavez(s) → GET /sport/api/savezi/{id}/full → panel s tabovima Sve klikabilno! ``` ### Agent W4 — Klubovi + openKlub panel ``` Implementiraj: - loadKlubovi() s filterima (sport, grad, razina, nositelj) - buildKlubCard(k) + buildKlubTable(rows) - Uvijek puni i kartice i tablicu (ne samo jedan view) - openKlub(id) → GET /sport/api/klubovi/{id} → panel ``` ### Agent W5 — Sportaši + openSportas panel (HNS Semafor) ``` Implementiraj: - loadSportasi() s filterima - buildPlayerCard(c) s fotografijom - openSportas(id) → GET /sport/api/sportas/{id}/profil - Panel: foto + stats bar (nastupi/goli/asist/žuti/crveni/sezone) - Tabovi: Sezone (tablica) | Utakmice (s logovima klubova) | Bio | Godišnjaci ``` ### Agent W6 — Financije + Sufinanciranje ``` Implementiraj: - loadFinancije() → GET /sport/api/sufinanciranje?limit=500 - Filteri: godina, sport, naziv - Chart.js pie/bar chart po sportu - Tablica svih primatelja s linkovima na PDF ``` ### Agent W7 — Sportski Objekti + Google Maps ``` Implementiraj: - loadObjekti() → GET /sport/api/sportski-objekti - buildObjektCard(o): ako ima lat/lng → Maps URL = https://maps.google.com/maps?q={lat},{lng}&z=17 - Iframe embed u kartici za objekte s koordinatama - Card/Table toggle ``` ### Agent W8 — Manifestacije + Mreža ``` Implementiraj: - loadManifest() → klikabilne kartice → source_url ili popup - loadNetwork(q) → GET /sport/api/network/pgz?q=X - D3 force graph s search inputima - Klik na čvor → openPanel s podacima ``` ### Agent W9 — Deploy + QA ``` - Provjeri Node.js syntax: node --check /tmp/sport2_new.js - Deploy skriptu gore - Test svaki endpoint - Provjeri da nema undefined funkcija - Verifikacija: curl -s https://sport.rinet.one/ | grep "function openSavez" ``` ### Agent W0 (Orchestrator) — Merge + Deploy ``` - Čekaj sve agente - Merge svih HTML/JS dijelova u jednu datoteku - Syntax check - Deploy - Test s 10 različitih klikova ``` --- ## VALIDACIJA (svaki agent mora proći ovo) ```bash # 1. Syntax check python3 -c " import re html = open('/home/claude/sport2_new.html').read() m = re.search(r'', html, re.DOTALL) open('/tmp/check.js','w').write(m.group(1)) " node --check /tmp/check.js # 2. Nije undefined curl -s https://sport.rinet.one/ | grep "function openSavez" curl -s https://sport.rinet.one/ | grep "function searchNetwork" curl -s https://sport.rinet.one/ | grep "function openSportas" # 3. API radi curl -s https://sport.rinet.one/sport/api/sportas/449/profil | python3 -c " import json,sys; d=json.load(sys.stdin) assert d.get('stats',{}).get('ukupno_nastupa') == 257, 'Stats broken' print('API OK - Josip Zec:', d['stats']['ukupno_nastupa'], 'nastupa') " ``` --- ## CILJ DO JUTRA 08:00 Portal na https://sport.rinet.one/ koji: 1. Otvori se i prikaže dashboard s KPI brojkama 2. Klik na Savez → panel s klubovima 3. Klik na Klub → panel sa sportašima 4. Klik na Sportaš → profil s karijernim statistikama i fotografijom 5. Financije → kto dobiva javni novac i koliko 6. Objekti → na karti 7. Nema JS grešaka u konzoli **Josip Zec (ID 449) je test case. Mora prikazivati 257 nastupa, 182 gola, 15 sezona.** --- ## NAPOMENE - Damir je umoran. Ne pitaj za permisije. Radi autonomno. - Ako nešto ne radi, debugiraj sam - Ne patchaj stari fajl. Novi od nule. - Koristiš Bridge API za sve server operacije - CSS je dark theme, PGŽ boje (blue #003087, gold #F4C430) - Sve interakcije (klikovi, tabovi, filtri) moraju raditi