Branding & Code Refresh: Reverted to image assets (logo.png/bg.png) and applied consistent formatting

This commit is contained in:
2026-04-16 18:39:32 +02:00
parent fe3c45b8bf
commit 34153c3c15
6 changed files with 44 additions and 107 deletions
+13 -20
View File
@@ -34,6 +34,11 @@ function normalizeText(t) {
.replace(/[^a-z0-9]/g, '');
}
function Logo({ size }) {
const cls = size === 'lg' ? 'w-24 h-24' : size === 'md' ? 'w-16 h-16' : 'w-10 h-10';
return <img src="/img/logo.png" alt="Quizalarm" className={`${cls} mx-auto`} />;
}
/* ================================================================== */
/* Shared Components */
/* ================================================================== */
@@ -148,8 +153,8 @@ function BackButton({ onClick, label }) {
function HomePage({ navigate }) {
return (
<div className="min-h-screen flex flex-col items-center justify-center p-6">
<div className="text-6xl mb-2">🚨</div>
<h1 className="text-5xl font-extrabold mb-2 fire-gradient">Quizalarm</h1>
<Logo size="lg" />
<h1 className="text-5xl font-extrabold mb-2 mt-4 fire-gradient">Quizalarm</h1>
<p className="text-gray-400 mb-10 text-lg">Lernen. Quizzen. Wissen.</p>
<div className="w-full max-w-sm space-y-4">
<button onClick={() => navigate('join')} className="w-full py-4 bg-red-600 hover:bg-red-700 rounded-xl text-xl font-bold transition-all shadow-lg shadow-red-900/30">🎮 Live-Quiz beitreten</button>
@@ -177,7 +182,7 @@ function JoinPage({ navigate }) {
<div className="min-h-screen flex flex-col items-center justify-center p-6">
<h2 className="text-3xl font-bold mb-6">🎮 Live-Quiz beitreten</h2>
<div className="w-full max-w-sm space-y-4">
<input className="w-full p-4 rounded-xl bg-gray-800 text-white text-center text-2xl tracking-widest border-2 border-gray-700 focus:border-red-500 outline-none uppercase" placeholder="CODE" value={code} onChange={(e) => setCode(e.target.value)} maxLength={6} />
<input className="w-full p-4 rounded-xl bg-gray-800 text-white text-center text-2xl tracking-widest border-2 border-gray-700 focus:border-red-500 outline-none uppercase" placeholder="CODE" value={code} onChange={(e) => setCode(e.target.value)} maxLength={20} />
<input className="w-full p-4 rounded-xl bg-gray-800 text-white text-center text-xl border-2 border-gray-700 focus:border-red-500 outline-none" placeholder="Dein Name" value={name} onChange={(e) => setName(e.target.value)} maxLength={20} onKeyDown={(e) => e.key === 'Enter' && handleJoin()} />
{error && <p className="text-red-400 text-center">{error}</p>}
<button onClick={handleJoin} className="w-full py-4 bg-red-600 hover:bg-red-700 rounded-xl text-xl font-bold shadow-lg shadow-red-900/30">Beitreten</button>
@@ -341,7 +346,7 @@ function LivePlayPage({ params, navigate }) {
}
/* ================================================================== */
/* Solo Select Page — with progress check */
/* Solo Select Page */
/* ================================================================== */
function SoloSelectPage({ navigate }) {
@@ -366,7 +371,6 @@ function SoloSelectPage({ navigate }) {
navigate('solo-quiz', { setId, setName: setName2, name: name.trim(), shuffle: doShuffle });
}
} catch (e) {
// If progress check fails, just start fresh
navigate('solo-quiz', { setId, setName: setName2, name: name.trim(), shuffle: doShuffle });
}
setChecking(false);
@@ -402,7 +406,6 @@ function SoloSelectPage({ navigate }) {
</label>
{error && <p className="text-red-400">{error}</p>}
{/* Progress dialog */}
{progressDialog && (
<div className="bg-gray-800 rounded-xl p-5 border-2 border-amber-500 space-y-3">
<h3 className="font-bold text-lg text-amber-400">📌 Gespeicherter Fortschritt</h3>
@@ -433,7 +436,7 @@ function SoloSelectPage({ navigate }) {
}
/* ================================================================== */
/* Solo Quiz Page — immediate save per answer + continue support */
/* Solo Quiz Page */
/* ================================================================== */
function SoloQuizPage({ params, navigate }) {
@@ -457,11 +460,8 @@ function SoloQuizPage({ params, navigate }) {
useEffect(() => {
api.get(`/api/sets/${params.setId}/questions`).then((qs) => {
setAllQuestions(qs);
// Filter out already answered questions
let remaining = qs.filter((q) => !priorIds.current.has(q.id));
if (params.shuffle && remaining.length > 0) {
remaining = shuffleArray(remaining);
}
if (params.shuffle && remaining.length > 0) remaining = shuffleArray(remaining);
setQuestions(remaining);
}).catch((e) => setError(e.message));
}, []);
@@ -476,7 +476,6 @@ function SoloQuizPage({ params, navigate }) {
if (error) return <div className="min-h-screen flex items-center justify-center text-red-400 text-xl p-6 text-center">{error}</div>;
if (!questions.length && allQuestions.length > 0) {
// All questions already answered → go straight to results
const allResults = priorResults.map((a) => ({ Frage_ID: a.Frage_ID, Richtig: a.Richtig, Punkte: a.Punkte }));
return (
<div className="min-h-screen flex flex-col items-center justify-center p-6">
@@ -502,10 +501,7 @@ function SoloQuizPage({ params, navigate }) {
antworten: shuffledAnswers,
};
const feedback = showFeedback ? {
correctKeys, correctText: typ === 'freitext' ? correctText : null, isCorrect,
} : null;
const feedback = showFeedback ? { correctKeys, correctText: typ === 'freitext' ? correctText : null, isCorrect } : null;
const totalProgress = priorIds.current.size + index + 1;
const totalAll = allQuestions.length;
@@ -521,7 +517,6 @@ function SoloQuizPage({ params, navigate }) {
const selectedSet = new Set(selected.map((s) => s.toUpperCase()));
ok = correct.length === selectedSet.size && correct.every((c) => selectedSet.has(c));
}
setCorrectKeys(correct);
setIsCorrect(ok);
setShowFeedback(true);
@@ -537,7 +532,6 @@ function SoloQuizPage({ params, navigate }) {
Session_ID: sessionId.current, Modus: 'Solo', Zeitstempel: new Date().toISOString(),
};
// Save immediately to Baserow
setSaving(true);
api.post('/api/results/single', answerData)
.catch((e) => console.error('Save error:', e))
@@ -594,7 +588,7 @@ function SoloQuizPage({ params, navigate }) {
}
/* ================================================================== */
/* Solo Result Page — matches by Frage_ID */
/* Solo Result Page */
/* ================================================================== */
function SoloResultPage({ params, navigate }) {
@@ -603,7 +597,6 @@ function SoloResultPage({ params, navigate }) {
const correct = results.filter((r) => r.Richtig).length;
const pct = total > 0 ? Math.round((correct / total) * 100) : 0;
// Map questions by ID for category lookup
const qMap = {};
(questions || []).forEach((q) => { qMap[q.id] = q; });