diff --git a/.gitignore b/.gitignore index b352ec1..758a3fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,12 @@ node_modules/ client/dist/ .env +*.log npm-debug.log* +yarn-debug.log* +yarn-error.log* .DS_Store +.vscode/ +.idea/ +*.swp + diff --git a/PRODUCT.md b/PRODUCT.md new file mode 100644 index 0000000..1444c01 --- /dev/null +++ b/PRODUCT.md @@ -0,0 +1,157 @@ +# PyBe — Product Document + +> **Version:** 2.2.0 +> **Release Date:** July 2026 +> **Status:** Active development — IIT Ropar Summer Internship + +--- + +## Version History + +| Version | Description | +|---|---| +| **v1.0.0** | Initial prototype — single-page React app, plain CSS, 30 classic scenarios, no routing, no auth | +| **v2.0.0** | Multi-page redesign — React Router, 6 UADE themes, 54+ scenarios, HorcruxVault, premium dark UI | +| **v2.1.0** | Auth system, left curriculum sidebar, sequential chapter learning flow, GSAP animations, docs-style theory reveal | +| **v2.2.0** | Dynamic dashboard theme selector (Default, Potterheads, Marvel, Anime), theme-switched case studies & scenarios, tailored Dark & Light mode color palettes, **First-Principles Friction Simulator**, **Interactive Mental Model Lab**, **Instant Micro-Sandbox**, and **Socratic Misconception Spotter** | + +--- + +## What's New in v2.2 + +### 1. First-Principles Learning Engine +- **Friction Simulator (Before vs After)**: Side-by-side comparison cards embedded in every chapter's Theory phase. Compares fragile manual code without the construct against clean Python code, explaining the exact pain point that forced computer scientists to invent the construct. +- **Interactive Mental Model Lab**: Live hands-on visualizers embedded in the Theory phase showing RAM memory slots (`0x7F8`), arithmetic operator pipelines, zero-indexed string character arrays, decision tree flowchart branching, loop iteration steppers, array append/pop counters, hash table lookup tables ($O(1)$ key mapping), unique set buckets, function machine inputs/outputs, binary/linear search scanners, `try/except` exception shields, array sort steppers, and RAM $\rightarrow$ Disk storage buffers. +- **Instant Micro-Sandbox / Interactive Try-It Widget**: Embedded live browser-based Python code editor and executor right below code examples. Features code resetting, live syntax validation, and an authentic dark terminal stdout console (`$ python main.py`). +- **Socratic Misconception Spotter**: Automated analysis of student reasoning during the Reasoning Summary phase (`SummaryPhase`). Detects 5 common beginner mental traps (0-indexing offsets, `=` assignment vs `==` comparison, string immutability in RAM, parallel list desynchronization, unhandled edge-case inputs) and provides targeted Socratic guiding prompts. + +### 2. Dynamic Dashboard Theme System +- Logged-in users can choose between 4 theme worlds on their dashboard: + 1. **Default Theme** 🐍: Classic PyBe Chai Stall & ISRO experience. + 2. **Potterheads** 🧙‍♂️: Hogwarts potions brewing, Marauder's map & spell vaults. + 3. **Marvel** 🦾: Avengers AI, J.A.R.V.I.S. suit telemetry & Infinity Stone grid. + 4. **Anime** ⚔️: Hidden Leaf Jutsu chakra engine & Legendary Creature hunter. + +### 3. Theme-Switched Case Studies & Scenarios +- Choosing a theme dynamically updates case study arcs and scenario recommendations across the dashboard, case study browser, scenario browser, and chapter learning flow. +- Core curriculum, syllabus structure, and Python theory remain completely preserved. +- **93 Total Seeded Scenarios**: 54 Default/Classic + 13 Potterheads + 13 Marvel + 13 Anime scenarios covering all 13 curriculum chapters. + +### 4. Tailored Dark & Light Mode Color Palettes +- Custom color tokens for both Light and Dark modes: + - **Potterheads Light**: Warm Hogwarts parchment background (`#FAF4E8`), wizard ink text (`#291E16`), Gryffindor amber accents (`#B45309`). + - **Marvel Light**: Stark Titanium metallic background (`#F1F5F9`), titanium dark text (`#0F172A`), Stark Red accents (`#DC2626`). + - **Anime Light**: Tokyo Sakura Lavender background (`#FAF5FF`), cyber dark text (`#1E1B4B`), Tokyo Magenta Pink accents (`#C026D3`). +- **Landing Page Integrity**: Unauthenticated visitors on `/` retain standard public landing page styling untouched. + +### 1. Authentication (Login / Signup) +- Local `localStorage`-based auth — no backend changes needed, fully offline-capable +- `AuthContext.jsx` manages sessions, progress-per-user, and chapter completion state +- Chapter completion is stored in `localStorage` keyed by `user.id` — survives browser refresh +- `Protected` route guard — unauthenticated users are redirected to `/login` + +### 2. Left Curriculum Sidebar (replaces top navbar) +- Fixed `260px` sidebar with collapsible sections +- 4 sections: Getting Started, Basics, Intermediate, Advanced +- 13 chapters total, each with status dot (○ not started / ✓ done) +- Overall progress bar at the top +- User chip with avatar initials +- GSAP stagger-in animation on first render +- Mobile: hamburger overlay that slides the sidebar in + +### 3. Sequential Chapter Learning Flow +Every chapter follows a fixed 4-phase flow: + +| Phase | Description | +|---|---| +| **Intro** | Hook, what you'll figure out, setup scenario, "Let's go" | +| **Questions** | Scenarios one-by-one (slide in/out with GSAP), plain-English reasoning textarea | +| **Summary** | Reasoning recap with educational score labels (🔥 Excellent / ⚡ Strong / 💡 Good / 📈 Getting there / 🌱 Just beginning) | +| **Theory** | Docs-style concept explanation (eyebrow → title → gradient concept name → prose → code block → callout → key takeaway → Mark Complete) | + +### 4. Educational Score System +- Primary: backend learning engine score (`promptScore`) from keyword/concept matching +- Fallback: client-side estimator based on reasoning length + quality signals (because/since/instead/organize/etc.) +- Score displayed as level label + emoji + colour — not just a number +- Per-answer badges in summary view + +### 5. Docs-style Theory Reveal (fixed) +- Previously: GSAP `.from('.theory-body > *')` re-animated already-visible headings, causing them to flash/disappear +- Fixed: All theory elements targeted by individual class selectors via `querySelectorAll`, then animated once with `gsap.set` + `gsap.to`. No double-animation. +- Phase reset: `useEffect([chapterId])` resets all state when the chapterId param changes, so "Mark Complete → next chapter" always starts at Intro, not Theory. + +### 6. Curriculum Structure + +| Section | Chapters | +|---|---| +| 🌱 Getting Started | Variables, Operators & Math, Strings & Text | +| 📚 Basics | Making Decisions (if/else), Loops, Lists | +| ⚙️ Intermediate | Dictionaries, Sets, Functions, Search & Filter | +| ⚡ Advanced | Error Handling, Algorithms, Files & Data | + +Each chapter contains: intro (hook, vibe, discover), theory (layman explanation, code example, real-world connection, key takeaway), and maps to 2–4 scenarios from the DB. + +### 7. Theory Content (per chapter) +All 13 chapters have hand-written theory content in `curriculum.js`: +- Written at a **junior student level** — plain English, no jargon +- Explains the concept as a rediscovery of what the learner just reasoned about +- Includes working code examples with in-line comments +- Ends with a key takeaway sentence +- Grounded in Barrows' PBL framework (theory emerges from lived problem) + +--- + +## Deliberate Design Decisions + +### No Authentication Backend (by design) +Auth is localStorage-only. This keeps the app 100% offline, requires zero database changes, and is appropriate for a single-user prototype. A real server-side auth layer is Phase 3. + +### No Python Sandbox (deferred to v3) +The current interaction model (reason in English → theory reveal → code example) is Phase 2. Running actual Python (Pyodide/WASM or server-side exec) is Phase 3. + +### Left Sidebar Always Visible +Research on educational platforms (Khan Academy, Codecademy, Brilliant) consistently shows that a persistent curriculum sidebar improves learner orientation. The sidebar shows progress at a glance and prevents the "where am I?" confusion of accordion menus. + +--- + +## Routing Structure + +``` +/ → Landing page (public) +/login → Login (redirect to /app if already logged in) +/signup → Signup (redirect to /app if already logged in) +/app → AppLayout (protected) + /app → AppHome dashboard + /app/chapter/:id → ChapterPage (4-phase learning flow) +``` + +--- + +## API Routes + +| Route | Description | +|---|---| +| `GET /api/health` | `{"ok":true,"product":"PyBe","version":"2.0.0"}` | +| `GET /api/casestudies` | All 6 UADE themes | +| `GET /api/casestudies/:id` | One theme | +| `GET /api/scenarios` | All 54 scenarios | +| `GET /api/scenarios?concept=X` | Filter by concept | +| `GET /api/scenarios?theme=X` | Filter by UADE theme | +| `POST /api/sessions` | Submit a reasoning session, get back score + feedback | +| `GET /api/analytics` | Aggregate stats (session count, concept counts, etc.) | + +--- + +## Roadmap (V0 → V3) + +| Phase | What | +|---|---| +| V0 (done) | Single-page prototype, 30 scenarios, plain CSS | +| V1 → v2.0 | Multi-page app, 6 UADE themes, 54+ scenarios, premium dark UI | +| V2 → v2.1 | Auth, left sidebar, sequential chapter flow, docs-style theory, GSAP | +| V3 (planned) | Python sandbox (Pyodide), audio input, leaderboard, real server-side auth | +| V4 (planned) | LLM trained on Python textbooks, rhizomatic path selector, Piaget-stage adaptive delivery | + +--- + +*PyBe v2.1 — IIT Ropar Summer Internship 2026 | Sukrit* diff --git a/README.md b/README.md index 5bc349d..8dc4e23 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,206 @@ -# PyBe MERN App +# PyBe v2.2 -PyBe is a scenario-driven Python learning prototype built from the supplied PRD and breakdown document. It has no login flow for now. +> **Python through discovery. Not syntax — stories.** -📚 View the project wiki: [WIKI.md](WIKI.md) +PyBe is a scenario-driven Python learning platform built on **Problem-Based Learning** and the **Universal Abstraction Discovery Engine (UADE)** concept. Instead of teaching Python constructs directly, PyBe presents real-world problems that grow until the current approach breaks — forcing the learner to *rediscover* the construct themselves. -## Features +📚 [context.md](context.md) · [product.md](product.md) · [WIKI.md](WIKI.md) -- Scenario browser with difficulty, concept, and search filters -- Interactive learning session: learner reasoning, abstraction mapping, conversational prompts, Python construct generation, prompt scoring, and reflection capture -- Dashboard with progress, prompt maturity, concept mastery, misconceptions, and recent sessions -- Roadmap view covering V0 through V3 from the source documents -- JSON-file backed API with seed data +--- + +## What's New in v2.2 + +### 1. 🧠 First-Principles Learning Engine +- **Friction Simulator (Before vs After)**: Side-by-side code comparison cards embedded in every chapter's Theory phase. Displays fragile manual code without the construct vs clean Python code, highlighting the exact pain point that led to the abstraction. +- **Interactive Mental Model Lab**: Live hands-on visualizers embedded in the Theory phase showing RAM memory slots (`0x7F8`), arithmetic operator pipelines, zero-indexed string character arrays, decision tree flowchart branching, loop iteration steppers, array append/pop counters, hash table lookup tables ($O(1)$ key mapping), unique set buckets, function machine inputs/outputs, binary/linear search scanners, `try/except` exception shields, array sort steppers, and RAM $\rightarrow$ Disk storage buffers. +- **Instant Micro-Sandbox / Interactive Try-It Widget**: Live browser-based Python code editor and executor embedded right below code examples. Features code resetting, live syntax validation, and an authentic dark terminal stdout console (`$ python main.py`). +- **Socratic Misconception Spotter**: Automated analysis of student plain-English reasoning during the Reasoning Summary phase (`SummaryPhase`). Detects 5 common beginner mental traps (0-indexing offsets, `=` assignment vs `==` comparison, string immutability in RAM, parallel list desynchronization, unhandled edge-case inputs) and provides targeted Socratic guiding prompts. + +### 2. 🎨 Dynamic Dashboard Theme Engine & Theme-Switched Curriculum +- **4 Theme Worlds**: Logged-in users can switch between **Default Theme** 🐍, **Potterheads** 🧙‍♂️, **Marvel** 🦾, and **Anime** ⚔️ directly from the dashboard. +- **Theme-Switched Scenarios & Case Studies**: Choosing a theme dynamically switches case study arcs and chapter scenarios across the dashboard, case study browser, scenario browser, and chapter learning flow. +- **Complete Chapter Coverage**: Every single one of the 13 curriculum chapters dynamically adapts its scenario questions, vibe, real-world connection, and code examples per active theme. + +### 3. 🌗 Tailored Light & Dark Modes +- Custom HSL color variables and dedicated Light & Dark mode styling for every theme: + - **Potterheads**: Hogwarts Dark Parchment (`#1E1610`) & Warm Light Parchment (`#FAF4E8`) with Dark Wizard Ink (`#291E16`). + - **Marvel**: Stark Cyber Dark (`#0B132B`) & Titanium Light (`#F1F5F9`) with Slate Ink (`#0F172A`). + - **Anime**: Tokyo Neon Dark (`#120D1D`) & Sakura Lavender Light (`#FAF5FF`) with Cyber Ink (`#1E1B4B`). + +### 4. 📊 93 Total Seeded Scenarios +- **54 Default/Classic Scenarios**: Real-world scenarios spanning Chai Stall, ISRO Space Mission Control, Instagram Filters, Food Delivery, AI Playlists, and Kota Merit Lists. +- **39 Theme-Specific Scenarios**: 13 Potterheads + 13 Marvel + 13 Anime scenarios covering all 13 chapters. + +## What came in v2.1 + +- **Login / Signup** — localStorage-based auth with per-user chapter progress tracking +- **Left curriculum sidebar** — full syllabus always visible, 13 chapters across 4 sections +- **Sequential chapter flow** — Intro → Questions → Reasoning Summary → Theory Reveal +- **Docs-style theory** — concept explained as documentation (prose + code block + callout) +- **GSAP animations** — staggered reveal on theory, slide transitions between phases +- **Educational score display** — level labels (🔥 Excellent / ⚡ Strong / 💡 Good / 📈 Getting there / 🌱 Beginning) with client-side fallback scoring + +## What came in v2.0 + +- Complete UI redesign — dark mode, glassmorphism, Space Grotesk + Inter typography +- 6 UADE Case Study Themes — Chai Stall, ISRO, Instagram, Food Delivery, AI Playlist, Kota +- 54+ scenarios — original 30 plus 24 theme-based scenarios +- `/api/casestudies` endpoint + theme filtering on `/api/scenarios` + +--- + +## Curriculum (13 Chapters) + +| Section | Chapters | +|---|---| +| 🌱 Getting Started | Variables · Operators & Math · Strings & Text | +| 📚 Basics | Making Decisions · Loops · Lists | +| ⚙️ Intermediate | Dictionaries · Sets · Functions · Search & Filter | +| ⚡ Advanced | Error Handling · Algorithms · Files & Data | + +--- ## Tech Stack -- JSON file storage -- Express + Node.js -- React + Vite -- Plain CSS, no auth +- **Frontend:** React 18 + Vite + React Router v6 + GSAP 3 +- **Styling:** Vanilla CSS (custom properties, dark mode, glassmorphism) +- **Fonts:** Space Grotesk (headings) + Inter (body) + JetBrains Mono (code) +- **Backend:** Node.js + Express +- **Data:** JSON file storage (`server/src/data/db.json`) — no MongoDB, no Docker +- **Auth:** localStorage-based (prototype — no backend auth) +- **Logic:** Deterministic rule-based learning engine (no external AI keys required) + +--- ## Prerequisites - Node.js 18+ -## Setup +--- -1. Install dependencies: +## Setup +### 1. Install dependencies ```bash npm run installAll ``` -2. Configure the server environment: - +### 2. Configure the server environment ```bash +# Windows +copy server\.env.example server\.env + +# macOS/Linux cp server/.env.example server/.env ``` +Default values work for local development. -The default values work for local development. - -3. Seed sample data: - +### 3. Seed sample data ```bash npm run seed ``` -4. Run the app: - +### 4. Run the app ```bash +# Start both servers together npm run dev + +# Or separately +npm run dev --prefix server # API on :5000 +npm run dev --prefix client # App on :5173 +``` + +- **App:** http://localhost:5173 → sign up, then start a chapter +- **API:** http://localhost:5000/api + +--- + +## API Endpoints + +| Method | Path | Description | +|---|---|---| +| GET | `/api/health` | `{"ok":true,"version":"2.0.0"}` | +| GET | `/api/scenarios` | All 69 scenarios (`?q=`, `?concept=`, `?theme=`, `?caseStudyId=`) | +| GET | `/api/scenarios/:id` | One scenario | +| POST | `/api/sessions` | Submit reasoning session → returns score + code + feedback | +| GET | `/api/sessions` | Recent sessions | +| GET | `/api/analytics` | Aggregate learner stats | +| GET | `/api/roadmap` | Learning roadmap phases | +| GET | `/api/casestudies` | All case study themes (`?theme=default`, `?theme=potterheads`, `?theme=marvel`, `?theme=anime`) | +| GET | `/api/casestudies/:id` | One theme | + +--- + +## Project Structure + +``` +pybe/ +├── client/ +│ └── src/ +│ ├── context/ +│ │ └── AuthContext.jsx # localStorage auth + progress tracking +│ ├── data/ +│ │ └── curriculum.js # 13 chapters with theory content + concept mappings +│ ├── layouts/ +│ │ └── AppLayout.jsx # Sidebar + content wrapper (protected) +│ ├── components/ +│ │ └── CurriculumSidebar.jsx # Collapsible syllabus with progress dots +│ ├── pages/ +│ │ ├── auth/ +│ │ │ ├── Login.jsx # GSAP entrance, glassmorphism card +│ │ │ └── Signup.jsx +│ │ ├── AppHome.jsx # Dashboard: progress bar, chapter list +│ │ ├── ChapterPage.jsx # 4-phase learning flow (Intro→Q→Summary→Theory) +│ │ └── Home.jsx # Public landing page +│ ├── styles/ +│ │ ├── index.css # Design system (CSS vars, dark mode, utilities) +│ │ └── animations.css # Keyframes +│ ├── App.jsx # Router with Protected/GuestOnly guards +│ └── main.jsx +│ +├── server/ +│ └── src/ +│ ├── data/ +│ │ ├── db.json # JSON data store (scenarios + sessions) +│ │ ├── store.js # CRUD helpers +│ │ └── roadmap.js +│ ├── routes/ # scenarios, sessions, analytics, roadmap, casestudies +│ ├── services/ +│ │ └── learningEngine.js # Keyword mapper, code generator, prompt evaluator +│ ├── seed.js # 54 scenarios (30 classic + 24 UADE themed) +│ └── index.js +│ +├── context.md # Pedagogical foundations +├── product.md # Full product document (features, decisions, roadmap) +└── README.md ``` -- Frontend: http://localhost:5173 -- API: http://localhost:5000/api +--- + +## Learning Flow (per chapter) + +``` +[Intro] → Hook, what you'll discover, scenario setup + ↓ "Let's go" +[Questions] → Scenarios one at a time (GSAP slide-in) + → User writes plain-English reasoning + ↓ Last question submitted +[Summary] → All answers shown with educational score level + → "Now discover why →" + ↓ +[Theory] → Docs-style: explanation prose → code block → callout → key takeaway + → "Mark as Complete ✓" → next chapter (always starts fresh at Intro) +``` + +--- ## Notes -The AI behavior in this prototype is deterministic and local. The abstraction mapper, prompt evaluator, and Python construct generator use rule-based logic so you can run everything without external AI keys. Later phases can replace those services with OpenAI, RAG, or TinyLLM components. +- The AI behavior is deterministic and local — no external API keys needed +- Learning data is in `server/src/data/db.json`; running `npm run seed` resets scenarios (not user progress) +- User progress is in `localStorage` and persists across browser sessions +- See `product.md` for full design decisions and `context.md` for the pedagogy + +--- -Learning data is stored in `server/src/data/db.json`. This keeps the prototype simple and fully local, without MongoDB, Docker, Atlas, or any external database. +*PyBe v2.1 — IIT Ropar Summer Internship 2026 | Sukrut* diff --git a/WIKI.md b/WIKI.md index 85846b2..01b6f1f 100644 --- a/WIKI.md +++ b/WIKI.md @@ -12,12 +12,24 @@ The project is designed to demonstrate a proof-of-concept for a Python learning - Provides a roadmap of learning goals from V0 through V3 ## Main Features -- Scenario browser with difficulty, concept, and search filters -- Interactive learning sessions with conversational prompts -- Reasoning support, abstraction mapping, prompt scoring, and reflection capture -- Dashboard with progress, prompt maturity, concept mastery, and misconceptions -- Roadmap visualization for staged product development -- Local JSON file storage with seedable sample data + +### 🧠 First-Principles Learning Engine +- **First-Principles Friction Simulator**: Side-by-side Before vs After code comparison in every chapter revealing the pain point behind each Python construct. +- **Interactive Mental Model Lab**: Live visualizer embedded in the Theory phase showing RAM memory slots (`0x7F8`), arithmetic pipelines, zero-indexed string cells, decision trees, loop steppers, hash tables, error shields, and sort steppers. +- **Instant Micro-Sandbox / Interactive Try-It Widget**: Embedded live browser-based Python executor with dark terminal stdout (`$ python main.py`), code resetting, and live syntax validation. +- **Socratic Misconception Spotter**: Automated analysis of student reasoning detecting 5 common beginner mental traps (0-indexing, `=` vs `==`, immutability, list desync, unhandled edge cases) with targeted Socratic prompts. + +### 🎨 Theme Systems & Content +- **Dynamic Dashboard Themes**: Interactive theme selector on dashboard (Default 🐍, Potterheads 🧙‍♂️, Marvel 🦾, Anime ⚔️). +- **Tailored Light & Dark Modes**: Bespoke color palettes for both Dark and Light modes across all themes (Hogwarts Parchment, Stark Titanium, Cyber Tokyo Lavender). +- **Theme-Switched Case Studies & Scenarios**: Dynamic filtering of case study arcs and 93 total scenarios matching the active theme across all 13 curriculum chapters. +- **Scenario Browser**: Filter scenarios by difficulty, concept, theme, and keyword search. + +### 📚 Learning Flow & Architecture +- **Sequential Chapter Learning**: 13 chapters across 4 curriculum sections (Getting Started, Basics, Intermediate, Advanced). +- **Interactive 4-Phase Learning Flow**: Intro → Questions → Reasoning Summary → Theory Reveal. +- **Educational Scoring System**: Reasoning quality evaluator with level labels (🔥 Excellent / ⚡ Strong / 💡 Good / 📈 Getting there / 🌱 Beginning). +- **Local JSON File Storage**: Seedable sample data (`server/src/data/db.json`) for 93 scenarios across all theme worlds. ## Technology Stack - Frontend: React + Vite diff --git a/client/index.html b/client/index.html index c880bd3..7e94d43 100644 --- a/client/index.html +++ b/client/index.html @@ -3,7 +3,12 @@ - PyBe + PyBe — Discover Python Through Real Stories + + + + +
diff --git a/client/package-lock.json b/client/package-lock.json index 15e5231..c92024d 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,22 +1,25 @@ { "name": "pybe-client", - "version": "1.0.0", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pybe-client", - "version": "1.0.0", + "version": "2.0.0", "dependencies": { "@vitejs/plugin-react": "^4.3.4", + "gsap": "^3.12.5", "lucide-react": "^0.468.0", "pybe-mern-app": "file:..", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-router-dom": "^6.28.0", "vite": "^6.0.7" } }, "..": { + "name": "pybe-mern-app", "version": "1.0.0", "dependencies": { "concurrently": "^9.1.2" @@ -697,6 +700,15 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@remix-run/router": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.3.tgz", + "integrity": "sha512-4An71tdz9X8+3sI4Qqqd2LWd9vS39J7sqd9EU4Scw7TJE/qB10Flv/UuqbPVgfQV9XoK8Np6jNquZitnZq5i+Q==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -1236,6 +1248,12 @@ "node": ">=6.9.0" } }, + "node_modules/gsap": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.15.0.tgz", + "integrity": "sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==", + "license": "Standard 'no charge' license: https://gsap.com/standard-license." + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1398,6 +1416,38 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.4.tgz", + "integrity": "sha512-SVUsDe+DybHM/WmYKIVYhZh1o5Dcuf16yM6WjG02Q9XVFMZIJyHYhwrr6bFBXZkVP6z69kNkMyBCujt8FaFLJA==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.4.tgz", + "integrity": "sha512-q4HvNl+mmDdkS0g+MqiBZNteQJCuimWoOyHMy4T/RQLAn9Z29+E91QXRaxOujeMl2HTzRSS0KFPd7lxX3PjV0Q==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3", + "react-router": "6.30.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/rollup": { "version": "4.62.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.0.tgz", diff --git a/client/package.json b/client/package.json index d45cb82..23eab93 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "pybe-client", - "version": "1.0.0", + "version": "2.0.0", "private": true, "scripts": { "dev": "vite", @@ -9,10 +9,15 @@ }, "dependencies": { "@vitejs/plugin-react": "^4.3.4", + "gsap": "^3.12.5", "lucide-react": "^0.468.0", "pybe-mern-app": "file:..", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-router-dom": "^6.28.0", "vite": "^6.0.7" + }, + "allowScripts": { + "esbuild@0.25.12": true } } diff --git a/client/src/App.jsx b/client/src/App.jsx new file mode 100644 index 0000000..042de74 --- /dev/null +++ b/client/src/App.jsx @@ -0,0 +1,106 @@ +import React, { Suspense, lazy } from 'react'; +import { BrowserRouter, Routes, Route, Navigate, useLocation } from 'react-router-dom'; +import { AuthProvider, useAuth } from './context/AuthContext.jsx'; + +// Auth pages (eager — small, always needed) +import Login from './pages/auth/Login.jsx'; +import Signup from './pages/auth/Signup.jsx'; + +// Lazy pages +const Home = lazy(() => import('./pages/Home.jsx')); +const AppLayout = lazy(() => import('./layouts/AppLayout.jsx')); +const AppHome = lazy(() => import('./pages/AppHome.jsx')); +const ChapterPage = lazy(() => import('./pages/ChapterPage.jsx')); + +function PageLoader() { + return ( +
+
+
+
+ Loading PyBe… +
+
+ +
+ ); +} + +// Protected route — redirects to /login if not authenticated +function Protected({ children }) { + const { user, loading } = useAuth(); + const location = useLocation(); + if (loading) return ; + if (!user) return ; + return children; +} + +// Guest-only route — redirects to /app if already logged in +function GuestOnly({ children }) { + const { user, loading } = useAuth(); + if (loading) return ; + if (user) return ; + return children; +} + +function AppRoutes() { + return ( + }> + + {/* Public landing */} + } /> + + {/* Auth */} + } /> + } /> + + {/* Protected app */} + } + > + } /> + } /> + + + {/* Catch-all */} + +
+
🐍
+

+ Page not found +

+ Go Home +
+
+ } /> + + + ); +} + +export default function App() { + return ( + + + + + + ); +} diff --git a/client/src/components/CaseStudyCard.jsx b/client/src/components/CaseStudyCard.jsx new file mode 100644 index 0000000..880cf69 --- /dev/null +++ b/client/src/components/CaseStudyCard.jsx @@ -0,0 +1,150 @@ +import React from 'react'; +import { useNavigate } from 'react-router-dom'; +import { ArrowRight, Layers } from 'lucide-react'; + +export default function CaseStudyCard({ caseStudy }) { + const navigate = useNavigate(); + + return ( +
+ {/* Top color bar */} +
+ +
+
{caseStudy.emoji}
+
+ {caseStudy.difficulty} + + {caseStudy.totalSteps} steps + +
+

{caseStudy.title}

+

With {caseStudy.character}

+

"{caseStudy.tagline}"

+
+ {caseStudy.pythonJourney.map((step, i) => ( + + {step} + {i < caseStudy.pythonJourney.length - 1 && ( + + )} + + ))} +
+
+ + + + +
+ ); +} diff --git a/client/src/components/CurriculumSidebar.jsx b/client/src/components/CurriculumSidebar.jsx new file mode 100644 index 0000000..20baa4e --- /dev/null +++ b/client/src/components/CurriculumSidebar.jsx @@ -0,0 +1,281 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { NavLink, useNavigate } from 'react-router-dom'; +import { gsap } from 'gsap'; +import { useAuth } from '../context/AuthContext.jsx'; +import { useTheme } from '../context/ThemeContext.jsx'; +import { CURRICULUM, ALL_CHAPTERS } from '../data/curriculum.js'; +import { + LogOut, ChevronDown, ChevronRight, + LayoutDashboard, Check, Circle, Sun, Moon, +} from 'lucide-react'; + +export default function CurriculumSidebar({ onNavigate }) { + const { user, logout, getChapterStatus, getProgress } = useAuth(); + const { theme, toggleTheme, isDark } = useTheme(); + const navigate = useNavigate(); + const sidebarRef = useRef(null); + const [openSections, setOpenSections] = useState(() => + Object.fromEntries(CURRICULUM.map(s => [s.id, true])) + ); + + const progress = getProgress(); + const completedCount = Object.values(progress).filter(p => p.status === 'completed').length; + const totalChapters = ALL_CHAPTERS.length; + const pct = Math.round((completedCount / totalChapters) * 100); + + useEffect(() => { + const items = sidebarRef.current?.querySelectorAll('.sb-chapter-link'); + if (!items?.length) return; + gsap.from(items, { x: -16, opacity: 0, duration: 0.35, stagger: 0.035, ease: 'power2.out', delay: 0.1 }); + }, []); + + function toggleSection(id) { + setOpenSections(prev => ({ ...prev, [id]: !prev[id] })); + } + + function handleLogout() { + logout(); + navigate('/login'); + } + + const statusIcon = (status) => { + if (status === 'completed') return ; + return ; + }; + + return ( + + ); +} diff --git a/client/src/components/HorcruxVault.jsx b/client/src/components/HorcruxVault.jsx new file mode 100644 index 0000000..d11f522 --- /dev/null +++ b/client/src/components/HorcruxVault.jsx @@ -0,0 +1,149 @@ +import React from 'react'; +import { Lock, CheckCircle2, Star } from 'lucide-react'; + +const HORCRUXES = [ + { id: 1, name: 'Variables & Types', icon: '📦', color: '#F59E0B', concept: 'variables', desc: 'Storing and naming — the atom of all programs.' }, + { id: 2, name: 'Control Flow', icon: '🔀', color: '#3B82F6', concept: 'conditionals', desc: 'Deciding and repeating — giving code a brain.' }, + { id: 3, name: 'Functions', icon: '🔧', color: '#10B981', concept: 'functions', desc: 'Packaging and reusing — write once, use everywhere.' }, + { id: 4, name: 'Data Structures', icon: '🗂️', color: '#8B5CF6', concept: 'lists', desc: 'Organizing and retrieving — data at scale.' }, + { id: 5, name: 'File & I/O', icon: '💾', color: '#EC4899', concept: 'file I/O', desc: 'Connecting to the world — persistence matters.' }, + { id: 6, name: 'Error Handling', icon: '🛡️', color: '#F97316', concept: 'error handling', desc: 'Expecting the unexpected — real code fails.' }, + { id: 7, name: 'Modules & Packages', icon: '🏛️', color: '#A8FF3E', concept: 'modules', desc: 'Building systems — from script to software.' }, +]; + +export default function HorcruxVault({ conceptCounts = {} }) { + const allConcepts = Object.keys(conceptCounts); + + const isUnlocked = (horcrux) => { + const count = conceptCounts[horcrux.concept] || 0; + return count >= 1; + }; + + const unlockedCount = HORCRUXES.filter(isUnlocked).length; + const progress = Math.round((unlockedCount / 7) * 100); + + return ( +
+
+
+
The 7 Horcruxes of Python
+

Each Horcrux is a pillar of Python mastery. Solve scenarios to unlock them all.

+
+
+ + + + {unlockedCount}/7 + +
+
+ +
+ {HORCRUXES.map((h) => { + const unlocked = isUnlocked(h); + return ( +
+ {unlocked &&
} +
{h.icon}
+
{h.name}
+
{h.desc}
+
+ {unlocked ? ( + + {conceptCounts[h.concept] || 0} sessions + + ) : ( + + Locked + + )} +
+
+ ); + })} +
+ + {unlockedCount === 7 && ( +
+ + You are a Python Wizard — all 7 Horcruxes found! +
+ )} + + +
+ ); +} diff --git a/client/src/components/LearningForm.jsx b/client/src/components/LearningForm.jsx new file mode 100644 index 0000000..5bd5aba --- /dev/null +++ b/client/src/components/LearningForm.jsx @@ -0,0 +1,149 @@ +import React from 'react'; +import { Send, Lightbulb, MessageSquare, Pencil } from 'lucide-react'; + +export default function LearningForm({ scenario, form, onChange, onSubmit, submitting }) { + return ( +
+ {/* Step 1 — Reasoning */} +
+
+
1
+
+
Your Reasoning
+
Think out loud. Don't worry about Python yet — reason in plain English.
+
+
+