feat: implement R42 chat infrastructure with Anthropic API integration and custom design system
This commit is contained in:
@@ -10,9 +10,21 @@ import Button from '../components/ui/Button';
|
||||
import Tag from '../components/ui/Tag';
|
||||
import { useApp } from '../store/AppContext';
|
||||
import { generateWeeklyQuiz, getCachedQuiz, saveTestResult, getTestResult } from '../lib/testService';
|
||||
import { storage } from '../lib/storage';
|
||||
|
||||
const TIMER_SECONDS = 300; // 5 minutes
|
||||
|
||||
function setQuizActive(userId, active) {
|
||||
if (!userId) return;
|
||||
if (active) storage.set(`quiz:active:${userId}`, true);
|
||||
else storage.remove(`quiz:active:${userId}`);
|
||||
try {
|
||||
window.dispatchEvent(new CustomEvent('respellion:quiz-state', { detail: { active } }));
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Helper: format mm:ss ──────────────────────────────────
|
||||
function formatTime(sec) {
|
||||
const m = Math.floor(sec / 60);
|
||||
@@ -65,6 +77,19 @@ const Testen = () => {
|
||||
return () => clearInterval(timerRef.current);
|
||||
}, [phase]);
|
||||
|
||||
// ── Clear quiz-active flag whenever we leave the quiz phase or unmount ──
|
||||
useEffect(() => {
|
||||
if (phase !== 'quiz' && currentUser) {
|
||||
setQuizActive(currentUser.id, false);
|
||||
}
|
||||
}, [phase, currentUser]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (currentUser) setQuizActive(currentUser.id, false);
|
||||
};
|
||||
}, [currentUser]);
|
||||
|
||||
// ── Start quiz ──
|
||||
const startQuiz = async () => {
|
||||
setPhase('loading');
|
||||
@@ -76,6 +101,7 @@ const Testen = () => {
|
||||
setAnswers({});
|
||||
setShowFeedback(false);
|
||||
setTimeLeft(TIMER_SECONDS);
|
||||
setQuizActive(currentUser.id, true);
|
||||
setPhase('quiz');
|
||||
} catch (e) {
|
||||
setError(e.message);
|
||||
|
||||
Reference in New Issue
Block a user