Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 52 additions & 39 deletions src/app/tutorial-hello-world/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,51 @@

import BackToDashBoardLink from "@/components/back-to-dashboard-link";
import YouTube from "react-youtube";
import { Cinzel } from 'next/font/google';
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"],
weight: ["400", "700"],
});

// 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
<div
className="min-h-screen p-4 md:p-12"
style={{
backgroundImage: "url('/geminiblurred.png')",
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundColor: '#fef3c7',
backgroundImage: "url('/geminiblurred.png')",
backgroundSize: "cover",
backgroundPosition: "center",
backgroundColor: "#fef3c7",
}}
>
<div
className="inline-block p-4"
style={{ zIndex: 10 }}
>
<div className="inline-block p-4" style={{ zIndex: 10 }}>
<BackToDashBoardLink />
</div>

{/* "scroll"*/}
<article className={`max-w-4xl mx-auto bg-amber-100 p-8 md:p-12 shadow-2xl shadow-amber-950/70 space-y-8
<article
className={`max-w-4xl mx-auto bg-amber-100 p-8 md:p-12 shadow-2xl shadow-amber-950/70 space-y-8
${bodyFontClass} border border-amber-800 transform rotate-[-0.5deg]
rounded-t-[4rem] rounded-b-lg`}>
rounded-t-[4rem] rounded-b-lg`}
>
{/* title*/}
<h1 className={`text-4xl md:text-5xl font-bold ${cinzelTitleClass}
border-b-4 border-amber-900 pb-4 mb-8 text-center uppercase`}>
<h1
className={`text-4xl md:text-5xl font-bold ${cinzelTitleClass}
border-b-4 border-amber-900 pb-4 mb-8 text-center uppercase`}
>
Quest: The Oracle&apos;s First Greeting
</h1>

<p className="text-xl italic text-amber-900">
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
Expand All @@ -56,7 +59,7 @@ export default function TutorialHelloWorld() {
</p>

<hr className="my-8 border-amber-900/50" />

{/* section*/}
<section className="space-y-4">
<h2 className={`text-3xl font-semibold ${cinzelTitleClass}`}>
Expand All @@ -79,7 +82,7 @@ export default function TutorialHelloWorld() {
</section>

<hr className="my-8 border-amber-900/50" />

{/* section */}
<section className="space-y-4">
<h2 className={`text-3xl font-semibold ${cinzelTitleClass}`}>
Expand All @@ -88,27 +91,27 @@ export default function TutorialHelloWorld() {
<p className="text-lg">Why start with something so simple?</p>
<ul className="list-disc list-inside space-y-3 text-lg pl-4">
<li>
<strong className="font-semibold text-amber-950">It&apos;s Tradition:</strong> Like a knight
receiving their first sword, programmers worldwide start here. It connects you to
generations of coders before you!
<strong className="font-semibold text-amber-950">It&apos;s Tradition:</strong> Like a
knight receiving their first sword, programmers worldwide start here. It connects you
to generations of coders before you!
</li>
<li>
<strong className="font-semibold text-amber-950">It&apos;s a Test:</strong> Successfully making the
machine say &quot;Hello World&quot; proves your basic setup is working. Your coding
environment, the language you&apos;re using - they&apos;re all aligned and ready for
more complex commands. It&apos;s like checking if your magic wand sparks before trying
to levitate a mountain.
<strong className="font-semibold text-amber-950">It&apos;s a Test:</strong>{" "}
Successfully making the machine say &quot;Hello World&quot; proves your basic setup is
working. Your coding environment, the language you&apos;re using - they&apos;re all
aligned and ready for more complex commands. It&apos;s like checking if your magic
wand sparks before trying to levitate a mountain.
</li>
<li>
<strong className="font-semibold text-amber-950">It&apos;s Confidence:</strong> Seeing your very
first command come to life, even a simple one, is a powerful boost! It&apos;s the
first step on your epic journey.
<strong className="font-semibold text-amber-950">It&apos;s Confidence:</strong> Seeing
your very first command come to life, even a simple one, is a powerful boost!
It&apos;s the first step on your epic journey.
</li>
</ul>
</section>

<hr className="my-8 border-amber-900/50" />

{/* section*/}
<section className="space-y-4">
<h2 className={`text-3xl font-semibold ${cinzelTitleClass}`}>
Expand All @@ -124,17 +127,27 @@ export default function TutorialHelloWorld() {
<p className="text-lg">
Different programming languages (spellbooks) have slightly different words for the
&apos;Display&apos; command (like{" "}
<code className="bg-amber-200 px-1 rounded text-amber-950 font-mono border border-amber-800">print</code>,{" "}
<code className="bg-amber-200 px-1 rounded text-amber-950 font-mono border border-amber-800">console.log</code>,{" "}
<code className="bg-amber-200 px-1 rounded text-amber-950 font-mono border border-amber-800">echo</code>), but the core
idea is the same: tell the machine to show those exact words.
<code className="bg-amber-200 px-1 rounded text-amber-950 font-mono border border-amber-800">
print
</code>
,{" "}
<code className="bg-amber-200 px-1 rounded text-amber-950 font-mono border border-amber-800">
console.log
</code>
,{" "}
<code className="bg-amber-200 px-1 rounded text-amber-950 font-mono border border-amber-800">
echo
</code>
), but the core idea is the same: tell the machine to show those exact words.
</p>
</section>

<hr className="my-8 border-amber-900/50" />

<YouTube videoId="hp4pYFASTrc"></YouTube>

<Quiz quizData={helloWorldQuiz}></Quiz>
</article>
</div>
);
}
}
122 changes: 122 additions & 0 deletions src/components/tutorial-quiz.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { Cinzel } from "next/font/google";
import { useState } from "react";
import { QuizData } from "@/lib/types/types";

const cinzel = Cinzel({ subsets: ["latin"], weight: ["700"] });

type QuizProps = {
quizData: QuizData;
};

export default function Quiz({ quizData }: QuizProps) {
const [questionNumber, setQuestionNumber] = useState<number>(0);
const [selectedOption, setSelectedOption] = useState<string | null>(null);
const [isCorrect, setIsCorrect] = useState<boolean | null>(null);
const [score, setScore] = useState(0);
const [showResults, setShowResults] = useState(false);

const currentQuestion = quizData.questions[questionNumber];

const handleOptionClick = (option: string) => {
if (selectedOption) return;
setSelectedOption(option);

// 1. Check Correctness
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 < quizData.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 (
<div className="mt-12 p-8 border-2 border-amber-800/50 rounded-xl bg-amber-50/50 shadow-inner shadow-amber-900/20">
<h2 className={`text-3xl font-bold text-center mb-6 text-amber-900 ${cinzel.className}`}>
{quizData.title}
</h2>

{showResults ? (
<div className="text-center space-y-6 animate-fade-in">
{/* Results */}
<p className="text-2xl text-amber-950">Quest Complete!</p>
<p className="text-xl">
You scored <span className="font-bold">{score}</span> out of{" "}
<span className="font-bold">{quizData.questions.length}</span>
</p>
<button
onClick={resetQuiz}
className="px-6 py-3 bg-amber-900 text-amber-100 font-bold rounded-lg hover:bg-amber-800 border-2 border-amber-950"
>
Try Again
</button>
</div>
) : (
<div className="space-y-6">
{/* Score Tracker Display */}
<div className="flex justify-between text-amber-800 font-serif italic">
<span>
Question {questionNumber + 1} of {quizData.questions.length}
</span>
<span>Score: {score}</span>
</div>

<div className="bg-amber-200/50 p-6 rounded-lg border border-amber-800/30">
<h3 className="text-xl font-semibold text-amber-950 mb-4">
{currentQuestion.questionText}
</h3>

<div className="grid gap-3">
{currentQuestion.options.map((option) => {
let buttonStyle = "bg-white hover:bg-amber-100 border-amber-300 text-amber-900";

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";
}

return (
<button
key={option}
onClick={() => handleOptionClick(option)}
disabled={selectedOption !== null}
className={`w-full text-left p-4 rounded border-2 transition-all ${buttonStyle} ${
selectedOption === null ? "hover:translate-x-1" : ""
}`}
>
{option}
</button>
);
})}
</div>
</div>
</div>
)}
</div>
);
}
72 changes: 72 additions & 0 deletions src/data/quizzes/01-hello-world.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
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",
},
{
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",
},
],
};
10 changes: 10 additions & 0 deletions src/lib/types/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export type Question = {
questionText: string;
options: string[];
correctAnswer: string;
};

export type QuizData = {
title: string;
questions: Question[];
};