diff --git a/frontend/src/app/lessons/page.tsx b/frontend/src/app/lessons/page.tsx new file mode 100644 index 00000000..9b5dc5cf --- /dev/null +++ b/frontend/src/app/lessons/page.tsx @@ -0,0 +1,99 @@ +'use client'; + +import Link from 'next/link'; +import { ArrowLeft } from 'lucide-react'; +import { motion } from 'framer-motion'; +import LessonWorkspace from '@/components/lesson/LessonWorkspace'; + +/** + * /lessons — demonstrates the interactive lesson workspace: lesson content on + * the left, a live Monaco code editor side-panel on the right. + * + * This page wires a sample Soroban lesson into {@link LessonWorkspace}; real + * curriculum data can be passed in the same shape from the course pages. + */ + +const SAMPLE_STARTER = `#![no_std] +use soroban_sdk::{contract, contractimpl, Env, Symbol, symbol_short}; + +#[contract] +pub struct Greeter; + +#[contractimpl] +impl Greeter { + // TODO: return a greeting Symbol from this function. + pub fn greet(env: Env) -> Symbol { + symbol_short!("hello") + } +}`; + +export default function LessonsPage() { + return ( +
+ {/* Background glows */} +
+
+ + {/* Navigation */} + + + {/* Main Content */} +
+ +

+ Write Your First Contract +

+

+ Follow the lesson and experiment in the live editor beside it. +

+
+ + + +

+ Soroban contracts are written in Rust. Every contract is a struct + annotated with #[contract], and its callable + methods live in an impl block marked + #[contractimpl]. +

+

+ In the editor on the right, the greet function + already returns a short symbol. Try editing the returned value, or add a new method + that takes a name and returns a personalised greeting. +

+

+ The editor provides Rust syntax highlighting and basic autocompletion. Use the + Reset button in the editor header to restore + the starter code at any time. +

+
+
+
+
+ ); +} diff --git a/frontend/src/components/lesson/LessonCodeEditor.tsx b/frontend/src/components/lesson/LessonCodeEditor.tsx new file mode 100644 index 00000000..76348c0f --- /dev/null +++ b/frontend/src/components/lesson/LessonCodeEditor.tsx @@ -0,0 +1,189 @@ +'use client'; + +import dynamic from 'next/dynamic'; +import type { OnMount } from '@monaco-editor/react'; +import React, { useCallback, useEffect, useState } from 'react'; +import { RotateCcw } from 'lucide-react'; +import { extendRustLanguage } from '@/lib/editor/SorobanLanguage'; +import { registerSorobanCompletion } from '@/lib/editor/SorobanCompletion'; + +/** + * LessonCodeEditor — a self-contained Monaco editor for the lesson side-panel. + * + * Design notes: + * - **Bundle size**: Monaco is heavy, so `@monaco-editor/react` is pulled in via + * `next/dynamic` with `ssr: false`. It is never part of the server bundle and + * only downloads on the client when a lesson with an editor is opened. + * - **Rust support**: syntax highlighting and basic autocomplete are wired up by + * reusing the shared `extendRustLanguage` / `registerSorobanCompletion` + * helpers, so the lesson editor stays consistent with the playground without + * duplicating the language definition. + * - **Decoupled**: unlike the playground editor, this component has no + * collaboration/compile coupling. It owns a single string of code, reports + * changes via `onChange`, and can reset back to the lesson's starter code. + * - **Resilient**: if Monaco fails to load, an accessible