From 2003488058e76aae07efc97e248793c42fd3745b Mon Sep 17 00:00:00 2001 From: Eric Zhang Date: Tue, 18 Nov 2025 18:18:43 -0500 Subject: [PATCH 1/7] feat: add quiz container --- src/app/tutorial-hello-world/page.tsx | 89 +++++++++++++++------------ src/components/tutorial-quiz.tsx | 11 ++++ 2 files changed, 61 insertions(+), 39 deletions(-) create mode 100644 src/components/tutorial-quiz.tsx diff --git a/src/app/tutorial-hello-world/page.tsx b/src/app/tutorial-hello-world/page.tsx index a097547..cee2292 100644 --- a/src/app/tutorial-hello-world/page.tsx +++ b/src/app/tutorial-hello-world/page.tsx @@ -2,7 +2,8 @@ import BackToDashBoardLink from "@/components/back-to-dashboard-link"; import YouTube from "react-youtube"; -import { Cinzel } from 'next/font/google'; +import TutorialQuiz from "@/components/tutorial-quiz"; +import { Cinzel } from "next/font/google"; const cinzel = Cinzel({ subsets: ["latin"], @@ -10,40 +11,40 @@ const cinzel = Cinzel({ }); // body text (Times New Roman= more readable) -const bodyFontClass = "font-serif text-amber-950"; +const bodyFontClass = "font-serif text-amber-950"; // titles (Cinzel font) -const cinzelTitleClass = cinzel.className; +const cinzelTitleClass = cinzel.className; export default function TutorialHelloWorld() { return ( - // Background of scroll + // Background of scroll
-
+
{/* "scroll"*/} -
- + rounded-t-[4rem] rounded-b-lg`} + > {/* title*/} -

+

Quest: The Oracle's First Greeting

- +

Welcome, brave coder! Your journey into the mystical lands of programming begins now. Before you can conjure complex spells or build mighty digital fortresses, every adventurer @@ -56,7 +57,7 @@ export default function TutorialHelloWorld() {


- + {/* section*/}

@@ -79,7 +80,7 @@ export default function TutorialHelloWorld() {


- + {/* section */}

@@ -88,27 +89,27 @@ export default function TutorialHelloWorld() {

Why start with something so simple?

  • - It's Tradition: Like a knight - receiving their first sword, programmers worldwide start here. It connects you to - generations of coders before you! + It's Tradition: Like a + knight receiving their first sword, programmers worldwide start here. It connects you + to generations of coders before you!
  • - It's a Test: Successfully making the - machine say "Hello World" proves your basic setup is working. Your coding - environment, the language you're using - they're all aligned and ready for - more complex commands. It's like checking if your magic wand sparks before trying - to levitate a mountain. + It's a Test:{" "} + Successfully making the machine say "Hello World" proves your basic setup is + working. Your coding environment, the language you're using - they're all + aligned and ready for more complex commands. It's like checking if your magic + wand sparks before trying to levitate a mountain.
  • - It's Confidence: Seeing your very - first command come to life, even a simple one, is a powerful boost! It's the - first step on your epic journey. + It's Confidence: Seeing + your very first command come to life, even a simple one, is a powerful boost! + It's the first step on your epic journey.

- +
- + {/* section*/}

@@ -124,17 +125,27 @@ export default function TutorialHelloWorld() {

Different programming languages (spellbooks) have slightly different words for the 'Display' command (like{" "} - print,{" "} - console.log,{" "} - echo), but the core - idea is the same: tell the machine to show those exact words. + + print + + ,{" "} + + console.log + + ,{" "} + + echo + + ), but the core idea is the same: tell the machine to show those exact words.

- +
+ +
); -} \ No newline at end of file +} diff --git a/src/components/tutorial-quiz.tsx b/src/components/tutorial-quiz.tsx new file mode 100644 index 0000000..b237191 --- /dev/null +++ b/src/components/tutorial-quiz.tsx @@ -0,0 +1,11 @@ +import { Cinzel } from "next/font/google"; +const cinzel = Cinzel({ subsets: ["latin"], weight: ["700"] }); +export default function TutorialQuiz() { + return ( +
+

+ Test Your Knowledge, Initiate +

+
+ ); +} From 5acfdea4f1843665f8f740fc9fe8be750c56a4c8 Mon Sep 17 00:00:00 2001 From: Eric Zhang Date: Tue, 18 Nov 2025 18:44:11 -0500 Subject: [PATCH 2/7] feat: add quiz question type, show questions --- src/components/tutorial-quiz.tsx | 14 ++++++++++++++ src/data/quizzes/01-hello-world.ts | 28 ++++++++++++++++++++++++++++ src/lib/types/types.ts | 10 ++++++++++ 3 files changed, 52 insertions(+) create mode 100644 src/data/quizzes/01-hello-world.ts create mode 100644 src/lib/types/types.ts diff --git a/src/components/tutorial-quiz.tsx b/src/components/tutorial-quiz.tsx index b237191..7b9d174 100644 --- a/src/components/tutorial-quiz.tsx +++ b/src/components/tutorial-quiz.tsx @@ -1,11 +1,25 @@ import { Cinzel } from "next/font/google"; +import { useState } from "react"; +import { helloWorldQuiz } from "@/data/quizzes/01-hello-world"; const cinzel = Cinzel({ subsets: ["latin"], weight: ["700"] }); export default function TutorialQuiz() { + const [questionNumber, setQuestionNumber] = useState(0); + const currentQuestion = helloWorldQuiz.questions[questionNumber]; + return (

Test Your Knowledge, Initiate

+ + {/* Question Card */} +
+
+

+ {currentQuestion.questionText} +

+
+
); } diff --git a/src/data/quizzes/01-hello-world.ts b/src/data/quizzes/01-hello-world.ts new file mode 100644 index 0000000..d4b4924 --- /dev/null +++ b/src/data/quizzes/01-hello-world.ts @@ -0,0 +1,28 @@ +import { QuizData } from "@/lib/types/types"; + +export const helloWorldQuiz: QuizData = { + title: "The Oracle's First Greeting", + questions: [ + { + questionText: "What is the primary purpose of a 'Hello World' program?", + options: [ + "To summon a digital dragon", + "To verify that your coding environment is set up correctly", + "To hack into the mainframe", + "To write a poem for the computer", + ], + correctAnswer: "To verify that your coding environment is set up correctly", + }, + { + questionText: + "True or False: 'Hello World' is only used in one specific programming language.", + options: ["True", "False"], + correctAnswer: "False", + }, + { + questionText: "Which of the following is a common command to display text?", + options: ["print", "shout", "whisper", "cast_spell"], + correctAnswer: "print", + }, + ], +}; diff --git a/src/lib/types/types.ts b/src/lib/types/types.ts new file mode 100644 index 0000000..03883c5 --- /dev/null +++ b/src/lib/types/types.ts @@ -0,0 +1,10 @@ +export type Question = { + questionText: string; + options: string[]; + correctAnswer: string; +}; + +export type QuizData = { + title: string; + questions: Question[]; +}; From 93edff36433a99d5ea87a3e504dc02d67b066431 Mon Sep 17 00:00:00 2001 From: Eric Zhang Date: Tue, 18 Nov 2025 18:47:20 -0500 Subject: [PATCH 3/7] feat: question choice display --- src/components/tutorial-quiz.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/tutorial-quiz.tsx b/src/components/tutorial-quiz.tsx index 7b9d174..25e994f 100644 --- a/src/components/tutorial-quiz.tsx +++ b/src/components/tutorial-quiz.tsx @@ -15,9 +15,19 @@ export default function TutorialQuiz() { {/* Question Card */}
+ {/* Question */}

{currentQuestion.questionText}

+ + {/* Choices */} +
+ {currentQuestion.options.map((option) => ( + + ))} +
From 6e7a213b249acb675814c3762e2105729ebf8f59 Mon Sep 17 00:00:00 2001 From: Eric Zhang Date: Tue, 18 Nov 2025 19:20:04 -0500 Subject: [PATCH 4/7] feat: add question answering --- src/components/tutorial-quiz.tsx | 51 ++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/src/components/tutorial-quiz.tsx b/src/components/tutorial-quiz.tsx index 25e994f..9b5a757 100644 --- a/src/components/tutorial-quiz.tsx +++ b/src/components/tutorial-quiz.tsx @@ -5,6 +5,24 @@ const cinzel = Cinzel({ subsets: ["latin"], weight: ["700"] }); export default function TutorialQuiz() { const [questionNumber, setQuestionNumber] = useState(0); const currentQuestion = helloWorldQuiz.questions[questionNumber]; + const [selectedOption, setSelectedOption] = useState(null); + const [isCorrect, setIsCorrect] = useState(null); + + const handleOptionClick = (option: string) => { + // Prevent clicking if already selected + if (selectedOption) return; + + setSelectedOption(option); + + // Check answer + let correct = null; + if (option === currentQuestion.correctAnswer) { + correct = true; + } else { + correct = false; + } + setIsCorrect(correct); + }; return (
@@ -22,11 +40,34 @@ export default function TutorialQuiz() { {/* Choices */}
- {currentQuestion.options.map((option) => ( - - ))} + {currentQuestion.options.map((option) => { + // Dynamic Styling Logic ( This is soo cool) + let buttonStyle = "bg-white hover:bg-amber-100 border-amber-300 text-amber-900"; + + if (selectedOption === option) { + if (isCorrect) { + buttonStyle = "bg-green-200 border-green-500 text-green-900 font-bold"; + } else { + buttonStyle = "bg-red-200 border-red-500 text-red-900 font-bold"; + } + } else if (selectedOption && option === currentQuestion.correctAnswer) { + // Highlight the correct answer if they got it wrong + buttonStyle = "bg-green-100 border-green-300 text-green-800 opacity-75"; + } + + return ( + + ); + })}
From ebb9e7b8c20df71808209393cfcb85d34ffd5c68 Mon Sep 17 00:00:00 2001 From: Eric Zhang Date: Tue, 18 Nov 2025 20:56:27 -0500 Subject: [PATCH 5/7] feat: quiz progression and completion --- src/components/tutorial-quiz.tsx | 133 ++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 46 deletions(-) diff --git a/src/components/tutorial-quiz.tsx b/src/components/tutorial-quiz.tsx index 9b5a757..55f5a94 100644 --- a/src/components/tutorial-quiz.tsx +++ b/src/components/tutorial-quiz.tsx @@ -1,76 +1,117 @@ import { Cinzel } from "next/font/google"; import { useState } from "react"; import { helloWorldQuiz } from "@/data/quizzes/01-hello-world"; + const cinzel = Cinzel({ subsets: ["latin"], weight: ["700"] }); + export default function TutorialQuiz() { const [questionNumber, setQuestionNumber] = useState(0); - const currentQuestion = helloWorldQuiz.questions[questionNumber]; const [selectedOption, setSelectedOption] = useState(null); const [isCorrect, setIsCorrect] = useState(null); + const [score, setScore] = useState(0); + const [showResults, setShowResults] = useState(false); + + const currentQuestion = helloWorldQuiz.questions[questionNumber]; const handleOptionClick = (option: string) => { - // Prevent clicking if already selected if (selectedOption) return; - setSelectedOption(option); - // Check answer - let correct = null; - if (option === currentQuestion.correctAnswer) { - correct = true; - } else { - correct = false; - } + const correct = option === currentQuestion.correctAnswer; setIsCorrect(correct); + + // 2. Update Score + if (correct) { + setScore((prev) => prev + 1); + } + + // 3. Auto-advance timer + setTimeout(() => { + const nextIndex = questionNumber + 1; + + if (nextIndex < helloWorldQuiz.questions.length) { + setQuestionNumber(nextIndex); + setSelectedOption(null); + setIsCorrect(null); + } else { + setShowResults(true); + } + }, 2000); // 2 second delay so they can read the feedback + }; + + const resetQuiz = () => { + setQuestionNumber(0); + setScore(0); + setShowResults(false); + setSelectedOption(null); + setIsCorrect(null); }; return (

- Test Your Knowledge, Initiate + {helloWorldQuiz.title}

- {/* Question Card */} -
-
- {/* Question */} -

- {currentQuestion.questionText} -

+ {/* 5. Conditional Rendering: Results vs Question */} + {showResults ? ( +
+

Quest Complete!

+

+ You scored {score} out of{" "} + {helloWorldQuiz.questions.length} +

+ +
+ ) : ( +
+ {/* Score Tracker Display */} +
+ + Question {questionNumber + 1} of {helloWorldQuiz.questions.length} + + Score: {score} +
+ +
+

+ {currentQuestion.questionText} +

- {/* Choices */} -
- {currentQuestion.options.map((option) => { - // Dynamic Styling Logic ( This is soo cool) - let buttonStyle = "bg-white hover:bg-amber-100 border-amber-300 text-amber-900"; +
+ {currentQuestion.options.map((option) => { + let buttonStyle = "bg-white hover:bg-amber-100 border-amber-300 text-amber-900"; - if (selectedOption === option) { - if (isCorrect) { - buttonStyle = "bg-green-200 border-green-500 text-green-900 font-bold"; - } else { - buttonStyle = "bg-red-200 border-red-500 text-red-900 font-bold"; + if (selectedOption === option) { + buttonStyle = isCorrect + ? "bg-green-200 border-green-500 text-green-900 font-bold" + : "bg-red-200 border-red-500 text-red-900 font-bold"; + } else if (selectedOption && option === currentQuestion.correctAnswer) { + buttonStyle = "bg-green-100 border-green-300 text-green-800 opacity-75"; } - } else if (selectedOption && option === currentQuestion.correctAnswer) { - // Highlight the correct answer if they got it wrong - buttonStyle = "bg-green-100 border-green-300 text-green-800 opacity-75"; - } - return ( - - ); - })} + return ( + + ); + })} +
-
+ )}
); } From baec054fac3b80cb8458ce182da9b8e889619177 Mon Sep 17 00:00:00 2001 From: Eric Zhang Date: Thu, 20 Nov 2025 01:36:54 -0500 Subject: [PATCH 6/7] fix: pass quiz data as props not hardcoded --- src/app/tutorial-hello-world/page.tsx | 6 ++++-- src/components/tutorial-quiz.tsx | 21 +++++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/app/tutorial-hello-world/page.tsx b/src/app/tutorial-hello-world/page.tsx index cee2292..506c19d 100644 --- a/src/app/tutorial-hello-world/page.tsx +++ b/src/app/tutorial-hello-world/page.tsx @@ -2,8 +2,10 @@ import BackToDashBoardLink from "@/components/back-to-dashboard-link"; import YouTube from "react-youtube"; -import TutorialQuiz from "@/components/tutorial-quiz"; +import Quiz from "@/components/tutorial-quiz"; + import { Cinzel } from "next/font/google"; +import { helloWorldQuiz } from "@/data/quizzes/01-hello-world"; const cinzel = Cinzel({ subsets: ["latin"], @@ -144,7 +146,7 @@ export default function TutorialHelloWorld() { - +
); diff --git a/src/components/tutorial-quiz.tsx b/src/components/tutorial-quiz.tsx index 55f5a94..6edc5f1 100644 --- a/src/components/tutorial-quiz.tsx +++ b/src/components/tutorial-quiz.tsx @@ -1,22 +1,27 @@ import { Cinzel } from "next/font/google"; import { useState } from "react"; -import { helloWorldQuiz } from "@/data/quizzes/01-hello-world"; +import { QuizData } from "@/lib/types/types"; const cinzel = Cinzel({ subsets: ["latin"], weight: ["700"] }); -export default function TutorialQuiz() { +type QuizProps = { + quizData: QuizData; +}; + +export default function Quiz({ quizData }: QuizProps) { const [questionNumber, setQuestionNumber] = useState(0); const [selectedOption, setSelectedOption] = useState(null); const [isCorrect, setIsCorrect] = useState(null); const [score, setScore] = useState(0); const [showResults, setShowResults] = useState(false); - const currentQuestion = helloWorldQuiz.questions[questionNumber]; + const currentQuestion = quizData.questions[questionNumber]; const handleOptionClick = (option: string) => { if (selectedOption) return; setSelectedOption(option); + // 1. Check Correctness const correct = option === currentQuestion.correctAnswer; setIsCorrect(correct); @@ -29,7 +34,7 @@ export default function TutorialQuiz() { setTimeout(() => { const nextIndex = questionNumber + 1; - if (nextIndex < helloWorldQuiz.questions.length) { + if (nextIndex < quizData.questions.length) { setQuestionNumber(nextIndex); setSelectedOption(null); setIsCorrect(null); @@ -50,16 +55,16 @@ export default function TutorialQuiz() { return (

- {helloWorldQuiz.title} + {quizData.title}

- {/* 5. Conditional Rendering: Results vs Question */} {showResults ? (
+ {/* Results */}

Quest Complete!

You scored {score} out of{" "} - {helloWorldQuiz.questions.length} + {quizData.questions.length}

From 543fb4044213c95f5978f2f84cd72308774d8798 Mon Sep 17 00:00:00 2001 From: Eric Zhang Date: Thu, 20 Nov 2025 01:43:05 -0500 Subject: [PATCH 7/7] feat: add more questions to quiz 01 --- src/data/quizzes/01-hello-world.ts | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/data/quizzes/01-hello-world.ts b/src/data/quizzes/01-hello-world.ts index d4b4924..225247b 100644 --- a/src/data/quizzes/01-hello-world.ts +++ b/src/data/quizzes/01-hello-world.ts @@ -24,5 +24,49 @@ export const helloWorldQuiz: QuizData = { options: ["print", "shout", "whisper", "cast_spell"], correctAnswer: "print", }, + { + questionText: + "In the tutorial, teaching the computer to say 'Hello World' is compared to what analogy?", + options: [ + "Training a dragon to fly", + "Teaching a parrot its first words", + "Building a fortress from scratch", + "Brewing a complex potion", + ], + correctAnswer: "Teaching a parrot its first words", + }, + { + questionText: + "Which of these commands was NOT mentioned as a way to display text in different languages?", + options: ["console.log", "echo", "print", "shout_loudly"], + correctAnswer: "shout_loudly", + }, + { + questionText: "Why is the 'Hello World' program considered a 'tradition'?", + options: [ + "It connects you to generations of coders before you", + "It requires a high-level wizard to perform", + "It is the only program that never has bugs", + "It costs gold coins to run", + ], + correctAnswer: "It connects you to generations of coders before you", + }, + { + questionText: + "What does the 'Hello World' program prove about your 'magic wand' (coding setup)?", + options: [ + "That it can levitate mountains", + "That it is broken", + "That it sparks and is ready for more complex commands", + "That it needs to be recharged", + ], + correctAnswer: "That it sparks and is ready for more complex commands", + }, + { + questionText: + "True or False: Even though the command looks different in different languages (like 'echo' or 'console.log'), the core idea is always to display the specific words.", + options: ["True", "False"], + correctAnswer: "True", + }, ], };