Redo early level drawings to be more natural
This commit is contained in:
1 parent
4884678f14
commit
338665c2f9
3 files changed
+127
-464
No files matched your search
+7
-1
@@ -86,8 +86,14 @@ a { color: var(--primary-dark); }
|
||||
.brand { display: inline-flex; align-items: center; gap: 8px; font-weight: 800; font-size: 1.3rem; color: var(--ink); text-decoration: none; }
|
||||
.brand .logo { font-size: 1.5rem; }
|
||||
.nav-links { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
||||
.nav-links a { text-decoration: none; color: var(--ink-soft); font-weight: 600; padding: 8px 12px; border-radius: 999px; }
|
||||
.nav-links a { text-decoration: none; color: var(--ink); font-weight: 700; padding: 8px 14px; border-radius: 999px; border: 2px solid transparent; }
|
||||
.nav-links a:hover { background: #fff; color: var(--ink); }
|
||||
/* Current page: lighter fill, darker bold text for clear, readable contrast */
|
||||
.nav-links a.active { background: #eaf0ff; color: var(--ink); font-weight: 800; }
|
||||
/* Sign-up call-to-action: outlined so it doesn't read as the active page */
|
||||
.nav-links a.cta { color: var(--primary-dark); border-color: var(--primary); }
|
||||
.nav-links a.cta:hover { background: var(--primary); color: #fff; }
|
||||
.nav-links a.cta.active { background: var(--primary); color: #fff; border-color: var(--primary); }
|
||||
|
||||
/* Forms */
|
||||
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Link from "next/link";
|
||||
import { getCurrentUser } from "@/lib/session";
|
||||
import LogoutButton from "./LogoutButton";
|
||||
import NavLinks from "./NavLinks";
|
||||
|
||||
export default async function SiteNav() {
|
||||
const user = await getCurrentUser();
|
||||
@@ -10,24 +10,7 @@ export default async function SiteNav() {
|
||||
<Link href="/" className="brand">
|
||||
<span className="logo">🐟</span> DrawIt
|
||||
</Link>
|
||||
<div className="nav-links">
|
||||
<Link href="/learn">Learn</Link>
|
||||
{user ? (
|
||||
<>
|
||||
{user.role === "admin" && <Link href="/admin">Admin</Link>}
|
||||
<Link href="/report">Report a problem</Link>
|
||||
<span className="pill role">{user.username}</span>
|
||||
<LogoutButton />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Link href="/login">Log in</Link>
|
||||
<Link href="/signup" className="btn" style={{ minHeight: 40, padding: "8px 18px" }}>
|
||||
Sign up
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<NavLinks user={user ? { username: user.username, isAdmin: user.role === "admin" } : null} />
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
|
||||
+118
-444
@@ -1,484 +1,158 @@
|
||||
/**
|
||||
* The DrawIt curriculum.
|
||||
*
|
||||
* Ability levels describe the learner. Each level has numbered sub-levels (lessons).
|
||||
* Each lesson is a sequence of steps built from the simplest possible shapes.
|
||||
*
|
||||
* SVG snippets use a 400x300 viewBox and are designed to stack: rendering steps
|
||||
* 1..n in order draws the whole picture. They power both the landing-page slideshow
|
||||
* and the step-by-step lesson guide.
|
||||
* The DrawIt curriculum. Levels describe the learner; each level has numbered sub-levels (lessons).
|
||||
* Each lesson is ordered steps built from simple shapes. SVG fragments use a 400x300 viewBox and
|
||||
* STACK: rendering steps 1..n draws the whole picture (powers the slideshow and the lesson guide).
|
||||
*/
|
||||
|
||||
export interface LevelMeta {
|
||||
key: string;
|
||||
name: string;
|
||||
emoji: string;
|
||||
blurb: string;
|
||||
}
|
||||
export interface LevelMeta { key: string; name: string; emoji: string; blurb: string; }
|
||||
|
||||
export const LEVELS: LevelMeta[] = [
|
||||
{
|
||||
key: "early-beginner",
|
||||
name: "Early Beginner",
|
||||
emoji: "🌱",
|
||||
blurb: "First lines and simple shapes. Perfect for brand-new artists.",
|
||||
},
|
||||
{
|
||||
key: "beginner",
|
||||
name: "Beginner",
|
||||
emoji: "✏️",
|
||||
blurb: "Combine shapes into friendly characters and objects.",
|
||||
},
|
||||
{
|
||||
key: "learner",
|
||||
name: "Learner",
|
||||
emoji: "🎨",
|
||||
blurb: "Add details, shading, and your own ideas.",
|
||||
},
|
||||
{
|
||||
key: "advanced-learned",
|
||||
name: "Advanced Learned",
|
||||
emoji: "🚀",
|
||||
blurb: "Proportion, perspective, and more complex scenes.",
|
||||
},
|
||||
{
|
||||
key: "superb",
|
||||
name: "Superb",
|
||||
emoji: "🌟",
|
||||
blurb: "Confident, expressive drawing in your own style.",
|
||||
},
|
||||
{ key: "early-beginner", name: "Early Beginner", emoji: "\u{1F331}", blurb: "First lines and simple shapes. Perfect for brand-new artists." },
|
||||
{ key: "beginner", name: "Beginner", emoji: "\u270F\uFE0F", blurb: "Combine shapes into friendly characters and objects." },
|
||||
{ key: "learner", name: "Learner", emoji: "\u{1F3A8}", blurb: "Add details, shading, and your own ideas." },
|
||||
{ key: "advanced-learned", name: "Advanced Learned", emoji: "\u{1F680}", blurb: "Proportion, perspective, and more complex scenes." },
|
||||
{ key: "superb", name: "Superb", emoji: "\u{1F31F}", blurb: "Confident, expressive drawing in your own style." },
|
||||
];
|
||||
|
||||
export function getLevel(key: string): LevelMeta | undefined {
|
||||
return LEVELS.find((l) => l.key === key);
|
||||
}
|
||||
export function getLevel(key: string): LevelMeta | undefined { return LEVELS.find((l) => l.key === key); }
|
||||
|
||||
/** What a step teaches. Drives the little label shown on each step. */
|
||||
export type StepKind = "construct" | "outline" | "color" | "shade" | "detail";
|
||||
|
||||
export interface LessonStep {
|
||||
n: number;
|
||||
title: string;
|
||||
instruction: string;
|
||||
tip?: string;
|
||||
/** Optional teaching tag. If omitted, a sensible label is derived from position. */
|
||||
kind?: StepKind;
|
||||
/** New shapes added at this step (cumulative when stacked 1..n). */
|
||||
svg: string;
|
||||
}
|
||||
export interface LessonStep { n: number; title: string; instruction: string; tip?: string; kind?: StepKind; svg: string; }
|
||||
|
||||
export interface Lesson {
|
||||
level: string;
|
||||
sublevel: number;
|
||||
slug: string;
|
||||
title: string;
|
||||
subject: string;
|
||||
emoji: string;
|
||||
intro: string;
|
||||
badgeKey: string;
|
||||
badgeName: string;
|
||||
steps: LessonStep[];
|
||||
}
|
||||
export interface Lesson { level: string; sublevel: number; slug: string; title: string; subject: string; emoji: string; intro: string; badgeKey: string; badgeName: string; steps: LessonStep[]; }
|
||||
|
||||
/* ----------------------- Early Beginner · Level 1 · Fish ----------------------- */
|
||||
|
||||
const FISH_STEPS: LessonStep[] = [
|
||||
{
|
||||
n: 1,
|
||||
title: "The body",
|
||||
instruction: "Draw a big oval lying on its side. This is the fish's body.",
|
||||
tip: "Slow and round — like a rugby ball or an egg.",
|
||||
svg: `<ellipse cx="205" cy="150" rx="120" ry="72" fill="#ffd566" stroke="#e0a92f" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 2,
|
||||
title: "The tail",
|
||||
instruction: "Add a triangle on the right side. That's the swishy tail!",
|
||||
tip: "Two lines out, then join them — like a slice of pizza.",
|
||||
svg: `<polygon points="318,150 392,98 392,202" fill="#ff9ec4" stroke="#e0699b" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 3,
|
||||
title: "The eye",
|
||||
instruction: "Draw a small circle near the front, then a dot inside it.",
|
||||
tip: "Keep it near the top-left so the fish looks where it's going.",
|
||||
svg: `<circle cx="135" cy="128" r="15" fill="#ffffff" stroke="#2b2440" stroke-width="3"/>
|
||||
<circle cx="131" cy="131" r="6.5" fill="#2b2440"/>`,
|
||||
},
|
||||
{
|
||||
n: 4,
|
||||
title: "The mouth",
|
||||
instruction: "Add a little curved smile at the very front (left tip).",
|
||||
tip: "Just a small smile — happy fish!",
|
||||
svg: `<path d="M92 152 q16 16 34 7" fill="none" stroke="#2b2440" stroke-width="4" stroke-linecap="round"/>`,
|
||||
},
|
||||
{
|
||||
n: 5,
|
||||
title: "The fins",
|
||||
instruction: "Add a curved fin on top and one underneath the body.",
|
||||
tip: "Like little waves on the fish's back and belly.",
|
||||
svg: `<path d="M172 84 q42 -34 84 -2" fill="#ffbf4d" stroke="#e0a92f" stroke-width="4" stroke-linecap="round"/>
|
||||
<path d="M180 218 q34 26 76 8" fill="#ffbf4d" stroke="#e0a92f" stroke-width="4" stroke-linecap="round"/>`,
|
||||
},
|
||||
{
|
||||
n: 6,
|
||||
title: "Gill & finish",
|
||||
instruction: "Draw a curved line behind the head for the gill. Your fish is done!",
|
||||
tip: "Now you can color it any way you like. 🎉",
|
||||
svg: `<path d="M168 92 q-18 58 0 116" fill="none" stroke="#e0a92f" stroke-width="3.5" stroke-linecap="round"/>`,
|
||||
},
|
||||
{ n: 1, kind: "construct", title: "The body", instruction: "Draw a big rounded body — fatter in the middle and tapering toward the tail.",
|
||||
tip: "Like a soft egg lying on its side.",
|
||||
svg: `<path d="M85 150 C 95 95, 180 78, 252 96 C 292 107, 306 128, 306 150 C 306 172, 292 193, 252 204 C 180 222, 95 205, 85 150 Z" fill="#ffd45e" stroke="#2b2440" stroke-width="4"/>` },
|
||||
{ n: 2, kind: "outline", title: "The tail", instruction: "Add a fan-shaped tail on the right with a little notch.",
|
||||
svg: `<path d="M300 150 C 332 130, 360 112, 390 100 C 374 130, 374 170, 390 200 C 360 188, 332 170, 300 150 Z" fill="#f6b73f" stroke="#2b2440" stroke-width="4" stroke-linejoin="round"/>` },
|
||||
{ n: 3, kind: "outline", title: "The fins", instruction: "Add a small fin on top (the back) and one underneath the belly.",
|
||||
svg: `<path d="M150 92 C 168 62, 212 60, 240 84 C 212 86, 178 88, 150 92 Z" fill="#f6b73f" stroke="#2b2440" stroke-width="4" stroke-linejoin="round"/><path d="M150 178 C 168 208, 206 210, 228 196 C 206 190, 176 184, 150 178 Z" fill="#f6b73f" stroke="#2b2440" stroke-width="4" stroke-linejoin="round"/>` },
|
||||
{ n: 4, kind: "detail", title: "The eye", instruction: "Draw a circle near the front with a dark pupil and a tiny white sparkle.",
|
||||
tip: "The sparkle makes it look alive!",
|
||||
svg: `<circle cx="132" cy="134" r="15" fill="#fff" stroke="#2b2440" stroke-width="3"/><circle cx="129" cy="136" r="7" fill="#2b2440"/><circle cx="125" cy="132" r="2.6" fill="#fff"/>` },
|
||||
{ n: 5, kind: "detail", title: "Mouth and gill", instruction: "Add a little smile at the front and a curved gill line behind the head.",
|
||||
svg: `<path d="M90 162 q15 13 32 4" fill="none" stroke="#2b2440" stroke-width="4" stroke-linecap="round"/><path d="M160 104 q-16 46 0 92" fill="none" stroke="#e0a92f" stroke-width="3.5" stroke-linecap="round"/>` },
|
||||
{ n: 6, kind: "detail", title: "Stripes", instruction: "Add a couple of curved stripes, then color your fish any way you like!",
|
||||
tip: "🎉",
|
||||
svg: `<path d="M205 96 q-20 54 4 110" fill="none" stroke="#f6b73f" stroke-width="7" stroke-linecap="round"/><path d="M240 100 q-16 50 4 100" fill="none" stroke="#f6b73f" stroke-width="7" stroke-linecap="round"/>` },
|
||||
];
|
||||
|
||||
export const FISH_LESSON: Lesson = {
|
||||
level: "early-beginner",
|
||||
sublevel: 1,
|
||||
slug: "fish",
|
||||
title: "Draw a Fish",
|
||||
subject: "a happy fish",
|
||||
emoji: "🐟",
|
||||
intro:
|
||||
"We'll build a friendly fish out of an oval, a triangle, a circle, and a couple of curves. Six easy steps!",
|
||||
badgeKey: "early-beginner-1-fish",
|
||||
badgeName: "Fish Friend",
|
||||
steps: FISH_STEPS,
|
||||
};
|
||||
|
||||
/* ----------------------- Early Beginner · Level 2 · Panda ----------------------- */
|
||||
export const FISH_LESSON: Lesson = { level: "early-beginner", sublevel: 1, slug: "fish", title: "Draw a Fish", subject: "a happy fish", emoji: "🐟", intro: "We'll build a friendly fish from a few simple shapes. Six easy steps!", badgeKey: "early-beginner-1-fish", badgeName: "Fish Friend", steps: FISH_STEPS };
|
||||
|
||||
const PANDA_STEPS: LessonStep[] = [
|
||||
{
|
||||
n: 1,
|
||||
title: "The head",
|
||||
instruction: "Draw one big round circle. This is the panda's face.",
|
||||
tip: "Nice and round, like a beach ball.",
|
||||
svg: `<ellipse cx="200" cy="165" rx="90" ry="82" fill="#ffffff" stroke="#2b2440" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 2,
|
||||
title: "The ears",
|
||||
instruction: "Add two small black circles on top for the ears.",
|
||||
tip: "One in each top corner of the head.",
|
||||
svg: `<circle cx="150" cy="92" r="28" fill="#2b2440"/>
|
||||
<circle cx="250" cy="92" r="28" fill="#2b2440"/>`,
|
||||
},
|
||||
{
|
||||
n: 3,
|
||||
title: "Eye patches",
|
||||
instruction: "Draw two black ovals where the eyes will go.",
|
||||
tip: "Pandas have big dark patches around their eyes.",
|
||||
svg: `<ellipse cx="167" cy="150" rx="22" ry="28" fill="#2b2440"/>
|
||||
<ellipse cx="233" cy="150" rx="22" ry="28" fill="#2b2440"/>`,
|
||||
},
|
||||
{
|
||||
n: 4,
|
||||
title: "The eyes",
|
||||
instruction: "Add a small white circle and a dot inside each patch.",
|
||||
tip: "The little white shine makes the eyes look sparkly.",
|
||||
svg: `<circle cx="170" cy="150" r="8" fill="#ffffff"/><circle cx="172" cy="152" r="4" fill="#2b2440"/>
|
||||
<circle cx="230" cy="150" r="8" fill="#ffffff"/><circle cx="228" cy="152" r="4" fill="#2b2440"/>`,
|
||||
},
|
||||
{
|
||||
n: 5,
|
||||
title: "The nose",
|
||||
instruction: "Draw a little black oval in the middle for the nose.",
|
||||
svg: `<ellipse cx="200" cy="184" rx="11" ry="7" fill="#2b2440"/>`,
|
||||
},
|
||||
{
|
||||
n: 6,
|
||||
title: "The smile",
|
||||
instruction: "Add two small curves under the nose for a happy mouth. Done!",
|
||||
tip: "Color the ears and patches black to finish. 🎉",
|
||||
svg: `<path d="M200 191 q-15 16 -30 7" fill="none" stroke="#2b2440" stroke-width="3.5" stroke-linecap="round"/>
|
||||
<path d="M200 191 q15 16 30 7" fill="none" stroke="#2b2440" stroke-width="3.5" stroke-linecap="round"/>`,
|
||||
},
|
||||
{ n: 1, kind: "construct", title: "The head", instruction: "Draw one big round face.",
|
||||
tip: "Nice and round.",
|
||||
svg: `<ellipse cx="200" cy="162" rx="92" ry="84" fill="#fff" stroke="#2b2440" stroke-width="4"/>` },
|
||||
{ n: 2, kind: "outline", title: "The ears", instruction: "Add two round ears in the top corners.",
|
||||
svg: `<circle cx="142" cy="92" r="30" fill="#2b2440"/><circle cx="258" cy="92" r="30" fill="#2b2440"/><circle cx="142" cy="92" r="14" fill="#5a5470"/><circle cx="258" cy="92" r="14" fill="#5a5470"/>` },
|
||||
{ n: 3, kind: "outline", title: "Eye patches", instruction: "Draw a dark leaf-shaped patch where each eye will go.",
|
||||
tip: "Pandas have big patches around their eyes.",
|
||||
svg: `<path d="M150 132 C 136 148, 140 178, 164 184 C 186 188, 196 166, 189 146 C 183 132, 164 124, 150 132 Z" fill="#2b2440"/><path d="M250 132 C 264 148, 260 178, 236 184 C 214 188, 204 166, 211 146 C 217 132, 236 124, 250 132 Z" fill="#2b2440"/>` },
|
||||
{ n: 4, kind: "detail", title: "The eyes", instruction: "Add a white circle, a pupil, and a sparkle inside each patch.",
|
||||
svg: `<circle cx="168" cy="158" r="9" fill="#fff"/><circle cx="170" cy="160" r="5" fill="#2b2440"/><circle cx="166" cy="156" r="2" fill="#fff"/><circle cx="232" cy="158" r="9" fill="#fff"/><circle cx="230" cy="160" r="5" fill="#2b2440"/><circle cx="228" cy="156" r="2" fill="#fff"/>` },
|
||||
{ n: 5, kind: "detail", title: "Nose and mouth", instruction: "Draw a rounded nose, a short line down, and two little smile curves.",
|
||||
svg: `<path d="M186 186 Q200 180 214 186 Q208 200 200 202 Q192 200 186 186 Z" fill="#2b2440"/><path d="M200 202 L200 212" stroke="#2b2440" stroke-width="3"/><path d="M200 212 q-13 12 -26 5 M200 212 q13 12 26 5" fill="none" stroke="#2b2440" stroke-width="3.5" stroke-linecap="round"/>` },
|
||||
{ n: 6, kind: "detail", title: "Rosy cheeks", instruction: "Add soft pink cheeks. Your panda is done!",
|
||||
tip: "🎉",
|
||||
svg: `<ellipse cx="150" cy="186" rx="15" ry="9" fill="#ffb6cf"/><ellipse cx="250" cy="186" rx="15" ry="9" fill="#ffb6cf"/>` },
|
||||
];
|
||||
|
||||
export const PANDA_LESSON: Lesson = {
|
||||
level: "early-beginner",
|
||||
sublevel: 2,
|
||||
slug: "panda",
|
||||
title: "Draw a Panda",
|
||||
subject: "a cuddly panda",
|
||||
emoji: "🐼",
|
||||
intro: "A panda is just circles and ovals! Six gentle steps and you'll have a cuddly friend.",
|
||||
badgeKey: "early-beginner-2-panda",
|
||||
badgeName: "Panda Pal",
|
||||
steps: PANDA_STEPS,
|
||||
};
|
||||
|
||||
/* ----------------------- Early Beginner · Level 3 · Flower ----------------------- */
|
||||
export const PANDA_LESSON: Lesson = { level: "early-beginner", sublevel: 2, slug: "panda", title: "Draw a Panda", subject: "a cuddly panda", emoji: "🐼", intro: "A panda is just circles and ovals. Let's make a cuddly friend!", badgeKey: "early-beginner-2-panda", badgeName: "Panda Pal", steps: PANDA_STEPS };
|
||||
|
||||
const FLOWER_STEPS: LessonStep[] = [
|
||||
{
|
||||
n: 1,
|
||||
title: "The middle",
|
||||
instruction: "Draw a circle in the middle of the page. This is the center.",
|
||||
tip: "Leave room all around it for the petals.",
|
||||
svg: `<circle cx="200" cy="120" r="34" fill="#ffc843" stroke="#e0a92f" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 2,
|
||||
title: "Top & bottom petals",
|
||||
instruction: "Add one oval petal above the center and one below.",
|
||||
tip: "Petals are just long ovals pointing outward.",
|
||||
svg: `<ellipse cx="200" cy="58" rx="22" ry="34" fill="#ff7eb6" stroke="#e0699b" stroke-width="3"/>
|
||||
<ellipse cx="200" cy="58" rx="22" ry="34" fill="#ff7eb6" stroke="#e0699b" stroke-width="3" transform="rotate(180 200 120)"/>`,
|
||||
},
|
||||
{
|
||||
n: 3,
|
||||
title: "Two more petals",
|
||||
instruction: "Add a petal on the upper-left and the lower-right.",
|
||||
svg: `<ellipse cx="200" cy="58" rx="22" ry="34" fill="#ff7eb6" stroke="#e0699b" stroke-width="3" transform="rotate(60 200 120)"/>
|
||||
<ellipse cx="200" cy="58" rx="22" ry="34" fill="#ff7eb6" stroke="#e0699b" stroke-width="3" transform="rotate(240 200 120)"/>`,
|
||||
},
|
||||
{
|
||||
n: 4,
|
||||
title: "Last petals",
|
||||
instruction: "Fill in the last two petals so the flower is full.",
|
||||
tip: "Now it looks like a daisy!",
|
||||
svg: `<ellipse cx="200" cy="58" rx="22" ry="34" fill="#ff7eb6" stroke="#e0699b" stroke-width="3" transform="rotate(120 200 120)"/>
|
||||
<ellipse cx="200" cy="58" rx="22" ry="34" fill="#ff7eb6" stroke="#e0699b" stroke-width="3" transform="rotate(300 200 120)"/>`,
|
||||
},
|
||||
{
|
||||
n: 5,
|
||||
title: "The stem",
|
||||
instruction: "Draw a tall green rectangle going down from the flower.",
|
||||
svg: `<rect x="194" y="150" width="12" height="108" rx="5" fill="#58c777" stroke="#3a9b57" stroke-width="2"/>`,
|
||||
},
|
||||
{
|
||||
n: 6,
|
||||
title: "The leaves",
|
||||
instruction: "Add two leaf ovals on the stem. Your flower is blooming!",
|
||||
tip: "Color it any colors you like. 🌸",
|
||||
svg: `<ellipse cx="160" cy="205" rx="28" ry="13" fill="#58c777" stroke="#3a9b57" stroke-width="2" transform="rotate(-25 160 205)"/>
|
||||
<ellipse cx="240" cy="222" rx="28" ry="13" fill="#58c777" stroke="#3a9b57" stroke-width="2" transform="rotate(25 240 222)"/>`,
|
||||
},
|
||||
{ n: 1, kind: "construct", title: "The middle", instruction: "Draw a circle in the center of the page.",
|
||||
tip: "Leave room all around for petals.",
|
||||
svg: `<circle cx="200" cy="118" r="34" fill="#ffd45e" stroke="#e0a92f" stroke-width="4"/>` },
|
||||
{ n: 2, kind: "outline", title: "First petals", instruction: "Add four petals: one on top, bottom, left, and right.",
|
||||
tip: "Petals are like rounded raindrops.",
|
||||
svg: `<path d="M200 86 C 180 78, 176 52, 200 40 C 224 52, 220 78, 200 86 Z" fill="#ff7eb6" stroke="#e0699b" stroke-width="3" transform="rotate(0 200 118)"/><path d="M200 86 C 180 78, 176 52, 200 40 C 224 52, 220 78, 200 86 Z" fill="#ff7eb6" stroke="#e0699b" stroke-width="3" transform="rotate(90 200 118)"/><path d="M200 86 C 180 78, 176 52, 200 40 C 224 52, 220 78, 200 86 Z" fill="#ff7eb6" stroke="#e0699b" stroke-width="3" transform="rotate(180 200 118)"/><path d="M200 86 C 180 78, 176 52, 200 40 C 224 52, 220 78, 200 86 Z" fill="#ff7eb6" stroke="#e0699b" stroke-width="3" transform="rotate(270 200 118)"/>` },
|
||||
{ n: 3, kind: "outline", title: "More petals", instruction: "Tuck four more petals into the gaps so the flower is full.",
|
||||
svg: `<path d="M200 86 C 180 78, 176 52, 200 40 C 224 52, 220 78, 200 86 Z" fill="#ff9ec4" stroke="#e0699b" stroke-width="3" transform="rotate(45 200 118)"/><path d="M200 86 C 180 78, 176 52, 200 40 C 224 52, 220 78, 200 86 Z" fill="#ff9ec4" stroke="#e0699b" stroke-width="3" transform="rotate(135 200 118)"/><path d="M200 86 C 180 78, 176 52, 200 40 C 224 52, 220 78, 200 86 Z" fill="#ff9ec4" stroke="#e0699b" stroke-width="3" transform="rotate(225 200 118)"/><path d="M200 86 C 180 78, 176 52, 200 40 C 224 52, 220 78, 200 86 Z" fill="#ff9ec4" stroke="#e0699b" stroke-width="3" transform="rotate(315 200 118)"/>` },
|
||||
{ n: 4, kind: "outline", title: "The stem", instruction: "Draw a curvy green stem going down from the flower.",
|
||||
svg: `<path d="M200 150 C 196 185, 210 214, 200 256" fill="none" stroke="#58c777" stroke-width="11" stroke-linecap="round"/>` },
|
||||
{ n: 5, kind: "outline", title: "The leaves", instruction: "Add a leaf on each side of the stem.",
|
||||
svg: `<path d="M200 198 C 168 184, 138 192, 150 218 C 162 240, 196 226, 200 198 Z" fill="#58c777" stroke="#3a9b57" stroke-width="3"/><path d="M200 226 C 232 214, 262 222, 250 246 C 238 266, 204 252, 200 226 Z" fill="#58c777" stroke="#3a9b57" stroke-width="3"/>` },
|
||||
{ n: 6, kind: "detail", title: "Seeds", instruction: "Dot some little seeds in the middle.",
|
||||
svg: `<circle cx="192" cy="112" r="4" fill="#e0a92f"/><circle cx="208" cy="114" r="4" fill="#e0a92f"/><circle cx="200" cy="124" r="4" fill="#e0a92f"/><circle cx="190" cy="126" r="3.5" fill="#e0a92f"/><circle cx="210" cy="126" r="3.5" fill="#e0a92f"/>` },
|
||||
{ n: 7, kind: "detail", title: "Leaf veins", instruction: "Add a line down each leaf, then color your flower!",
|
||||
tip: "🌸",
|
||||
svg: `<path d="M168 210 q22 4 30 16 M232 238 q-20 4 -30 -8" fill="none" stroke="#3a9b57" stroke-width="2.5"/>` },
|
||||
];
|
||||
|
||||
export const FLOWER_LESSON: Lesson = {
|
||||
level: "early-beginner",
|
||||
sublevel: 3,
|
||||
slug: "flower",
|
||||
title: "Draw a Flower",
|
||||
subject: "a cheerful flower",
|
||||
emoji: "🌸",
|
||||
intro: "A circle in the middle and oval petals all around — that's a flower! Then a stem and leaves.",
|
||||
badgeKey: "early-beginner-3-flower",
|
||||
badgeName: "Flower Power",
|
||||
steps: FLOWER_STEPS,
|
||||
};
|
||||
|
||||
/* ----------------------- Early Beginner · Level 4 · Unicorn ----------------------- */
|
||||
export const FLOWER_LESSON: Lesson = { level: "early-beginner", sublevel: 3, slug: "flower", title: "Draw a Flower", subject: "a cheerful flower", emoji: "🌸", intro: "A circle in the middle and petals all around — then a stem and leaves.", badgeKey: "early-beginner-3-flower", badgeName: "Flower Power", steps: FLOWER_STEPS };
|
||||
|
||||
const UNICORN_STEPS: LessonStep[] = [
|
||||
{
|
||||
n: 1,
|
||||
title: "The head",
|
||||
instruction: "Draw a tall oval for the unicorn's head.",
|
||||
tip: "A little taller than it is wide.",
|
||||
svg: `<ellipse cx="200" cy="165" rx="66" ry="80" fill="#ffffff" stroke="#2b2440" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 2,
|
||||
title: "The ears",
|
||||
instruction: "Add a pointy triangle ear on each side of the top.",
|
||||
svg: `<polygon points="152,100 138,58 176,86" fill="#ffffff" stroke="#2b2440" stroke-width="4" stroke-linejoin="round"/>
|
||||
<polygon points="248,100 262,58 224,86" fill="#ffffff" stroke="#2b2440" stroke-width="4" stroke-linejoin="round"/>`,
|
||||
},
|
||||
{
|
||||
n: 3,
|
||||
title: "The magic horn",
|
||||
instruction: "Draw a tall triangle in the middle on top — the horn!",
|
||||
tip: "Add a few short lines for the swirl.",
|
||||
svg: `<polygon points="200,92 186,22 214,92" fill="#ffc843" stroke="#e0a92f" stroke-width="3" stroke-linejoin="round"/>
|
||||
<path d="M192 78 l16 -5 M195 60 l12 -4 M198 44 l9 -3" stroke="#e0a92f" stroke-width="2.5" fill="none" stroke-linecap="round"/>`,
|
||||
},
|
||||
{
|
||||
n: 4,
|
||||
title: "The eyes",
|
||||
instruction: "Add two tall oval eyes with little lashes.",
|
||||
tip: "Pink cheeks make it extra cute.",
|
||||
svg: `<ellipse cx="174" cy="158" rx="7" ry="10" fill="#2b2440"/>
|
||||
<ellipse cx="226" cy="158" rx="7" ry="10" fill="#2b2440"/>
|
||||
<path d="M163 150 q6 -8 14 -5 M237 150 q-6 -8 -14 -5" stroke="#2b2440" stroke-width="2.5" fill="none" stroke-linecap="round"/>
|
||||
<circle cx="158" cy="192" r="12" fill="#ffd1e3"/><circle cx="242" cy="192" r="12" fill="#ffd1e3"/>`,
|
||||
},
|
||||
{
|
||||
n: 5,
|
||||
title: "Nose & mouth",
|
||||
instruction: "Add two dots for the nose and a small smile.",
|
||||
svg: `<circle cx="186" cy="208" r="4" fill="#2b2440"/>
|
||||
<circle cx="214" cy="208" r="4" fill="#2b2440"/>
|
||||
<path d="M186 224 q14 12 28 0" fill="none" stroke="#2b2440" stroke-width="3" stroke-linecap="round"/>`,
|
||||
},
|
||||
{
|
||||
n: 6,
|
||||
title: "The rainbow mane",
|
||||
instruction: "Add a curly forelock and flowing strands down one side.",
|
||||
tip: "Use lots of colors — that's the unicorn magic! 🦄",
|
||||
svg: `<path d="M176 94 q-12 24 8 40 M200 94 q-6 26 0 44 M224 94 q12 24 -8 40" fill="none" stroke="#ff7eb6" stroke-width="9" stroke-linecap="round"/>
|
||||
<path d="M256 122 q42 20 30 72" stroke="#a06bff" stroke-width="13" fill="none" stroke-linecap="round"/>
|
||||
<path d="M258 144 q44 24 24 84" stroke="#7ec8ff" stroke-width="13" fill="none" stroke-linecap="round"/>
|
||||
<path d="M252 166 q40 28 14 80" stroke="#ff7eb6" stroke-width="13" fill="none" stroke-linecap="round"/>`,
|
||||
},
|
||||
{ n: 1, kind: "construct", title: "The head", instruction: "Draw a rounded head that's a little narrower at the chin.",
|
||||
svg: `<path d="M120 152 C 120 96, 165 72, 200 72 C 235 72, 280 96, 280 152 C 280 202, 246 236, 200 240 C 154 236, 120 202, 120 152 Z" fill="#fff" stroke="#2b2440" stroke-width="4"/>` },
|
||||
{ n: 2, kind: "outline", title: "The ears", instruction: "Add a pointy ear on each side with a pink inside.",
|
||||
svg: `<path d="M150 98 C 138 72, 132 58, 150 60 C 166 64, 174 84, 180 96 Z" fill="#fff" stroke="#2b2440" stroke-width="4" stroke-linejoin="round"/><path d="M250 98 C 262 72, 268 58, 250 60 C 234 64, 226 84, 220 96 Z" fill="#fff" stroke="#2b2440" stroke-width="4" stroke-linejoin="round"/><path d="M156 84 q-6 12 0 22 M244 84 q6 12 0 22" fill="#ffd1e3"/>` },
|
||||
{ n: 3, kind: "outline", title: "The magic horn", instruction: "Draw a tall horn in the middle with little swirl lines.",
|
||||
svg: `<polygon points="200,80 188,18 212,80" fill="#ffd45e" stroke="#e0a92f" stroke-width="3" stroke-linejoin="round"/><path d="M193 66 l14 -5 M196 50 l11 -4 M199 36 l8 -3" stroke="#e0a92f" stroke-width="2.5" fill="none" stroke-linecap="round"/>` },
|
||||
{ n: 4, kind: "detail", title: "Eyes and cheeks", instruction: "Add two big eyes with sparkles and soft rosy cheeks.",
|
||||
svg: `<ellipse cx="172" cy="158" rx="8" ry="11" fill="#2b2440"/><circle cx="169" cy="153" r="3" fill="#fff"/><ellipse cx="228" cy="158" rx="8" ry="11" fill="#2b2440"/><circle cx="225" cy="153" r="3" fill="#fff"/><ellipse cx="150" cy="190" rx="13" ry="8" fill="#ffd1e3"/><ellipse cx="250" cy="190" rx="13" ry="8" fill="#ffd1e3"/>` },
|
||||
{ n: 5, kind: "detail", title: "Nose and smile", instruction: "Add two tiny nostril dots and a friendly smile.",
|
||||
svg: `<circle cx="188" cy="210" r="3.5" fill="#2b2440"/><circle cx="212" cy="210" r="3.5" fill="#2b2440"/><path d="M186 222 q14 12 28 0" fill="none" stroke="#2b2440" stroke-width="3" stroke-linecap="round"/>` },
|
||||
{ n: 6, kind: "color", title: "The rainbow mane", instruction: "Add flowing locks of color down one side of the head.",
|
||||
tip: "Use lots of colors!",
|
||||
svg: `<path d="M256 118 C 300 130, 300 175, 282 210 C 292 178, 276 150, 256 140 Z" fill="#c79bff"/><path d="M262 140 C 305 160, 300 205, 276 236 C 290 200, 272 168, 252 158 Z" fill="#8ec9ff"/><path d="M252 170 C 292 196, 280 236, 252 258 C 270 224, 248 192, 238 184 Z" fill="#ff9ec4"/>` },
|
||||
{ n: 7, kind: "detail", title: "Forelock and sparkles", instruction: "Add a curl between the ears and a few sparkles. 🦄",
|
||||
svg: `<path d="M176 92 C 160 110, 168 140, 190 132 C 176 120, 182 104, 196 96 Z" fill="#c79bff"/><path d="M200 88 C 196 120, 214 122, 214 96 Z" fill="#8ec9ff"/><g stroke="#ffd45e" stroke-width="3" fill="none" stroke-linecap="round"><path d="M300 95 l0 14 M293 102 l14 0"/><path d="M120 110 l0 10 M115 115 l10 0"/></g>` },
|
||||
];
|
||||
|
||||
export const UNICORN_LESSON: Lesson = {
|
||||
level: "early-beginner",
|
||||
sublevel: 4,
|
||||
slug: "unicorn",
|
||||
title: "Draw a Unicorn",
|
||||
subject: "a magical unicorn",
|
||||
emoji: "🦄",
|
||||
intro: "An oval head, triangle ears and horn, then a rainbow mane. Let's make some magic!",
|
||||
badgeKey: "early-beginner-4-unicorn",
|
||||
badgeName: "Unicorn Magic",
|
||||
steps: UNICORN_STEPS,
|
||||
};
|
||||
|
||||
/* ----------------------- Early Beginner · Level 5 · Tree ----------------------- */
|
||||
export const UNICORN_LESSON: Lesson = { level: "early-beginner", sublevel: 4, slug: "unicorn", title: "Draw a Unicorn", subject: "a magical unicorn", emoji: "🦄", intro: "A rounded head, a sparkly horn, and a rainbow mane. Let's make magic!", badgeKey: "early-beginner-4-unicorn", badgeName: "Unicorn Magic", steps: UNICORN_STEPS };
|
||||
|
||||
const TREE_STEPS: LessonStep[] = [
|
||||
{
|
||||
n: 1,
|
||||
title: "The trunk",
|
||||
instruction: "Draw a tall brown rectangle. This is the tree trunk.",
|
||||
{ n: 1, kind: "construct", title: "The trunk", instruction: "Draw a trunk that's a little wider at the bottom.",
|
||||
tip: "Stand it up tall in the middle.",
|
||||
svg: `<rect x="184" y="150" width="32" height="110" rx="6" fill="#b5793f" stroke="#8a5a2b" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 2,
|
||||
title: "Big green bush",
|
||||
instruction: "Draw a big green circle on top of the trunk for leaves.",
|
||||
svg: `<circle cx="200" cy="120" r="70" fill="#62c178" stroke="#3a9b57" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 3,
|
||||
title: "Left bump",
|
||||
instruction: "Add another green circle on the upper-left.",
|
||||
svg: `<path d="M178 262 C 176 222, 184 200, 190 176 L210 176 C 216 200, 224 222, 222 262 C 214 266, 186 266, 178 262 Z" fill="#b5793f" stroke="#8a5a2b" stroke-width="4"/>` },
|
||||
{ n: 2, kind: "outline", title: "The branches", instruction: "Add two branches reaching up from the trunk.",
|
||||
svg: `<path d="M198 180 C 190 152, 166 142, 150 132" fill="none" stroke="#8a5a2b" stroke-width="12" stroke-linecap="round"/><path d="M204 180 C 214 152, 238 144, 254 134" fill="none" stroke="#8a5a2b" stroke-width="12" stroke-linecap="round"/>` },
|
||||
{ n: 3, kind: "outline", title: "Leafy clumps", instruction: "Draw a big round clump of leaves up top and one on the left.",
|
||||
tip: "Treetops are nice and lumpy.",
|
||||
svg: `<circle cx="150" cy="95" r="46" fill="#62c178" stroke="#3a9b57" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 4,
|
||||
title: "Right bump",
|
||||
instruction: "Add a green circle on the upper-right too.",
|
||||
svg: `<circle cx="252" cy="100" r="44" fill="#62c178" stroke="#3a9b57" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 5,
|
||||
title: "Top bump",
|
||||
instruction: "One more green circle on top to round it off.",
|
||||
svg: `<circle cx="205" cy="66" r="46" fill="#62c178" stroke="#3a9b57" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 6,
|
||||
title: "Fruit & grass",
|
||||
instruction: "Add a few red fruits and a wavy line of grass at the bottom.",
|
||||
tip: "Your tree is grown! 🌳",
|
||||
svg: `<circle cx="170" cy="112" r="7" fill="#e85a5a"/>
|
||||
<circle cx="228" cy="96" r="7" fill="#e85a5a"/>
|
||||
<circle cx="205" cy="142" r="7" fill="#e85a5a"/>
|
||||
<path d="M120 260 q20 -16 40 0 q20 -16 40 0 q20 -16 40 0 q20 -16 40 0" fill="none" stroke="#58c777" stroke-width="4" stroke-linecap="round"/>`,
|
||||
},
|
||||
svg: `<circle cx="150" cy="120" r="54" fill="#62c178" stroke="#3a9b57" stroke-width="4"/><circle cx="205" cy="86" r="60" fill="#62c178" stroke="#3a9b57" stroke-width="4"/>` },
|
||||
{ n: 4, kind: "outline", title: "More leaves", instruction: "Add clumps on the right and middle to fill out the top.",
|
||||
svg: `<circle cx="258" cy="120" r="50" fill="#62c178" stroke="#3a9b57" stroke-width="4"/><circle cx="200" cy="135" r="56" fill="#62c178" stroke="#3a9b57" stroke-width="4"/>` },
|
||||
{ n: 5, kind: "detail", title: "Apples", instruction: "Dot a few red apples in the leaves.",
|
||||
svg: `<circle cx="160" cy="120" r="8" fill="#e8554e"/><circle cx="232" cy="100" r="8" fill="#e8554e"/><circle cx="205" cy="150" r="8" fill="#e8554e"/><circle cx="255" cy="140" r="8" fill="#e8554e"/>` },
|
||||
{ n: 6, kind: "detail", title: "Grass", instruction: "Add a wavy line of grass along the bottom.",
|
||||
svg: `<path d="M120 262 q14 -18 28 0 q14 -18 28 0 q14 -18 28 0 q14 -18 28 0 q14 -18 28 0" fill="none" stroke="#58c777" stroke-width="4" stroke-linecap="round"/>` },
|
||||
{ n: 7, kind: "detail", title: "Bark", instruction: "Add a couple of bark lines on the trunk, then color your tree!",
|
||||
tip: "🌳",
|
||||
svg: `<path d="M194 198 q4 24 0 56 M206 198 q-3 24 0 54" fill="none" stroke="#8a5a2b" stroke-width="2.5"/>` },
|
||||
];
|
||||
|
||||
export const TREE_LESSON: Lesson = {
|
||||
level: "early-beginner",
|
||||
sublevel: 5,
|
||||
slug: "tree",
|
||||
title: "Draw a Tree",
|
||||
subject: "a leafy tree",
|
||||
emoji: "🌳",
|
||||
intro: "A trunk and a bunch of bumpy green circles make a leafy tree. Add some fruit at the end!",
|
||||
badgeKey: "early-beginner-5-tree",
|
||||
badgeName: "Tree Top",
|
||||
steps: TREE_STEPS,
|
||||
};
|
||||
|
||||
/* ----------------------- Early Beginner · Level 6 · Dinosaur ----------------------- */
|
||||
export const TREE_LESSON: Lesson = { level: "early-beginner", sublevel: 5, slug: "tree", title: "Draw a Tree", subject: "a leafy tree", emoji: "🌳", intro: "A trunk, some branches, and big clumps of leaves make a leafy tree.", badgeKey: "early-beginner-5-tree", badgeName: "Tree Top", steps: TREE_STEPS };
|
||||
|
||||
const DINO_STEPS: LessonStep[] = [
|
||||
{
|
||||
n: 1,
|
||||
title: "The body",
|
||||
instruction: "Draw a big oval lying down. This is the dinosaur's body.",
|
||||
tip: "A long-neck dinosaur is nice and round.",
|
||||
svg: `<ellipse cx="205" cy="195" rx="82" ry="48" fill="#7ec86a" stroke="#4f9b46" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 2,
|
||||
title: "The long neck",
|
||||
instruction: "Draw a long oval reaching up from the left of the body.",
|
||||
tip: "Lean it up and to the side.",
|
||||
svg: `<ellipse cx="158" cy="120" rx="20" ry="62" fill="#7ec86a" stroke="#4f9b46" stroke-width="4" transform="rotate(-18 158 120)"/>`,
|
||||
},
|
||||
{
|
||||
n: 3,
|
||||
title: "The head",
|
||||
instruction: "Add a small oval on top of the neck, and a dot for the eye.",
|
||||
svg: `<ellipse cx="136" cy="58" rx="28" ry="22" fill="#7ec86a" stroke="#4f9b46" stroke-width="4"/>
|
||||
<circle cx="124" cy="52" r="4" fill="#2b2440"/>`,
|
||||
},
|
||||
{
|
||||
n: 4,
|
||||
title: "The tail",
|
||||
instruction: "Draw a long pointy tail sweeping out to the right.",
|
||||
svg: `<path d="M270 200 Q345 175 392 158 Q345 200 282 222 Z" fill="#7ec86a" stroke="#4f9b46" stroke-width="4" stroke-linejoin="round"/>`,
|
||||
},
|
||||
{
|
||||
n: 5,
|
||||
title: "The legs",
|
||||
instruction: "Add two chunky rectangle legs under the body.",
|
||||
svg: `<rect x="166" y="230" width="26" height="46" rx="7" fill="#7ec86a" stroke="#4f9b46" stroke-width="4"/>
|
||||
<rect x="222" y="230" width="26" height="46" rx="7" fill="#7ec86a" stroke="#4f9b46" stroke-width="4"/>`,
|
||||
},
|
||||
{
|
||||
n: 6,
|
||||
title: "Spots & smile",
|
||||
instruction: "Add a few darker spots and a little smile. Roar!",
|
||||
tip: "You can color your dino any color — they didn't leave us photos! 🦕",
|
||||
svg: `<circle cx="205" cy="180" r="9" fill="#4f9b46"/>
|
||||
<circle cx="238" cy="198" r="8" fill="#4f9b46"/>
|
||||
<circle cx="182" cy="208" r="7" fill="#4f9b46"/>
|
||||
<path d="M120 66 q12 8 23 2" fill="none" stroke="#2b2440" stroke-width="2.5" stroke-linecap="round"/>`,
|
||||
},
|
||||
{ n: 1, kind: "construct", title: "The body", instruction: "Draw a big rounded body.",
|
||||
tip: "A long-neck dino is nice and round.",
|
||||
svg: `<path d="M118 200 C 118 166, 160 150, 210 150 C 270 150, 302 170, 302 200 C 302 230, 262 246, 205 246 C 155 246, 118 230, 118 200 Z" fill="#7ec86a" stroke="#4f9b46" stroke-width="4"/>` },
|
||||
{ n: 2, kind: "outline", title: "The long neck", instruction: "Sweep a long neck up from the left of the body.",
|
||||
tip: "Curve it gently.",
|
||||
svg: `<path d="M150 168 C 122 122, 112 80, 124 55 C 130 44, 148 46, 152 58 C 146 86, 162 124, 180 160 Z" fill="#7ec86a" stroke="#4f9b46" stroke-width="4" stroke-linejoin="round"/>` },
|
||||
{ n: 3, kind: "detail", title: "The head", instruction: "Add a small rounded head on top with a dot for the eye.",
|
||||
svg: `<path d="M100 46 C 100 32, 120 28, 138 34 C 152 39, 154 56, 142 64 C 126 72, 104 64, 98 54 Z" fill="#7ec86a" stroke="#4f9b46" stroke-width="4" stroke-linejoin="round"/><circle cx="118" cy="46" r="4" fill="#2b2440"/>` },
|
||||
{ n: 4, kind: "outline", title: "The tail", instruction: "Draw a long tail swooping out to the right.",
|
||||
svg: `<path d="M298 198 C 338 184, 372 176, 398 168 C 380 192, 360 206, 304 220 C 300 213, 298 206, 298 198 Z" fill="#7ec86a" stroke="#4f9b46" stroke-width="4" stroke-linejoin="round"/>` },
|
||||
{ n: 5, kind: "outline", title: "The legs", instruction: "Add two sturdy legs underneath.",
|
||||
svg: `<path d="M168 242 C 165 264, 166 278, 180 280 C 193 280, 192 264, 190 242 Z" fill="#7ec86a" stroke="#4f9b46" stroke-width="4" stroke-linejoin="round"/><path d="M232 244 C 229 266, 230 280, 244 282 C 257 282, 256 266, 254 244 Z" fill="#7ec86a" stroke="#4f9b46" stroke-width="4" stroke-linejoin="round"/>` },
|
||||
{ n: 6, kind: "detail", title: "Back plates", instruction: "Add little triangle plates along the back.",
|
||||
svg: `<path d="M150 150 l10 -16 l12 16 Z" fill="#4f9b46"/><path d="M186 146 l11 -17 l12 17 Z" fill="#4f9b46"/><path d="M224 147 l11 -16 l12 16 Z" fill="#4f9b46"/><path d="M262 152 l10 -15 l12 16 Z" fill="#4f9b46"/>` },
|
||||
{ n: 7, kind: "detail", title: "Spots", instruction: "Dot a few spots on the body.",
|
||||
svg: `<circle cx="205" cy="188" r="9" fill="#4f9b46"/><circle cx="240" cy="200" r="7" fill="#4f9b46"/><circle cx="180" cy="210" r="6" fill="#4f9b46"/>` },
|
||||
{ n: 8, kind: "detail", title: "Smile", instruction: "Add a friendly smile, then color your dino any color you like!",
|
||||
tip: "🦕",
|
||||
svg: `<path d="M108 56 q12 10 24 3" fill="none" stroke="#2b2440" stroke-width="2.5" stroke-linecap="round"/>` },
|
||||
];
|
||||
|
||||
export const DINO_LESSON: Lesson = {
|
||||
level: "early-beginner",
|
||||
sublevel: 6,
|
||||
slug: "dinosaur",
|
||||
title: "Draw a Dinosaur",
|
||||
subject: "a friendly dinosaur",
|
||||
emoji: "🦕",
|
||||
intro: "A round body, a long neck, a small head, and a swooshy tail — meet your long-neck dino!",
|
||||
badgeKey: "early-beginner-6-dinosaur",
|
||||
badgeName: "Dino Master",
|
||||
steps: DINO_STEPS,
|
||||
};
|
||||
export const DINO_LESSON: Lesson = { level: "early-beginner", sublevel: 6, slug: "dinosaur", title: "Draw a Dinosaur", subject: "a friendly dinosaur", emoji: "🦕", intro: "A round body, a long neck, a small head, and a swooshy tail!", badgeKey: "early-beginner-6-dinosaur", badgeName: "Dino Master", steps: DINO_STEPS };
|
||||
|
||||
export const LESSONS: Lesson[] = [
|
||||
FISH_LESSON,
|
||||
PANDA_LESSON,
|
||||
FLOWER_LESSON,
|
||||
UNICORN_LESSON,
|
||||
TREE_LESSON,
|
||||
DINO_LESSON,
|
||||
];
|
||||
export const LESSONS: Lesson[] = [FISH_LESSON, PANDA_LESSON, FLOWER_LESSON, UNICORN_LESSON, TREE_LESSON, DINO_LESSON];
|
||||
|
||||
export function getLesson(level: string, sublevel: number): Lesson | undefined {
|
||||
return LESSONS.find((l) => l.level === level && l.sublevel === sublevel);
|
||||
}
|
||||
|
||||
export function getLessonBySlug(slug: string): Lesson | undefined {
|
||||
return LESSONS.find((l) => l.slug === slug);
|
||||
}
|
||||
|
||||
/** SVG markup that stacks steps 1..upTo (inclusive). Wrapped in a viewBox group. */
|
||||
export function cumulativeSvg(lesson: Lesson, upTo: number): string {
|
||||
return lesson.steps
|
||||
.filter((s) => s.n <= upTo)
|
||||
.map((s) => s.svg)
|
||||
.join("\n");
|
||||
}
|
||||
export function getLesson(level: string, sublevel: number): Lesson | undefined { return LESSONS.find((l) => l.level === level && l.sublevel === sublevel); }
|
||||
export function getLessonBySlug(slug: string): Lesson | undefined { return LESSONS.find((l) => l.slug === slug); }
|
||||
export function cumulativeSvg(lesson: Lesson, upTo: number): string { return lesson.steps.filter((s) => s.n <= upTo).map((s) => s.svg).join("\n"); }
|
||||
Reference in new issue
Block a user