UI Refresh & Logic Updates: New answer color scheme, improved Boolean/Number handling for results, and localized formatting.
This commit is contained in:
+11
-16
@@ -16,23 +16,22 @@
|
||||
background: #111111 url('/img/bg.png') center/cover fixed;
|
||||
}
|
||||
|
||||
/* Answer button base colors */
|
||||
.answer-a {
|
||||
background: #dc2626;
|
||||
}
|
||||
|
||||
.answer-a:hover {
|
||||
background: #b91c1c;
|
||||
}
|
||||
|
||||
.answer-b {
|
||||
background: #2563eb;
|
||||
}
|
||||
|
||||
.answer-b:hover {
|
||||
.answer-a:hover {
|
||||
background: #1d4ed8;
|
||||
}
|
||||
|
||||
.answer-b {
|
||||
background: #7c3aed;
|
||||
}
|
||||
|
||||
.answer-b:hover {
|
||||
background: #6d28d9;
|
||||
}
|
||||
|
||||
.answer-c {
|
||||
background: #d97706;
|
||||
}
|
||||
@@ -42,14 +41,13 @@
|
||||
}
|
||||
|
||||
.answer-d {
|
||||
background: #16a34a;
|
||||
background: #0891b2;
|
||||
}
|
||||
|
||||
.answer-d:hover {
|
||||
background: #15803d;
|
||||
background: #0e7490;
|
||||
}
|
||||
|
||||
/* Selected state */
|
||||
.answer-a.selected,
|
||||
.answer-b.selected,
|
||||
.answer-c.selected,
|
||||
@@ -58,7 +56,6 @@
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
/* Disabled state */
|
||||
.answer-a.disabled,
|
||||
.answer-b.disabled,
|
||||
.answer-c.disabled,
|
||||
@@ -67,7 +64,6 @@
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Ensure Tailwind doesn't override answer button styles */
|
||||
button.answer-a,
|
||||
button.answer-b,
|
||||
button.answer-c,
|
||||
@@ -83,7 +79,6 @@
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
/* Fire gradient for headings */
|
||||
.fire-gradient {
|
||||
background: linear-gradient(135deg, #dc2626, #f59e0b);
|
||||
-webkit-background-clip: text;
|
||||
|
||||
+20
-30
@@ -158,8 +158,9 @@ function StatsPage() {
|
||||
const u = a['Nutzername'] || 'Unbekannt';
|
||||
if (!users[u]) users[u] = { total: 0, correct: 0, points: 0 };
|
||||
users[u].total++;
|
||||
if (a['Richtig']) users[u].correct++;
|
||||
users[u].points += a['Punkte'] || 0;
|
||||
const richtig = a['Richtig'];
|
||||
if (richtig === true || richtig === 'true' || richtig === 1) users[u].correct++;
|
||||
users[u].points += Number(a['Punkte']) || 0;
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -167,21 +168,11 @@ function StatsPage() {
|
||||
<div className="bg-white rounded-xl shadow p-6">
|
||||
<h2 className="text-xl font-bold mb-4">📊 Übersicht</h2>
|
||||
<div className="grid grid-cols-3 gap-4 text-center">
|
||||
<div className="bg-red-50 rounded-lg p-4">
|
||||
<div className="text-2xl font-bold text-red-600">{Object.keys(sessions).length}</div>
|
||||
<div className="text-sm text-gray-500">Sessions</div>
|
||||
</div>
|
||||
<div className="bg-amber-50 rounded-lg p-4">
|
||||
<div className="text-2xl font-bold text-amber-600">{Object.keys(users).length}</div>
|
||||
<div className="text-sm text-gray-500">Teilnehmer</div>
|
||||
</div>
|
||||
<div className="bg-orange-50 rounded-lg p-4">
|
||||
<div className="text-2xl font-bold text-orange-600">{data.answers.length}</div>
|
||||
<div className="text-sm text-gray-500">Antworten</div>
|
||||
</div>
|
||||
<div className="bg-red-50 rounded-lg p-4"><div className="text-2xl font-bold text-red-600">{Object.keys(sessions).length}</div><div className="text-sm text-gray-500">Sessions</div></div>
|
||||
<div className="bg-amber-50 rounded-lg p-4"><div className="text-2xl font-bold text-amber-600">{Object.keys(users).length}</div><div className="text-sm text-gray-500">Teilnehmer</div></div>
|
||||
<div className="bg-orange-50 rounded-lg p-4"><div className="text-2xl font-bold text-orange-600">{data.answers.length}</div><div className="text-sm text-gray-500">Antworten</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl shadow p-6">
|
||||
<h3 className="text-lg font-bold mb-3">👤 Pro Teilnehmer</h3>
|
||||
<input className="w-full p-2 border rounded-lg mb-3 focus:border-red-500 outline-none" placeholder="Filtern..." value={filter} onChange={(e) => setFilter(e.target.value)} />
|
||||
@@ -189,28 +180,27 @@ function StatsPage() {
|
||||
<table className="w-full text-sm">
|
||||
<thead><tr className="border-b"><th className="text-left py-2">Name</th><th>Richtig</th><th>Gesamt</th><th>Quote</th><th>Punkte</th></tr></thead>
|
||||
<tbody>
|
||||
{Object.entries(users)
|
||||
.filter(([u]) => !filter || u.toLowerCase().includes(filter.toLowerCase()))
|
||||
.sort(([, a], [, b]) => b.points - a.points)
|
||||
.map(([u, v]) => (
|
||||
<tr key={u} className="border-b last:border-0">
|
||||
<td className="py-2 font-medium">{u}</td>
|
||||
<td className="text-center text-green-600">{v.correct}</td>
|
||||
<td className="text-center">{v.total}</td>
|
||||
<td className="text-center">{Math.round((v.correct / v.total) * 100)}%</td>
|
||||
<td className="text-center font-bold">{v.points}</td>
|
||||
</tr>
|
||||
))}
|
||||
{Object.entries(users).filter(([u]) => !filter || u.toLowerCase().includes(filter.toLowerCase())).sort(([, a], [, b]) => b.points - a.points).map(([u, v]) => (
|
||||
<tr key={u} className="border-b last:border-0">
|
||||
<td className="py-2 font-medium">{u}</td>
|
||||
<td className="text-center text-green-600">{v.correct}</td>
|
||||
<td className="text-center">{v.total}</td>
|
||||
<td className="text-center">{Math.round((v.correct / v.total) * 100)}%</td>
|
||||
<td className="text-center font-bold">{v.points.toLocaleString('de')}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-xl shadow p-6">
|
||||
<h3 className="text-lg font-bold mb-3">📁 Sessions</h3>
|
||||
{Object.entries(sessions).reverse().map(([sid, s]) => {
|
||||
const total = s.answers.length;
|
||||
const correct = s.answers.filter((a) => a['Richtig']).length;
|
||||
const correct = s.answers.filter((a) => {
|
||||
const v = a['Richtig'];
|
||||
return v === true || v === 'true' || v === 1;
|
||||
}).length;
|
||||
const uniqueUsers = new Set(s.answers.map((a) => a['Nutzername'])).size;
|
||||
return (
|
||||
<div key={sid} className="border-b last:border-0 py-3">
|
||||
@@ -485,7 +475,7 @@ function LiveControlPage({ token, code, ws, initialSession }) {
|
||||
{result?.stats && (
|
||||
<div className="grid grid-cols-2 gap-2 mb-4">
|
||||
{Object.entries(result.stats).map(([k, v]) => (
|
||||
<div key={k} className={`p-2 rounded-lg text-white text-center ${k === 'A' ? 'bg-red-500' : k === 'B' ? 'bg-blue-500' : k === 'C' ? 'bg-amber-500' : 'bg-green-500'}`}>
|
||||
<div key={k} className={`p-2 rounded-lg text-white text-center ${k === 'A' ? 'bg-blue-500' : k === 'B' ? 'bg-purple-500' : k === 'C' ? 'bg-amber-500' : 'bg-cyan-500'}`}>
|
||||
{k}: <strong>{v}</strong>
|
||||
</div>
|
||||
))}
|
||||
|
||||
+6
-3
@@ -705,8 +705,11 @@ function MyResultsPage({ navigate }) {
|
||||
<div className="w-full max-w-md mt-6 space-y-4">
|
||||
{Object.entries(sessions).reverse().map(([sid, s]) => {
|
||||
const total = s.answers.length;
|
||||
const cor = s.answers.filter((a) => a['Richtig']).length;
|
||||
const points = s.answers.reduce((sum, a) => sum + (a['Punkte'] || 0), 0);
|
||||
const cor = s.answers.filter((a) => {
|
||||
const v = a['Richtig'];
|
||||
return v === true || v === 'true' || v === 1;
|
||||
}).length;
|
||||
const points = s.answers.reduce((sum, a) => sum + (Number(a['Punkte']) || 0), 0);
|
||||
return (
|
||||
<div key={sid} className="bg-gray-800 rounded-xl p-4">
|
||||
<div className="flex justify-between items-start mb-2">
|
||||
@@ -716,7 +719,7 @@ function MyResultsPage({ navigate }) {
|
||||
</div>
|
||||
<span className="text-sm text-gray-400">{s.date ? new Date(s.date).toLocaleDateString('de') : ''}</span>
|
||||
</div>
|
||||
<p>{cor}/{total} richtig — {points} Punkte</p>
|
||||
<p>{cor}/{total} richtig — {points.toLocaleString('de')} Punkte</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -113,7 +113,7 @@ function PresentApp() {
|
||||
{question?.typ?.toLowerCase() !== 'freitext' && (
|
||||
<div className="grid grid-cols-2 gap-4 flex-1 max-h-96">
|
||||
{(question?.antworten || []).map((a) => {
|
||||
const colors = { A: 'bg-red-600', B: 'bg-blue-600', C: 'bg-amber-600', D: 'bg-green-600' };
|
||||
const colors = { A: 'bg-blue-600', B: 'bg-purple-600', C: 'bg-amber-600', D: 'bg-cyan-600' };
|
||||
return (
|
||||
<div key={a.key} className={`${colors[a.key] || 'bg-gray-600'} rounded-2xl flex items-center justify-center p-6 text-2xl font-bold`}>{a.text}</div>
|
||||
);
|
||||
|
||||
+3
-5
@@ -16,13 +16,12 @@
|
||||
background: #111111 url('/img/bg.png') center/cover fixed;
|
||||
}
|
||||
|
||||
/* Answer colors for presentation view */
|
||||
.answer-a {
|
||||
background: #dc2626;
|
||||
background: #2563eb;
|
||||
}
|
||||
|
||||
.answer-b {
|
||||
background: #2563eb;
|
||||
background: #7c3aed;
|
||||
}
|
||||
|
||||
.answer-c {
|
||||
@@ -30,10 +29,9 @@
|
||||
}
|
||||
|
||||
.answer-d {
|
||||
background: #16a34a;
|
||||
background: #0891b2;
|
||||
}
|
||||
|
||||
/* Fire gradient for headings */
|
||||
.fire-gradient {
|
||||
background: linear-gradient(135deg, #dc2626, #f59e0b);
|
||||
-webkit-background-clip: text;
|
||||
|
||||
Reference in New Issue
Block a user