diff --git a/src/app/learn/page.tsx b/src/app/learn/page.tsx index 6f2684e..860aa40 100644 --- a/src/app/learn/page.tsx +++ b/src/app/learn/page.tsx @@ -4,6 +4,9 @@ import { LEVELS, getSubjects, getGroupedSubjects, BEGINNER_PACKS, lessonStepCoun import { getCurrentUser } from "@/lib/session"; import { getCompletedSteps, hasBadge } from "@/lib/progress"; import { isLevelUnlocked, countCompletedLessons, isPackComplete, BEGINNER_UNLOCK_THRESHOLD } from "@/lib/gating"; +import { canCreate } from "@/lib/session"; +import { isCreateEnabled } from "@/lib/comfyui"; +import { listCreatedForUser, listPromoted, buildCreatedLessons, type CreatedLessonRow } from "@/lib/createdLessons"; export const metadata = { title: "Learn · DrawIt" }; export const dynamic = "force-dynamic"; @@ -70,6 +73,47 @@ export default async function LearnPage() { ); }; + const creator = canCreate(user); + const createEnabled = isCreateEnabled(); + const toCreatedSubject = (row: CreatedLessonRow) => ({ key: row.slug, name: row.subject, emoji: row.emoji, order: 0, lessons: buildCreatedLessons(row) }); + + // "Create your own" entry + the user's creations + any promoted (global) ones, for EB/Beginner. + const creationsSection = (lvlKey: string) => { + if (lvlKey !== "early-beginner" && lvlKey !== "beginner") return null; + // Create UI is hidden entirely unless ComfyUI is configured (being a Creator alone isn't enough). + const canCreateNow = creator && createEnabled; + const mine: CreatedLessonRow[] = user && creator ? listCreatedForUser(user.id, lvlKey) : []; + const featured: CreatedLessonRow[] = listPromoted(lvlKey); + const ready = mine.filter((r) => r.status === "ready"); + const pending = mine.filter((r) => ["pending", "generating", "needs_review"].includes(r.status)); + // Nothing to show: Create disabled and no existing or featured creations. + if (!canCreateNow && ready.length === 0 && pending.length === 0 && featured.length === 0) return null; + return ( +
+
+ {canCreateNow ? "✨ Create your own" : "✨ My Creations"} + {canCreateNow && + New lesson} +
+
+ {ready.map((r) => subjectAccordion(toCreatedSubject(r), false))} + {pending.map((r) => ( +
+ {r.emoji} {r.subject}{" "} + {r.status === "needs_review" ? "⏳ Waiting for approval" : "🎨 Drawing…"} +
+ ))} + {canCreateNow && ready.length === 0 && pending.length === 0 &&

No creations yet — tap “+ New lesson”.

} + {featured.length > 0 && ( + <> + 🌟 Featured creations + {featured.map((r) => subjectAccordion(toCreatedSubject(r), false))} + + )} +
+
+ ); + }; + return ( <> @@ -116,6 +160,7 @@ export default async function LearnPage() { ) : lvl.key === "beginner" ? ( // Beginner: group subjects into packs, each with a per-pack badge.
+ {creationsSection(lvl.key)} {BEGINNER_PACKS.map((pack) => { const packSubjects = subjects.filter((s) => pack.subjectKeys.includes(s.key)); const packDone = !!user && isPackComplete(user.id, pack); @@ -136,51 +181,5 @@ export default async function LearnPage() { ) : lvl.key === "early-beginner" ? ( // Early Beginner: themed groups, each holding its subjects.
- {getGroupedSubjects(lvl.key).map((group) => { - const groupDone = group.subjects.every((s) => subjectComplete(s)); - return ( -
-
- {group.emoji} {group.name} - {group.subjects.filter((s) => subjectComplete(s)).length}/{group.subjects.length} done -
-
- {group.subjects.map((subj) => subjectAccordion(subj, subj.key === firstIncomplete))} -
-
- ); - })} -
- ) : ( - // Any future flat level -
- {subjects.map((subj) => { - const phased = subj.lessons.length > 1 || !!subj.lessons[0].phase; - if (!phased) { - const l = subj.lessons[0]; - const done = isDone(l); - const inProg = !done && doneCount(l) > 0; - return ( - -
- {subj.emoji} {l.title} - {done ? ✓ Done : inProg ? Step {Math.min(doneCount(l) + 1, lessonStepCount(l))}/{lessonStepCount(l)} : {lessonStepCount(l)} steps} -
- - ); - } - return subjectAccordion(subj, subj.key === firstIncomplete); - })} -
- )} -
- ); - })} - - - - ); -} - -const subCard = (done: boolean): React.CSSProperties => ({ textDecoration: "none", color: "inherit", border: done ? "2px solid var(--leaf)" : "2px solid var(--line)", boxShadow: "none", padding: 14 }); -const phaseBox: React.CSSProperties = { display: "block", border: "2px solid var(--line)", borderRadius: 12, padding: "12px 14px", background: "var(--surface)" }; + {creationsSection(lvl.key)} + {getGroupedSubjects(lvl.key).map((group) = \ No newline at end of file