Download admin.html from jaynesmax/futbol: direct link, hf CLI and curl.
- Browser
- Download file 6.01 kB
-
https://huggingface.co/spaces/jaynesmax/futbol/resolve/main/admin.html
- Command line
-
hf download hf://spaces/jaynesmax/futbol/admin.html
-
curl -L -o admin.html https://huggingface.co/spaces/jaynesmax/futbol/resolve/main/admin.html
6.01 kB
| <html lang="sw"><head> | |
| <meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"> | |
| <title>Admin β FUTBOL PICKS</title> | |
| <link rel="stylesheet" href="styles.css"> | |
| </head><body> | |
| <header id="nav"></header> | |
| <main> | |
| <p id="denied" class="err" hidden>Huna ruhusa ya kuona ukurasa huu. <a href="login.html">Ingia</a></p> | |
| <div id="panel" hidden> | |
| <div class="card"> | |
| <h1>1. Ongeza mechi</h1> | |
| <form id="matchForm"> | |
| <div class="grid2"> | |
| <div><label>Ligi / Mashindano</label><input id="mComp" required></div> | |
| <div><label>Nchi (hiari)</label><input id="mCountry"></div> | |
| <div><label>Timu ya nyumbani</label><input id="mHome" required></div> | |
| <div><label>Timu ya ugenini</label><input id="mAway" required></div> | |
| <div><label>Muda wa kuanza</label><input type="datetime-local" id="mKick" required></div> | |
| </div> | |
| <button type="submit" style="margin-top:1rem">Hifadhi mechi</button> | |
| </form> | |
| <p class="msg" id="mMsg"></p> | |
| </div> | |
| <div class="card"> | |
| <h1>2. Ongeza utabiri</h1> | |
| <form id="predForm"> | |
| <label>Mechi</label><select id="pMatch" required></select> | |
| <div class="grid2"> | |
| <div><label>Soko</label><input id="pMarket" placeholder="Mfano: Matokeo, Over 2.5, BTTS" required></div> | |
| <div><label>Uchaguzi</label><input id="pSelection" placeholder="Mfano: Nyumbani, Ndiyo" required></div> | |
| </div> | |
| <label>Maelezo ya uchambuzi</label><textarea id="pExpl" rows="3"></textarea> | |
| <label class="row" style="margin-top:.8rem"><input type="checkbox" id="pPub" style="width:auto"> Chapisha sasa</label> | |
| <button type="submit" style="margin-top:1rem">Hifadhi utabiri</button> | |
| </form> | |
| <p class="msg" id="pMsg"></p> | |
| </div> | |
| <div class="card" style="overflow-x:auto"> | |
| <h1>3. Utabiri wote</h1> | |
| <table> | |
| <thead><tr><th>Mechi</th><th>Soko / Uchaguzi</th><th>Chapisha</th><th>Matokeo</th></tr></thead> | |
| <tbody id="rows"></tbody> | |
| </table> | |
| <p class="msg" id="rMsg"></p> | |
| </div> | |
| </div> | |
| </main> | |
| <script type="module"> | |
| import { sb, esc, fmtDate, renderNav, currentProfile } from "./common.js"; | |
| const $ = id => document.getElementById(id); | |
| const { session, profile } = await currentProfile(); | |
| renderNav("admin", profile); | |
| const say = (id, text, ok = true) => { $(id).className = "msg " + (ok ? "ok" : "err"); $(id).textContent = text; }; | |
| const isAdmin = !!session && profile?.role === "admin"; | |
| if (!isAdmin) { | |
| $("denied").hidden = false; | |
| } else { | |
| $("panel").hidden = false; | |
| await loadMatches(); | |
| await loadPredictions(); | |
| } | |
| async function loadMatches() { | |
| const { data, error } = await sb.from("matches").select("*").order("kickoff_at", { ascending: false }); | |
| if (error) return say("mMsg", error.message, false); | |
| $("pMatch").innerHTML = data.map(m => | |
| `<option value="${m.id}">${esc(m.home_team)} vs ${esc(m.away_team)} β ${fmtDate(m.kickoff_at)}</option>`).join(""); | |
| } | |
| $("matchForm").onsubmit = async e => { | |
| e.preventDefault(); | |
| const { error } = await sb.from("matches").insert({ | |
| competition: $("mComp").value.trim(), | |
| country: $("mCountry").value.trim() || null, | |
| home_team: $("mHome").value.trim(), | |
| away_team: $("mAway").value.trim(), | |
| kickoff_at: new Date($("mKick").value).toISOString() | |
| }); | |
| if (error) return say("mMsg", error.message, false); | |
| e.target.reset(); | |
| say("mMsg", "Mechi imehifadhiwa β"); | |
| loadMatches(); | |
| }; | |
| $("predForm").onsubmit = async e => { | |
| e.preventDefault(); | |
| const published = $("pPub").checked; | |
| const { error } = await sb.from("predictions").insert({ | |
| match_id: $("pMatch").value, | |
| market: $("pMarket").value.trim(), | |
| selection: $("pSelection").value.trim(), | |
| explanation: $("pExpl").value.trim() || null, | |
| published, | |
| published_at: published ? new Date().toISOString() : null, | |
| created_by: session.user.id | |
| }); | |
| if (error) return say("pMsg", error.message, false); | |
| e.target.reset(); | |
| say("pMsg", "Utabiri umehifadhiwa β"); | |
| loadPredictions(); | |
| }; | |
| async function loadPredictions() { | |
| const { data, error } = await sb.from("predictions") | |
| .select("*, matches(home_team,away_team)") | |
| .order("created_at", { ascending: false }); | |
| if (error) return say("rMsg", error.message, false); | |
| $("rows").innerHTML = data.length ? data.map(p => ` | |
| <tr> | |
| <td>${esc(p.matches.home_team)} vs ${esc(p.matches.away_team)}</td> | |
| <td>${esc(p.market)}: <b>${esc(p.selection)}</b></td> | |
| <td><button class="${p.published ? "ghost" : "gold"}" data-pub="${p.id}" data-on="${p.published}"> | |
| ${p.published ? "Ficha" : "Chapisha"}</button></td> | |
| <td> | |
| <select data-res="${p.id}" style="width:auto"> | |
| ${["pending", "won", "lost", "void"].map(r => | |
| `<option value="${r}" ${p.result === r ? "selected" : ""}>${r}</option>`).join("")} | |
| </select> | |
| </td> | |
| </tr>`).join("") : `<tr><td colspan="4">Hakuna utabiri bado.</td></tr>`; | |
| } | |
| $("rows").onclick = async e => { | |
| const btn = e.target.closest("[data-pub]"); | |
| if (!btn) return; | |
| const id = btn.dataset.pub; | |
| const nowPublished = btn.dataset.on !== "true"; | |
| const { data: current } = await sb.from("predictions").select("published_at").eq("id", id).single(); | |
| const { error } = await sb.from("predictions").update({ | |
| published: nowPublished, | |
| // Tarehe ya kwanza ya kuchapisha inabaki, haibadilishwi | |
| published_at: nowPublished ? (current.published_at || new Date().toISOString()) : current.published_at | |
| }).eq("id", id); | |
| if (error) return say("rMsg", error.message, false); | |
| loadPredictions(); | |
| }; | |
| $("rows").onchange = async e => { | |
| const sel = e.target.closest("[data-res]"); | |
| if (!sel) return; | |
| const { error } = await sb.from("predictions").update({ result: sel.value }).eq("id", sel.dataset.res); | |
| if (error) return say("rMsg", error.message, false); | |
| say("rMsg", "Matokeo yamehifadhiwa β"); | |
| }; | |
| </script> | |
| </body></html> | |