183 lines
6.3 KiB
HTML
183 lines
6.3 KiB
HTML
{{define "main-page"}}
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
<title>Interactive HTML Tutorial</title>
|
|
<script type="module" src="/datastar.js"></script>
|
|
<style>
|
|
*{box-sizing:border-box} body{font-family:Inter,system-ui,Segoe UI,Roboto,Arial; background:#f3f6fb; padding:24px}
|
|
.container{max-width:900px;margin:0 auto;background:#fff;border-radius:12px;box-shadow:0 10px 40px rgba(0,0,0,.08);overflow:hidden}
|
|
.header{padding:28px;background:linear-gradient(90deg,#5562f7,#8b5cf6);color:#fff;text-align:center}
|
|
.header h1{margin:0;font-size:1.8rem}
|
|
#content{padding:28px;min-height:360px}
|
|
button{background:#5562f7;color:#fff;border:none;padding:10px 18px;border-radius:8px;cursor:pointer}
|
|
.btn-ghost{background:#eef2ff;color:#111}
|
|
.quiz-option{display:block;width:100%;text-align:left;padding:12px;border-radius:8px;margin:8px 0;border:1px solid #eef2ff;background:#fbfdff}
|
|
pre.code{background:#0f1724;color:#a7f3d0;padding:12px;border-radius:8px;overflow:auto}
|
|
.hint{background:#fff7ed;border-left:4px solid #f59e0b;padding:12px;border-radius:6px;margin:12px 0}
|
|
.feedback{padding:14px;border-radius:8px;margin:12px 0}
|
|
.feedback.success{background:#ecfdf5;border-left:4px solid #10b981;}
|
|
.feedback.error{background:#fff1f2;border-left:4px solid #ef4444;}
|
|
footer{padding:16px;text-align:center;font-size:.9rem;color:#6b7280;}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>Learn HTML — Interactive Mini Tutorial</h1>
|
|
<p style="opacity:.9;margin-top:6px">Hands-on lessons, short quizzes and tiny exercises.</p>
|
|
</div>
|
|
|
|
<div id="content" data-signals='{"progress":0,"mastery":0}'>
|
|
{{template "intro" .}}
|
|
</div>
|
|
|
|
<footer>
|
|
Progress: <span data-signal="progress">0</span>% • Mastery: <span data-signal="mastery">0</span>%
|
|
</footer>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
{{end}}
|
|
|
|
|
|
{{/* --- Intro screen --- */}}
|
|
{{define "intro"}}
|
|
<div style="padding:8px 0 0 0">
|
|
<div style="margin-bottom:18px">
|
|
<h2>Welcome 👋</h2>
|
|
<p>In this short interactive tutorial you'll learn what HTML is, try a quick quiz, and write your first <h1> tag.</p>
|
|
</div>
|
|
|
|
<div style="display:flex;gap:12px;align-items:center">
|
|
<button data-on:click="@get('/node/what-is-html')">Start Learning</button>
|
|
<button class="btn-ghost" data-on:click="@get('/node/summary')">See Outline</button>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
|
|
{{/* --- Outline / summary --- */}}
|
|
{{define "summary"}}
|
|
<h2>Lesson Outline</h2>
|
|
<ul>
|
|
<li>What is HTML? (short)</li>
|
|
<li>Quiz: basic concept</li>
|
|
<li>Exercise: create a heading (<h1>)</li>
|
|
</ul>
|
|
<p>
|
|
<button data-on:click="@get('/node/what-is-html')">Begin Lesson</button>
|
|
</p>
|
|
{{end}}
|
|
|
|
|
|
{{/* --- Short lesson node --- */}}
|
|
{{define "what-is-html"}}
|
|
<h2>What is HTML?</h2>
|
|
<p><strong>HTML</strong> stands for <em>HyperText Markup Language</em>. It's the language used to describe the structure of web pages using tags such as <h1>, <p>, <a> and others.</p>
|
|
|
|
<h3>Key ideas</h3>
|
|
<ul>
|
|
<li>HTML is markup, not a programming language.</li>
|
|
<li>Elements use tags: <tag>content</tag>.</li>
|
|
<li>Browsers render HTML to show pages.</li>
|
|
</ul>
|
|
|
|
<div style="margin-top:18px">
|
|
<button data-on:click="@get('/node/quiz-what-is-html')">Take a quick quiz</button>
|
|
<button class="btn-ghost" data-on:click="@get('/node/exercise-first-tag')">Try an exercise instead</button>
|
|
</div>
|
|
{{end}}
|
|
|
|
|
|
{{/* --- Quiz node --- */}}
|
|
{{define "quiz-what-is-html"}}
|
|
<h2>Quiz — What is HTML?</h2>
|
|
<p>Choose the best answer:</p>
|
|
|
|
<div style="margin-top:12px">
|
|
{{range .QuizOptions}}
|
|
<button class="quiz-option" data-on:click="@post('/answer', {quiz: 'quiz-what-is-html', answer: '{{.ID}}'})">
|
|
<strong>{{.ID | printf "%s."}}</strong> {{.Text}}
|
|
</button>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div id="quiz-feedback" style="margin-top:12px"></div>
|
|
|
|
<div style="margin-top:16px">
|
|
<button class="btn-ghost" data-on:click="@get('/node/what-is-html')">Back</button>
|
|
</div>
|
|
{{end}}
|
|
|
|
|
|
{{/* Keep an alias if older links use the other name */}}
|
|
{{define "quiz-html-tags"}}{{template "quiz-what-is-html" .}}{{end}}
|
|
|
|
|
|
{{/* --- Exercise: first tag --- */}}
|
|
{{define "exercise-first-tag"}}
|
|
<h2>Exercise — Your first <h1></h2>
|
|
<p>Finish the HTML snippet so the page shows a heading that reads <strong>Hello World</strong>.</p>
|
|
|
|
<pre class="code"><!doctype html>
|
|
<html>
|
|
<body>
|
|
<!-- add a heading below -->
|
|
{{printf "%s" ""}}
|
|
</body>
|
|
</html></pre>
|
|
|
|
<textarea id="code" placeholder="Type your HTML here"><h1>Hello World</h1></textarea>
|
|
|
|
<div style="margin-top:12px">
|
|
<button data-on:click="$$post('/code/check', {exerciseId: 'first-tag', code: document.querySelector('#code').value})">Run & Check</button>
|
|
<button class="btn-ghost" data-on:click="@get('/node/what-is-html')">Skip</button>
|
|
</div>
|
|
|
|
<div id="exercise-feedback" style="margin-top:12px"></div>
|
|
{{end}}
|
|
|
|
|
|
{{/* --- Feedback fragments --- */}}
|
|
{{define "correct-answer"}}
|
|
<div class="feedback success">
|
|
<h3>✅ Correct</h3>
|
|
<p>{{.Explanation}}</p>
|
|
<button data-on:click="@get('/node/{{.NextNode}}')">Continue</button>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{define "wrong-answer"}}
|
|
<div class="feedback error">
|
|
<h3>❌ Not quite</h3>
|
|
{{if .ShowHint}}<div class="hint">{{.Hint}}</div>{{end}}
|
|
<p>Try again or review the lesson.</p>
|
|
<div style="margin-top:10px">
|
|
<button data-on:click="@get('/node/quiz-what-is-html')">Try Again</button>
|
|
<button class="btn-ghost" data-on:click="@get('/node/what-is-html')">Review</button>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
|
|
{{/* --- Code-check results --- */}}
|
|
{{define "code-pass"}}
|
|
<div class="feedback success">
|
|
<h3>🎉 Nice work — it passed!</h3>
|
|
<p>{{.Output}}</p>
|
|
<button data-on:click="@get('/node/quiz-what-is-html')">Go to Quiz</button>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{define "code-fail"}}
|
|
<div class="feedback error">
|
|
<h3>Looks like there is an issue</h3>
|
|
<p>{{.Error}}</p>
|
|
<button class="btn-ghost" data-on:click="@get('/node/exercise-first-tag')">Open Editor</button>
|
|
</div>
|
|
{{end}}
|
|
|