52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
import { LESSONS } from '../data/lessons'
|
|
import type { UserProgress } from '../types'
|
|
import '../styles/typing.css'
|
|
|
|
type Props = {
|
|
progress: UserProgress
|
|
onSelect: (lessonId: number) => void
|
|
}
|
|
|
|
export function LessonSelect({ progress, onSelect }: Props) {
|
|
const isUnlocked = (lessonId: number) => {
|
|
const lesson = LESSONS.find(l => l.id === lessonId)
|
|
if (!lesson?.unlockAfter) return true
|
|
return progress.completedLessons.includes(lesson.unlockAfter)
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<div className="modeHeader">
|
|
<h2 className="modeTitle">Lessons</h2>
|
|
<p className="modeSubtitle">
|
|
Master each lesson to unlock the next ({progress.completedLessons.length}/{LESSONS.length} completed)
|
|
</p>
|
|
</div>
|
|
<div className="lessonSelect">
|
|
{LESSONS.map(lesson => {
|
|
const unlocked = isUnlocked(lesson.id)
|
|
const completed = progress.completedLessons.includes(lesson.id)
|
|
|
|
return (
|
|
<div
|
|
key={lesson.id}
|
|
className={`lessonCard ${!unlocked ? 'locked' : ''} ${completed ? 'completed' : ''}`}
|
|
onClick={() => unlocked && onSelect(lesson.id)}
|
|
>
|
|
<div className="lessonId">Lesson {lesson.id}</div>
|
|
<div className="lessonName">{lesson.name}</div>
|
|
{lesson.newKeys.length > 0 && (
|
|
<div className="lessonKeys">
|
|
New: {lesson.newKeys.join(' ')}
|
|
</div>
|
|
)}
|
|
<div className="lessonStatus">
|
|
{completed ? 'Completed' : unlocked ? 'Ready' : 'Locked'}
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|