feat: implement knowledge testing system with leaderboard, quiz generation, and PocketBase integration

This commit is contained in:
RaymondVerhoef
2026-05-14 16:53:10 +02:00
parent 42d7209773
commit 74ba5d3dc0
15 changed files with 590 additions and 512 deletions

View File

@@ -1,12 +1,12 @@
import React, { createContext, useContext, useReducer, useEffect } from 'react';
import { storage } from '../lib/storage';
import * as db from '../lib/db';
const AppContext = createContext();
const initialState = {
currentUser: null, // will hold user object if logged in
users: [], // array of registered users
weekNumber: 1, // current learning week
currentUser: null,
users: [],
weekNumber: 1,
isLoading: true
};
@@ -20,25 +20,11 @@ function appReducer(state, action) {
isLoading: false
};
case 'LOGIN':
return {
...state,
currentUser: action.payload
};
return { ...state, currentUser: action.payload };
case 'LOGOUT':
return {
...state,
currentUser: null
};
case 'REGISTER_USER':
return {
...state,
users: [...state.users, action.payload]
};
return { ...state, currentUser: null };
case 'ADVANCE_WEEK':
return {
...state,
weekNumber: state.weekNumber + 1
};
return { ...state, weekNumber: state.weekNumber + 1 };
default:
return state;
}
@@ -47,48 +33,31 @@ function appReducer(state, action) {
export function AppProvider({ children }) {
const [state, dispatch] = useReducer(appReducer, initialState);
// Initialize app state from storage
useEffect(() => {
const loadState = () => {
let users = storage.get('users:registry');
// Seed first admin if no users exist
if (!users || users.length === 0) {
const initialAdmin = {
id: 'u_1',
name: 'Admin',
role: 'admin',
pin: '0000',
registeredAt: new Date().toISOString()
};
users = [initialAdmin];
storage.set('users:registry', users);
// Also seed initial empty leaderboard
storage.set('leaderboard:current', []);
}
const storedWeek = storage.get('admin:current_week') || 1;
const loadState = async () => {
let members = await db.getTeamMembers();
if (!members || members.length === 0) {
const created = await db.addTeamMember({ name: 'Admin', role: 'admin', pin: '0000' });
members = [created];
}
const storedWeek = Number(await db.getSetting('admin:current_week', 1));
// Automatically login if we saved session (optional, simpler to require login per session)
const sessionUserId = sessionStorage.getItem('respellion_session');
if (sessionUserId) {
const user = users.find(u => u.id === sessionUserId);
const user = members.find(u => u.id === sessionUserId);
if (user) {
dispatch({ type: 'LOGIN', payload: user });
}
}
dispatch({
type: 'INIT_APP',
payload: { users, weekNumber: storedWeek }
});
dispatch({ type: 'INIT_APP', payload: { users: members, weekNumber: storedWeek } });
};
loadState();
loadState().catch(console.error);
}, []);
// Expose dispatch actions as convenient methods
const login = (userId, pin) => {
const user = state.users.find(u => u.id === userId && u.pin === pin);
if (user) {