feat: implement onboarding process and enrollment status tracking for users
This commit is contained in:
@@ -161,7 +161,7 @@ const Dashboard = () => {
|
||||
<div>
|
||||
<h3 className="text-xl">Learning</h3>
|
||||
<p className="text-fg-muted text-sm mt-1">
|
||||
{curriculumActive ? `Week ${weekNumber} topic:` : 'Your topic this week:'}
|
||||
{curriculumActive ? `Week ${currWeek} topic:` : 'Your topic this week:'}
|
||||
</p>
|
||||
</div>
|
||||
{learnDone ? <Tag variant="success">Completed</Tag> : <Tag variant="accent">To Do</Tag>}
|
||||
|
||||
74
src/pages/Onboarding.jsx
Normal file
74
src/pages/Onboarding.jsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import { useState } from 'react';
|
||||
import { useNavigate, Navigate } from 'react-router-dom';
|
||||
import { BookOpen, ArrowRight, LogOut } from 'lucide-react';
|
||||
import { useApp } from '../store/AppContext';
|
||||
import Card from '../components/ui/Card';
|
||||
import Button from '../components/ui/Button';
|
||||
|
||||
const Onboarding = () => {
|
||||
const { state, enrollCurrentUser, logout } = useApp();
|
||||
const navigate = useNavigate();
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
if (state.isLoading) return <div className="p-8">Loading...</div>;
|
||||
if (!state.currentUser) return <Navigate to="/login" replace />;
|
||||
if (state.currentUser.enrollment_status === 'active') {
|
||||
return <Navigate to="/" replace />;
|
||||
}
|
||||
|
||||
const handleStart = async () => {
|
||||
setBusy(true);
|
||||
setError('');
|
||||
try {
|
||||
await enrollCurrentUser();
|
||||
navigate('/', { replace: true });
|
||||
} catch (e) {
|
||||
setError(e.message || 'Could not start the curriculum. Please try again.');
|
||||
setBusy(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-bg flex items-center justify-center p-4">
|
||||
<div className="w-full max-w-lg">
|
||||
<div className="text-center mb-8">
|
||||
<img src="/images/icon.png" alt="Respellion Icon" className="h-20 mx-auto mb-4" />
|
||||
<h1 className="text-3xl text-teal font-bold tracking-tight">Welcome, {state.currentUser.name}</h1>
|
||||
</div>
|
||||
|
||||
<Card className="border border-bg-warm">
|
||||
<div className="text-center py-2">
|
||||
<BookOpen size={48} className="mx-auto text-teal mb-4" />
|
||||
<h2 className="text-2xl font-bold mb-3">Start your learning journey</h2>
|
||||
<p className="text-fg-muted mb-2">
|
||||
The curriculum is a 26-week cycle of weekly learning sessions and tests.
|
||||
</p>
|
||||
<p className="text-fg-muted mb-6">
|
||||
When you click <strong>Start</strong>, week 1 begins today. You can pick this up at any moment — the cycle is yours.
|
||||
</p>
|
||||
|
||||
{error && (
|
||||
<div className="text-red-500 text-sm font-medium mb-4">{error}</div>
|
||||
)}
|
||||
|
||||
<Button onClick={handleStart} disabled={busy} className="text-lg px-8 py-3">
|
||||
{busy ? 'Starting...' : <>Start my journey <ArrowRight size={20} className="ml-2" /></>}
|
||||
</Button>
|
||||
|
||||
<div className="mt-6">
|
||||
<button
|
||||
onClick={logout}
|
||||
className="text-xs text-fg-muted hover:text-fg inline-flex items-center gap-1"
|
||||
>
|
||||
<LogOut size={12} /> Sign out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Onboarding;
|
||||
@@ -10,6 +10,7 @@ import Button from '../components/ui/Button';
|
||||
import Tag from '../components/ui/Tag';
|
||||
import { useApp } from '../store/AppContext';
|
||||
import { generateWeeklyQuiz, saveTestResult, getTestResult } from '../lib/testService';
|
||||
import { getCurriculumWeek, getCurriculumCycle } from '../lib/curriculumService';
|
||||
import { storage } from '../lib/storage';
|
||||
|
||||
const TIMER_SECONDS = 300; // 5 minutes
|
||||
@@ -180,7 +181,7 @@ const Testen = () => {
|
||||
<div className="text-center py-12">
|
||||
<CheckSquare size={64} className="mx-auto text-teal/30 mb-6" />
|
||||
<h1 className="text-3xl md:text-4xl font-bold text-teal mb-4">Weekly Test</h1>
|
||||
<p className="text-fg-muted text-lg mb-2">Week {weekNumber}</p>
|
||||
<p className="text-fg-muted text-lg mb-2">Cycle {getCurriculumCycle(weekNumber)} · Week {getCurriculumWeek(weekNumber)} of 26</p>
|
||||
<p className="text-fg-muted mb-8 max-w-md mx-auto">
|
||||
Test your knowledge with 5 AI-generated questions. You have 5 minutes to complete the test. Good luck!
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user