Dashboard
Přehled aktuálních příležitostí
LIVE — aktualizováno před 3s
Aktivní Surebety
načítám…
Nejlepší ROI
Valuebety dnes
EV+ příležitosti
Steam moves
Sledujte velké peníze
🔥 Top surebety
Zobrazit vše →
💰 Velké pohyby kurzů
Zobrazit vše →
⭐ Top valuebety
Zobrazit vše →
👥 Tipsteři — konsenzus dne
Zobrazit vše →
i
Surebety / arbitráž: Vsadíte na všechny výsledky u různých sázkovek tak, abyste vydělali bez ohledu na výsledek. Klikněte na řádek pro otevření kalkulačky rozdělení sázek.
Aktivní arbitrážní příležitosti
i
Valuebety: Sázky, kde nabízený kurz je výhodnější než „spravedlivý" kurz odvozený z Pinnacle (po odečtení marže). Pozitivní očekávaná hodnota (EV+).
Valuebety podle EV
i
Velké peníze / Sharp money: Detekce zápasů, kde se kurz výrazně pohnul oproti otevíracímu kurzu. Velký pohyb = sázejí velcí hráči = signál, že trh ví něco, co my zatím ne.
Detekované pohyby kurzů
i
Tipsteři: Sledujeme nejlepší tipsterské účty z české scény (Telegram, Tiplix, Forebet). Když se 5+ tipsterů shodne na stejném tipu, je to silný konsenzus.
🎯 Konsenzus dne
Zápasy, kde se shoduje 5+ tipsterů

Top tipsteři podle ROI (90 dní)

i
Live kurzy: Srovnání kurzů ze všech českých sázkovek pro všechny aktuální zápasy. Nejlepší kurz je zvýrazněn zeleně.
Surebet kalkulačka

Zadejte kurzy z jednotlivých sázkovek a celkovou sázku — kalkulačka spočítá optimální rozdělení.

📋
Historie sázek
Zde uvidíš historii svých sázek včetně ROI a profit/loss. (Připravujeme)
⚙️
Nastavení účtu
Předplatné, notifikace, preferované sázkovky, sporty. (Připravujeme)
class="onboarding-summary-row">Sporty${ONB_STATE.sports.length} vybráno
Sázkovky${ONB_STATE.bookmakers.length} napojeno
Bankroll${ONB_STATE.bankroll.toLocaleString('cs')} Kč
Notifikace${ONB_STATE.alerts.length || 'Žádné'}
Min. ROI≥ ${ONB_STATE.minRoi}%
🎁 Dostáváš 14 dní Pro plánu zdarma
Bez platební karty. Zruš kdykoli.
`, onMount: () => {}, canNext: () => true, isFinal: true, }), ]; function renderOnboardingStep() { const step = ONB_STEPS[ONB_STATE.step](); document.querySelectorAll('#onb-progress .onboarding-step-bar').forEach((b, i) => { b.classList.toggle('done', i < ONB_STATE.step); b.classList.toggle('current', i === ONB_STATE.step); }); $('#onb-body').innerHTML = `
${step.eyebrow}

${step.title}

${step.sub}

${step.body}
${ONB_STATE.step > 0 && !step.isFinal ? '' : ''}
`; step.onMount(); ONB_STATE._step = step; updateNextBtn(); } function updateNextBtn() { const btn = $('#onb-next'); if (!btn) return; const can = ONB_STATE._step.canNext(); btn.disabled = !can; if (!can && ONB_STATE._step.nextHint) { const hint = ONB_STATE._step.nextHint(); btn.textContent = hint || (ONB_STATE._step.isFinal ? 'Spustit aplikaci →' : 'Pokračovat →'); } else { btn.textContent = ONB_STATE._step.isFinal ? 'Spustit aplikaci →' : 'Pokračovat →'; } } function onbNext() { if (ONB_STATE.step < ONB_STEPS.length - 1) { ONB_STATE.step++; renderOnboardingStep(); } } function onbBack() { if (ONB_STATE.step > 0) { ONB_STATE.step--; renderOnboardingStep(); } } function openOnboarding() { ONB_STATE.step = 0; $('#onboarding').classList.add('show'); renderOnboardingStep(); } function closeOnboarding() { $('#onboarding').classList.remove('show'); try { localStorage.setItem('surebet_onb_done', '1'); } catch(e) {} } function finishOnboarding() { closeOnboarding(); showToast('✓ Profil nastaven – vítej v SureBet CZ'); } window.addEventListener('load', () => { let done = false; try { done = !!localStorage.getItem('surebet_onb_done'); } catch(e) {} if (!done) setTimeout(() => openOnboarding(), 800); }); /* ============== DASHBOARD STAT CARDS ============== */ function renderDashboardStats() { const sbs = MATCHES.map(m => ({m, sb: findSurebets(m)})).filter(x => x.sb.roi > 0).sort((a,b)=>b.sb.roi - a.sb.roi); const vbs = []; MATCHES.forEach(m => findValuebets(m).forEach(vb => vbs.push(vb))); const sms = []; MATCHES.forEach(m => findSharpMoves(m).forEach(mv => sms.push(mv))); const steam = sms.filter(mv => Math.abs(mv.avg_change) > 10); $('#stat-surebets-count').textContent = sbs.length; $('#stat-surebets-trend').textContent = sbs.length ? `Top ${Math.min(3, sbs.length)} sledováno v reálném čase` : 'Aktuálně žádné'; $('#stat-best-roi').textContent = sbs.length ? `${sbs[0].sb.roi.toFixed(2)} %` : '—'; $('#stat-best-match').textContent = sbs.length ? `${sbs[0].m.home} — ${sbs[0].m.away}` : '—'; $('#stat-valuebets-count').textContent = vbs.length; $('#stat-steam-count').textContent = steam.length; } /* ============== RE-RENDER VŠECH SEKCÍ NA ZMĚNU FILTRU ============== */ function rerenderAll() { renderDashboard(); renderDashboardStats(); renderSurebets(); renderValuebets(); renderSharpMoney(); renderLiveOdds(); } /* ============== FILTER + SEARCH HANDLERY ============== */ function bindFilterHandlers() { $$('.filter-bar').forEach(bar => { const group = bar.dataset.filterGroup; if (!group) return; bar.querySelectorAll('.filter-chip').forEach(chip => { chip.addEventListener('click', () => { bar.querySelectorAll('.filter-chip').forEach(c => c.classList.remove('active')); chip.classList.add('active'); if (group === 'surebets' && chip.dataset.sport) FILTER_STATE.surebets.sport = chip.dataset.sport; else if (group === 'valuebets' && chip.dataset.sport) FILTER_STATE.valuebets.sport = chip.dataset.sport; else if (group === 'sharp' && chip.dataset.severity) FILTER_STATE.sharp.severity = chip.dataset.severity; else if (group === 'live' && chip.dataset.sport) FILTER_STATE.live.sport = chip.dataset.sport; persistFilters(); rerenderAll(); }); }); bar.querySelectorAll('select').forEach(sel => { sel.addEventListener('change', () => { if (group === 'surebets') { if (sel.dataset.minRoi !== undefined) FILTER_STATE.surebets.minRoi = parseFloat(sel.value); if (sel.dataset.sort !== undefined) FILTER_STATE.surebets.sort = sel.value; } else if (group === 'valuebets') { if (sel.dataset.minEv !== undefined) FILTER_STATE.valuebets.minEv = parseFloat(sel.value); if (sel.dataset.sort !== undefined) FILTER_STATE.valuebets.sort = sel.value; } persistFilters(); rerenderAll(); }); }); }); const search = $('#topbar-search-input'); if (search) { let timer; search.addEventListener('input', () => { clearTimeout(timer); timer = setTimeout(() => { FILTER_STATE.search = search.value.trim(); rerenderAll(); }, 200); }); } } function applyFiltersToUI() { const setActiveChip = (group, attr, value) => { const bar = document.querySelector(`.filter-bar[data-filter-group="${group}"]`); if (!bar) return; bar.querySelectorAll('.filter-chip').forEach(c => { c.classList.toggle('active', c.dataset[attr] === value); }); }; setActiveChip('surebets', 'sport', FILTER_STATE.surebets.sport); setActiveChip('valuebets', 'sport', FILTER_STATE.valuebets.sport); setActiveChip('sharp', 'severity', FILTER_STATE.sharp.severity); setActiveChip('live', 'sport', FILTER_STATE.live.sport); const setSelectVal = (group, attr, value) => { const sel = document.querySelector(`.filter-bar[data-filter-group="${group}"] select[data-${attr}]`); if (sel) sel.value = String(value); }; setSelectVal('surebets', 'min-roi', FILTER_STATE.surebets.minRoi); setSelectVal('surebets', 'sort', FILTER_STATE.surebets.sort); setSelectVal('valuebets', 'min-ev', FILTER_STATE.valuebets.minEv); setSelectVal('valuebets', 'sort', FILTER_STATE.valuebets.sort); } function applyOnboardingToFilters() { if (ONB_STATE.sports.length === 1) { const s = ONB_STATE.sports[0]; if (['fotbal', 'hokej', 'tenis', 'basketbal'].includes(s)) { FILTER_STATE.surebets.sport = s; FILTER_STATE.valuebets.sport = s; FILTER_STATE.live.sport = s; } } if (ONB_STATE.minRoi !== undefined && ONB_STATE.minRoi >= 0) { FILTER_STATE.surebets.minRoi = ONB_STATE.minRoi; } persistFilters(); applyFiltersToUI(); rerenderAll(); } const _origFinishOnboarding = finishOnboarding; finishOnboarding = function() { _origFinishOnboarding(); applyOnboardingToFilters(); }; /* ============== VALUEBET "OTEVŘÍT" ACTION ============== */ function openValuebet(matchId, bm, side, odd, ev) { const m = MATCHES.find(mm => mm.id === matchId); if (!m) return; showToast(`${sideLabel(side, m)} @ ${bmName(bm)} ${odd.toFixed(2)} (EV +${ev.toFixed(2)}%) — otevři účet u ${bmName(bm)} pro sázku`); } /* ============== INIT ============== */ renderBookmakerFilter(); renderDashboardStats(); renderDashboard(); renderSurebets(); renderValuebets(); renderSharpMoney(); renderTipsters(); renderLiveOdds(); calculateManual(); bindFilterHandlers(); applyFiltersToUI(); rerenderAll(); et(matchId, bm, side, odd, ev) { const m = MATCHES.find(mm => mm.id === matchId); if (!m) return; showToast(`${sideLabel(side, m)} @ ${bmName(bm)} ${odd.toFixed(2)} (EV +${ev.toFixed(2)}%) — otevri ucet u ${bmName(bm)} pro sazku`); } /* ============== INIT ============== */ renderBookmakerFilter(); renderDashboardStats(); renderDashboard(); renderSurebets(); renderValuebets(); renderSharpMoney(); renderTipsters(); renderLiveOdds(); calculateManual(); bindFilterHandlers(); applyFiltersToUI(); rerenderAll(); ml>