fix: update current lesson store

pull/8127/head
Arik Chakma 6 months ago
parent e11ac4bf84
commit ac1da1be10
  1. 34
      src/components/Course/CourseLayout.tsx
  2. 14
      src/components/Course/QuizView.tsx
  3. 15
      src/components/SqlCodeEditor/SqlCodeEditor.tsx
  4. 9
      src/lib/course.ts
  5. 13
      src/stores/course.ts

@ -1,13 +1,13 @@
import { ChevronLeft, ChevronRight, Loader2 } from 'lucide-react'; import { ChevronLeft, ChevronRight, Loader2 } from 'lucide-react';
import { CourseSidebar, type CourseSidebarProps } from './CourseSidebar'; import { CourseSidebar, type CourseSidebarProps } from './CourseSidebar';
import { useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { import {
useCompleteLessonMutation, useCompleteLessonMutation,
useCourseProgress, useCourseProgress,
} from '../../hooks/use-course'; } from '../../hooks/use-course';
import { NextLessonAlertModal } from './NextLessonAlertModal'; import { NextLessonAlertModal } from './NextLessonAlertModal';
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { lessonSubmitStatus } from '../../stores/course'; import { currentLesson } from '../../stores/course';
import { getPercentage } from '../../helper/number'; import { getPercentage } from '../../helper/number';
type CourseLayoutProps = { type CourseLayoutProps = {
@ -18,7 +18,7 @@ export function CourseLayout(props: CourseLayoutProps) {
const { children, ...sidebarProps } = props; const { children, ...sidebarProps } = props;
const { chapters, courseId, chapterId, lessonId, lesson } = sidebarProps; const { chapters, courseId, chapterId, lessonId, lesson } = sidebarProps;
const $lessonSubmitStatus = useStore(lessonSubmitStatus); const $currentLesson = useStore(currentLesson);
const [showNextWarning, setShowNextWarning] = useState(false); const [showNextWarning, setShowNextWarning] = useState(false);
const { data: courseProgress } = useCourseProgress(courseId); const { data: courseProgress } = useCourseProgress(courseId);
@ -85,6 +85,21 @@ export function CourseLayout(props: CourseLayoutProps) {
); );
}; };
useEffect(() => {
if ($currentLesson) {
return;
}
currentLesson.set({
courseId,
chapterId,
lessonId,
lessonType: lesson.frontmatter.type,
challengeStatus: 'pending',
quizStatus: 'pending',
});
}, [$currentLesson]);
return ( return (
<> <>
{showNextWarning && ( {showNextWarning && (
@ -123,9 +138,18 @@ export function CourseLayout(props: CourseLayoutProps) {
<button <button
className="flex items-center gap-1 rounded-lg border border-zinc-800 px-2 py-1.5 text-sm leading-none disabled:opacity-60" className="flex items-center gap-1 rounded-lg border border-zinc-800 px-2 py-1.5 text-sm leading-none disabled:opacity-60"
onClick={() => { onClick={() => {
const isQuizPending =
($currentLesson?.lessonType === 'lesson-quiz' ||
$currentLesson?.lessonType === 'quiz') &&
$currentLesson?.quizStatus === 'pending';
const isChallengePending =
($currentLesson?.lessonType === 'lesson-challenge' ||
$currentLesson?.lessonType === 'challenge') &&
$currentLesson?.challengeStatus === 'pending';
if ( if (
$lessonSubmitStatus === 'idle' && (isQuizPending || isChallengePending) &&
lesson?.frontmatter?.type !== 'lesson' &&
!isCurrentLessonCompleted !isCurrentLessonCompleted
) { ) {
setShowNextWarning(true); setShowNextWarning(true);

@ -2,7 +2,8 @@ import { useState } from 'react';
import { Circle, CircleCheck, CircleX } from 'lucide-react'; import { Circle, CircleCheck, CircleX } from 'lucide-react';
import { cn } from '../../lib/classname'; import { cn } from '../../lib/classname';
import type { LessonFileType } from '../../lib/course'; import type { LessonFileType } from '../../lib/course';
import { lessonSubmitStatus } from '../../stores/course'; import { currentLesson } from '../../stores/course';
import { useStore } from '@nanostores/react';
type QuizViewProps = { type QuizViewProps = {
lesson: LessonFileType; lesson: LessonFileType;
@ -18,6 +19,7 @@ export function QuizView(props: QuizViewProps) {
Record<number, number | undefined> Record<number, number | undefined>
>({}); >({});
const $currentLesson = useStore(currentLesson);
const [isSubmitted, setIsSubmitted] = useState(false); const [isSubmitted, setIsSubmitted] = useState(false);
const isAllAnswered = const isAllAnswered =
@ -80,7 +82,15 @@ export function QuizView(props: QuizViewProps) {
disabled={isSubmitted || !isAllAnswered} disabled={isSubmitted || !isAllAnswered}
onClick={() => { onClick={() => {
setIsSubmitted(true); setIsSubmitted(true);
lessonSubmitStatus.set('submitted'); if (!$currentLesson) {
console.error('FIX: update current lesson');
return;
}
currentLesson.set({
...$currentLesson,
quizStatus: 'correct',
});
}} }}
> >
Submit my Answers Submit my Answers

@ -13,7 +13,8 @@ import { keymap } from '@codemirror/view';
import { Check, type LucideIcon, Play, WandSparkles, X } from 'lucide-react'; import { Check, type LucideIcon, Play, WandSparkles, X } from 'lucide-react';
import { useSqlite } from './use-sqlite'; import { useSqlite } from './use-sqlite';
import { cn } from '../../lib/classname'; import { cn } from '../../lib/classname';
import { lessonSubmitStatus } from '../../stores/course'; import { currentLesson } from '../../stores/course';
import { useStore } from '@nanostores/react';
export type SqlCodeEditorProps = { export type SqlCodeEditorProps = {
defaultValue?: string; defaultValue?: string;
@ -25,6 +26,7 @@ export type SqlCodeEditorProps = {
export function SqlCodeEditor(props: SqlCodeEditorProps) { export function SqlCodeEditor(props: SqlCodeEditorProps) {
const { defaultValue, initSteps = [], expectedResults } = props; const { defaultValue, initSteps = [], expectedResults } = props;
const $currentLesson = useStore(currentLesson);
const editorRef = useRef<HTMLDivElement>(null); const editorRef = useRef<HTMLDivElement>(null);
const [queryResults, setQueryResults] = useState<QueryExecResult[] | null>( const [queryResults, setQueryResults] = useState<QueryExecResult[] | null>(
null, null,
@ -181,7 +183,16 @@ export function SqlCodeEditor(props: SqlCodeEditorProps) {
setQueryResults(results); setQueryResults(results);
setQueryError(error); setQueryError(error);
setIsSubmitted(true); setIsSubmitted(true);
lessonSubmitStatus.set(error ? 'wrong' : 'submitted');
if (!$currentLesson) {
console.error('FIX: update current lesson');
return;
}
currentLesson.set({
...$currentLesson,
challengeStatus: error ? 'wrong' : 'correct',
});
}} }}
/> />
</div> </div>

@ -6,11 +6,18 @@ export interface CourseFrontmatter {
description: string; description: string;
} }
export type AllowedLessonType =
| 'lesson'
| 'challenge'
| 'quiz'
| 'lesson-challenge'
| 'lesson-quiz';
export type LessonFrontmatter = { export type LessonFrontmatter = {
title: string; title: string;
description: string; description: string;
order: number; order: number;
type: 'lesson' | 'challenge' | 'quiz' | 'lesson-challenge' | 'lesson-quiz'; type: AllowedLessonType;
defaultValue?: string; defaultValue?: string;
initSteps?: string[]; initSteps?: string[];

@ -1,4 +1,13 @@
import { atom } from 'nanostores'; import { atom } from 'nanostores';
import type { AllowedLessonType } from '../lib/course';
export type LessonSubmitStatus = 'idle' | 'submitting' | 'submitted' | 'wrong'; export type CurrentLessonType = {
export const lessonSubmitStatus = atom<LessonSubmitStatus>('idle'); courseId: string;
chapterId: string;
lessonId: string;
lessonType: AllowedLessonType;
challengeStatus?: 'pending' | 'wrong' | 'correct';
quizStatus?: 'pending' | 'wrong' | 'correct';
};
export const currentLesson = atom<CurrentLessonType | null>(null);

Loading…
Cancel
Save