File size: 4,065 Bytes
66dca15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>BOU 2026 – Results (organizer)</title>
<style>
  :root{
    --bg:#f4f5f7; --card:#ffffff; --text:#1b1e24; --muted:#636a76;
    --accent:#2f5ed1; --border:#dfe2e8; --track:#eef0f3;
  }
  @media (prefers-color-scheme: dark){
    :root{
      --bg:#14161b; --card:#1d2027; --text:#eef0f3; --muted:#9aa1ad;
      --accent:#6e94f2; --border:#2b2f38; --track:#262a32;
    }
  }
  *{box-sizing:border-box;}
  body{margin:0; background:var(--bg); color:var(--text); font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;}
  .wrap{max-width:560px; margin:0 auto; padding:32px 18px 70px;}
  h1{font-size:1.3rem; margin:0 0 18px;}
  input{width:100%; padding:10px 12px; border-radius:10px; border:1px solid var(--border); background:var(--card); color:var(--text); margin-bottom:10px;}
  button, a.btn{display:inline-block; padding:10px 16px; border:none; border-radius:10px; background:var(--accent); color:#fff; font-weight:600; cursor:pointer; text-decoration:none; font-size:.9rem;}
  .card{background:var(--card); border:1px solid var(--border); border-radius:14px; padding:14px 16px; margin-bottom:10px;}
  .row{display:flex; justify-content:space-between; align-items:baseline;}
  .proj{font-weight:600;}
  .presenter{color:var(--muted); font-size:.85rem;}
  .pct{font-weight:600; color:var(--accent);}
  .track{height:8px; background:var(--track); border-radius:5px; margin-top:8px; overflow:hidden;}
  .fill{height:100%; background:var(--accent); width:0%;}
  .count{font-size:.75rem; color:var(--muted); margin-top:4px;}
  .toolbar{display:flex; gap:10px; margin:16px 0 22px; align-items:center;}
  .msg{font-size:.85rem; color:var(--muted);}
</style>
</head>
<body>
<div class="wrap">
  <h1>BOU 2026 — Results (organizer only)</h1>
  <div id="gate">
    <input id="key" type="password" placeholder="Admin key">
    <button id="loadBtn">View results</button>
  </div>
  <div id="dash" style="display:none">
    <div class="toolbar">
      <a class="btn" id="exportLink" href="#">Download Excel log</a>
      <span class="msg" id="total"></span>
    </div>
    <div id="results"></div>
  </div>
  <div class="msg" id="err"></div>
</div>
<script>
const keyEl = document.getElementById("key");
const err = document.getElementById("err");

async function load(){
  const key = keyEl.value.trim();
  if (!key) return;
  sessionStorage.setItem("adminKey", key);
  err.textContent = "";
  try{
    const res = await fetch("/api/results?key=" + encodeURIComponent(key));
    const data = await res.json();
    if (!data.ok){ err.textContent = data.error || "Could not load results."; return; }
    document.getElementById("gate").style.display = "none";
    document.getElementById("dash").style.display = "block";
    document.getElementById("exportLink").href = "/api/export?key=" + encodeURIComponent(key);
    render(data);
  } catch(e){
    err.textContent = "Network error.";
  }
}

function render(data){
  const resultsEl = document.getElementById("results");
  const total = data.total || 0;
  document.getElementById("total").textContent = total ? total + " vote" + (total===1?"":"s") + " recorded" : "No votes yet";
  resultsEl.innerHTML = "";
  data.projects.forEach(p => {
    const c = data.counts[p.id] || 0;
    const pct = total ? Math.round((c/total)*100) : 0;
    const div = document.createElement("div");
    div.className = "card";
    div.innerHTML = `
      <div class="row">
        <div><div class="proj">${p.name}</div><div class="presenter">${p.who}</div></div>
        <div class="pct">${pct}%</div>
      </div>
      <div class="track"><div class="fill" style="width:${pct}%"></div></div>
      <div class="count">${c} vote${c===1?"":"s"}</div>
    `;
    resultsEl.appendChild(div);
  });
}

document.getElementById("loadBtn").addEventListener("click", load);
const saved = sessionStorage.getItem("adminKey");
if (saved){ keyEl.value = saved; load(); }
</script>
</body>
</html>