feat/course
Arik Chakma 1 month ago
parent f13d98eff3
commit 088d4e2e2d
  1. 4
      src/components/Course/ChallengeView.tsx
  2. 13
      src/components/Course/CourseLayout.tsx
  3. 3
      src/components/Course/CourseSidebar.tsx
  4. 4
      src/components/Course/LessonView.tsx
  5. 2
      src/components/Course/QuizView.tsx
  6. 27
      src/components/SqlCodeEditor/SqlCodeEditor.tsx
  7. 8
      src/components/SqlCodeEditor/SqlTableResult.tsx

@ -27,8 +27,7 @@ type ChallengeViewProps = {
}; };
export function ChallengeView(props: ChallengeViewProps) { export function ChallengeView(props: ChallengeViewProps) {
const { children, title, course, lesson, courseId, lessonId, chapterId } = const { children, title, course, lesson, courseId, chapterId } = props;
props;
const { chapters } = course; const { chapters } = course;
const { frontmatter } = lesson; const { frontmatter } = lesson;
@ -39,6 +38,7 @@ export function ChallengeView(props: ChallengeViewProps) {
courseId={courseId} courseId={courseId}
chapterId={chapterId} chapterId={chapterId}
lessonId={lesson.id} lessonId={lesson.id}
lesson={lesson}
title={title} title={title}
chapters={chapters} chapters={chapters}
completedPercentage={0} completedPercentage={0}

@ -3,12 +3,13 @@ import { CourseSidebar, type CourseSidebarProps } from './CourseSidebar';
import { useMemo } from 'react'; import { useMemo } from 'react';
type CourseLayoutProps = { type CourseLayoutProps = {
isSubmitted?: boolean;
children: React.ReactNode; children: React.ReactNode;
} & CourseSidebarProps; } & CourseSidebarProps;
export function CourseLayout(props: CourseLayoutProps) { export function CourseLayout(props: CourseLayoutProps) {
const { children, ...sidebarProps } = props; const { children, isSubmitted, ...sidebarProps } = props;
const { chapters, courseId, chapterId, lessonId } = sidebarProps; const { chapters, courseId, chapterId, lessonId, lesson } = sidebarProps;
const allLessonLinks = useMemo(() => { const allLessonLinks = useMemo(() => {
const lessons: string[] = []; const lessons: string[] = [];
@ -51,6 +52,14 @@ 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={() => {
if (!isSubmitted && lesson?.frontmatter?.type !== 'lesson') {
// show a warning modal
window.alert(
'Please submit your answer before moving to the next lesson.',
);
return;
}
window.location.href = nextLessonLink; window.location.href = nextLessonLink;
}} }}
disabled={!nextLessonLink} disabled={!nextLessonLink}

@ -1,5 +1,5 @@
import { useState } from 'react'; import { useState } from 'react';
import type { ChapterFileType } from '../../lib/course'; import type { ChapterFileType, LessonFileType } from '../../lib/course';
import { Chapter } from './Chapter'; import { Chapter } from './Chapter';
export type CourseSidebarProps = { export type CourseSidebarProps = {
@ -9,6 +9,7 @@ export type CourseSidebarProps = {
title: string; title: string;
chapters: ChapterFileType[]; chapters: ChapterFileType[];
lesson: LessonFileType;
completedPercentage: number; completedPercentage: number;
}; };

@ -23,8 +23,7 @@ type LessonViewProps = {
}; };
export function LessonView(props: LessonViewProps) { export function LessonView(props: LessonViewProps) {
const { children, title, course, lesson, courseId, lessonId, chapterId } = const { children, title, course, lesson, courseId, chapterId } = props;
props;
const { chapters } = course; const { chapters } = course;
return ( return (
@ -32,6 +31,7 @@ export function LessonView(props: LessonViewProps) {
courseId={courseId} courseId={courseId}
chapterId={chapterId} chapterId={chapterId}
lessonId={lesson.id} lessonId={lesson.id}
lesson={lesson}
title={title} title={title}
chapters={chapters} chapters={chapters}
completedPercentage={0} completedPercentage={0}

@ -1,5 +1,4 @@
import { useState } from 'react'; import { useState } from 'react';
import { CourseSidebar } from './CourseSidebar';
import { CourseLayout } from './CourseLayout'; import { CourseLayout } from './CourseLayout';
import { Circle, CircleCheck, CircleX } from 'lucide-react'; import { Circle, CircleCheck, CircleX } from 'lucide-react';
import { cn } from '../../lib/classname'; import { cn } from '../../lib/classname';
@ -50,6 +49,7 @@ export function QuizView(props: QuizViewProps) {
courseId={courseId} courseId={courseId}
chapterId={chapterId} chapterId={chapterId}
lessonId={lesson.id} lessonId={lesson.id}
lesson={lesson}
title={title} title={title}
chapters={chapters} chapters={chapters}
completedPercentage={0} completedPercentage={0}

@ -19,10 +19,17 @@ export type SqlCodeEditorProps = {
initSteps?: string[]; initSteps?: string[];
expectedResults?: QueryExecResult[]; expectedResults?: QueryExecResult[];
onQuerySubmit?: () => void;
}; };
export function SqlCodeEditor(props: SqlCodeEditorProps) { export function SqlCodeEditor(props: SqlCodeEditorProps) {
const { defaultValue, initSteps = [], expectedResults } = props; const {
defaultValue,
initSteps = [],
expectedResults,
onQuerySubmit,
} = props;
const editorRef = useRef<HTMLDivElement>(null); const editorRef = useRef<HTMLDivElement>(null);
const [queryResult, setQueryResult] = useState<QueryExecResult[] | null>( const [queryResult, setQueryResult] = useState<QueryExecResult[] | null>(
@ -141,27 +148,13 @@ export function SqlCodeEditor(props: SqlCodeEditorProps) {
return; return;
} }
const { results, error } = handleQuery(query);
setQueryResult(results);
setQueryError(error);
setIsSubmitted(false);
}}
/>
<DatabaseActionButton
label="Submit"
onClick={() => {
const query = editor?.state?.doc.toString();
if (!query) {
return;
}
const { results, error } = handleQuery(query); const { results, error } = handleQuery(query);
setQueryResult(results); setQueryResult(results);
setQueryError(error); setQueryError(error);
setIsSubmitted(true); setIsSubmitted(true);
onQuerySubmit?.();
}} }}
className="bg-zinc-800 px-3 text-white"
/> />
</div> </div>
</ResizablePanel> </ResizablePanel>

@ -6,7 +6,6 @@ type SqlTableResultProps = {
error?: string; error?: string;
onTryAgain?: () => void; onTryAgain?: () => void;
onNext?: () => void;
matchAnswers?: boolean; matchAnswers?: boolean;
expectedResults?: QueryExecResult[] | null; expectedResults?: QueryExecResult[] | null;
@ -16,7 +15,6 @@ export function SqlTableResult(props: SqlTableResultProps) {
const { const {
results, results,
error, error,
onNext,
onTryAgain, onTryAgain,
expectedResults, expectedResults,
matchAnswers = false, matchAnswers = false,
@ -53,12 +51,6 @@ export function SqlTableResult(props: SqlTableResultProps) {
> >
Yes, I want to try again Yes, I want to try again
</button> </button>
<button
className="rounded-md bg-zinc-800 px-2 py-0.5 outline-none focus:outline-none"
onClick={onNext}
>
No, move to next
</button>
</div> </div>
</div> </div>
)} )}

Loading…
Cancel
Save