diff --git a/.windsurf/plans/kids-interactive-elements.md b/.windsurf/plans/kids-interactive-elements.md new file mode 100644 index 00000000..04844415 --- /dev/null +++ b/.windsurf/plans/kids-interactive-elements.md @@ -0,0 +1,201 @@ +# New Interactive Elements for Kids Levels + +Add 5 new interactive components to enhance kids learning, inspired by key concepts from the prompting book. + +--- + +## Current State + +### Existing Components +| Component | Purpose | Used In | +|-----------|---------|---------| +| `PromptVsMistake` | Choose between good/bad prompts | All worlds | +| `MagicWords` | Fill-in-the-blank prompts | All worlds | +| `DragDropPrompt` | Arrange prompt pieces in order | World 2-5 | +| `Panel/StoryScene` | Story dialogue with Promi | All worlds | +| `LevelComplete` | Celebration with stars | All worlds | + +### Book Concepts Not Yet Covered for Kids +1. **Few-shot learning** - Teaching by example +2. **Iterative refinement** - Improving prompts step-by-step +3. **Prompt anatomy** - Understanding prompt parts (role, context, task, format) +4. **Common pitfalls** - Recognizing and avoiding mistakes +5. **Chain of thought** - Step-by-step reasoning + +--- + +## Proposed New Components + +### 1. `` - Interactive Prompt Tester +**Concept**: Kids build a prompt and see a simulated AI response (pre-defined). + +**Props**: +```tsx + +``` + +**UX**: +- Shows base prompt with "add detail" buttons +- Each addition shows immediate simulated response change +- Teaches iterative refinement concept + +**Book Reference**: Chapter 8 (Iterative Refinement) + +--- + +### 2. `` - Anatomy Highlighter +**Concept**: Interactive visualization of prompt components. + +**Props**: +```tsx + +``` + +**UX**: +- Colored highlights on prompt parts +- Tap a part to see explanation +- Legend shows what each color means + +**Book Reference**: Chapter 2 (Anatomy of a Prompt) + +--- + +### 3. `` - Few-Shot Learning Game +**Concept**: Match examples to teach AI patterns. + +**Props**: +```tsx + +``` + +**UX**: +- Shows pattern with examples +- Kids choose what comes next +- Teaches few-shot learning concept + +**Book Reference**: Chapter 7 (Few-Shot Learning) + +--- + +### 4. `` - Fix the Prompt +**Concept**: Identify and fix problems in broken prompts. + +**Props**: +```tsx + +``` + +**UX**: +- Shows "sick" prompt with symptoms +- Kids tap problems to apply fixes +- Prompt "heals" as problems are fixed +- Fun medical/doctor theme + +**Book Reference**: Chapter 15 (Common Pitfalls) + +--- + +### 5. `` - Chain of Thought Builder +**Concept**: Teach kids to ask AI to show its work. + +**Props**: +```tsx + +``` + +**UX**: +- Shows problem with wrong answer first +- Kids add "magic words" to unlock step-by-step +- Steps reveal one at a time +- Teaches chain of thought prompting + +**Book Reference**: Chapter 6 (Chain of Thought) + +--- + +## Implementation Priority + +| Priority | Component | Complexity | Impact | +|----------|-----------|------------|--------| +| 1 | `PromptParts` | Medium | High - visual learning | +| 2 | `ExampleMatcher` | Low | High - gamification | +| 3 | `PromptDoctor` | Medium | High - error recognition | +| 4 | `StepByStep` | Low | Medium - advanced concept | +| 5 | `PromptLab` | High | Medium - complex interactions | + +--- + +## Level Integration + +### Where to Add Components + +| World | Level | New Component | Concept | +|-------|-------|---------------|---------| +| 2 | 2-4 Detail Detective | `PromptParts` | See prompt anatomy | +| 3 | 3-2 Show Don't Tell | `ExampleMatcher` | Teach by example | +| 5 | 5-2 Fix It Up | `PromptDoctor` | Fix broken prompts | +| 5 | 5-1 Perfect Prompt | `StepByStep` | Complex reasoning | +| 5 | 5-3 Prompt Remix | `PromptLab` | Iterate and improve | + +--- + +## Estimated Work + +- **Component Development**: ~2-3 hours per component +- **Level Content Updates**: ~30 min per level +- **i18n**: Add translation keys for new component labels +- **Testing**: Visual review on mobile/desktop + +--- + +## Questions for User + +1. **Priority**: Should I implement all 5, or start with top 2-3? +2. **Theming**: Any specific visual style preferences (medical theme for PromptDoctor, etc.)? +3. **Complexity**: Is `PromptLab` too complex for MVP, or should it be simpler? diff --git a/mdx-components.tsx b/mdx-components.tsx index 187a8bf3..a7b9edee 100644 --- a/mdx-components.tsx +++ b/mdx-components.tsx @@ -1,7 +1,7 @@ import type { MDXComponents } from "mdx/types"; import type { ComponentPropsWithoutRef } from "react"; import { BeforeAfterEditor, BookPartsNav, BREAKFramework, Callout, ChainErrorDemo, ChainExample, ChainFlowDemo, Checklist, CodeEditor, Collapsible, Compare, ContentPipelineDemo, ContextPlayground, ContextWindowDemo, CostCalculatorDemo, CRISPEFramework, DiffView, EmbeddingsDemo, FallbackDemo, FewShotDemo, FillInTheBlank, IconCheck, IconClipboard, IconLightbulb, IconLock, IconSettings, IconStar, IconTarget, IconUser, IconX, InfoGrid, InteractiveChecklist, IterativeRefinementDemo, JailbreakDemo, JsonYamlDemo, LLMCapabilitiesDemo, NavButton, NavFooter, PrinciplesSummary, PromptAnalyzer, PromptBreakdown, PromptBuilder, PromptChallenge, PromptDebugger, Quiz, RTFFramework, SpecificitySpectrum, StructuredOutputDemo, SummarizationDemo, TemperatureDemo, TextToImageDemo, TextToVideoDemo, TokenizerDemo, TokenPredictionDemo, TryIt, ValidationDemo, VersionDiff } from "@/components/book/interactive"; -import { PromiCharacter, PromiWithMessage, Panel, StoryScene, PromptVsMistake, MagicWords, DragDropPrompt, LevelComplete } from "@/components/kids/elements"; +import { PromiCharacter, PromiWithMessage, Panel, StoryScene, PromptVsMistake, MagicWords, DragDropPrompt, LevelComplete, Section, PromptParts, ExampleMatcher, PromptDoctor, StepByStep, PromptLab, WordPredictor } from "@/components/kids/elements"; export function useMDXComponents(components: MDXComponents): MDXComponents { return { @@ -92,5 +92,12 @@ export function useMDXComponents(components: MDXComponents): MDXComponents { MagicWords, DragDropPrompt, LevelComplete, + Section, + PromptParts, + ExampleMatcher, + PromptDoctor, + StepByStep, + PromptLab, + WordPredictor, }; } diff --git a/messages/ar.json b/messages/ar.json index d11f66a6..5587e43c 100644 --- a/messages/ar.json +++ b/messages/ar.json @@ -1399,7 +1399,14 @@ "stars": { "title": "اجمع النجوم", "description": "اجمع النجوم وافتح مستويات جديدة" } }, "startButton": "ابدأ اللعب!", - "ageNote": "الأفضل للأطفال من 8-14 سنة الذين يعرفون القراءة والكتابة" + "ageNote": "الأفضل للأطفال من 8-14 سنة الذين يعرفون القراءة والكتابة", + "whatYouLearn": "ماذا ستتعلم", + "readyTitle": "مستعد للبدء؟", + "readyMessage": "لننطلق في مغامرة ونتعلم كيف نتحدث مع الذكاء الاصطناعي!" + }, + "navigation": { + "back": "رجوع", + "next": "التالي" }, "map": { "title": "خريطة العالم", "subtitle": "اختر مستوى وابدأ مغامرتك!", "worldLevels": "{count} مستويات", "levelNumber": "المستوى {number}", "locked": "أكمل المستوى السابق للفتح" }, "worlds": { "1": { "title": "قرية البداية" }, "2": { "title": "قلعة الوضوح" }, "3": { "title": "كهوف السياق" }, "4": { "title": "وادي الإبداع" }, "5": { "title": "جبل الإتقان" } }, diff --git a/messages/az.json b/messages/az.json index 0aa868e3..c618fd5b 100644 --- a/messages/az.json +++ b/messages/az.json @@ -1399,7 +1399,14 @@ "stars": { "title": "Ulduz Qazan", "description": "Ulduzlar topla və yeni səviyyələri aç" } }, "startButton": "Oynamağa Başla!", - "ageNote": "Oxumaq və yazmaq bilən 8-14 yaşlı uşaqlar üçün ən uyğun" + "ageNote": "Oxumaq və yazmaq bilən 8-14 yaşlı uşaqlar üçün ən uyğun", + "whatYouLearn": "Nə öyrənəcəksən", + "readyTitle": "Başlamağa hazırsan?", + "readyMessage": "Gəl macəraya çıxaq və AI ilə danışmağı öyrənək!" + }, + "navigation": { + "back": "Geri", + "next": "İrəli" }, "map": { "title": "Dünya Xəritəsi", "subtitle": "Bir səviyyə seç və macərana başla!", "worldLevels": "{count} səviyyə", "levelNumber": "Səviyyə {number}", "locked": "Açmaq üçün əvvəlki səviyyəni tamamla" }, "worlds": { "1": { "title": "Başlanğıc Kəndi" }, "2": { "title": "Aydınlıq Qalası" }, "3": { "title": "Kontekst Mağaraları" }, "4": { "title": "Yaradıcılıq Kanyonu" }, "5": { "title": "Ustad Dağı" } }, diff --git a/messages/de.json b/messages/de.json index 82a71a35..423dfc47 100644 --- a/messages/de.json +++ b/messages/de.json @@ -1399,7 +1399,14 @@ "stars": { "title": "Sterne sammeln", "description": "Sammle Sterne und schalte neue Level frei" } }, "startButton": "Jetzt spielen!", - "ageNote": "Am besten für Kinder von 8-14 Jahren, die lesen und schreiben können" + "ageNote": "Am besten für Kinder von 8-14 Jahren, die lesen und schreiben können", + "whatYouLearn": "Was du lernst", + "readyTitle": "Bereit zum Starten?", + "readyMessage": "Lass uns auf ein Abenteuer gehen und lernen, mit KI zu sprechen!" + }, + "navigation": { + "back": "Zurück", + "next": "Weiter" }, "map": { "title": "Weltkarte", "subtitle": "Wähle ein Level und starte dein Abenteuer!", "worldLevels": "{count} Level", "levelNumber": "Level {number}", "locked": "Schließe das vorherige Level ab zum Freischalten" }, "worlds": { "1": { "title": "Startdorf" }, "2": { "title": "Klarheitsschloss" }, "3": { "title": "Kontext-Höhlen" }, "4": { "title": "Kreativ-Canyon" }, "5": { "title": "Meisterberg" } }, diff --git a/messages/el.json b/messages/el.json index f5c44126..7b2a8d98 100644 --- a/messages/el.json +++ b/messages/el.json @@ -1399,7 +1399,14 @@ "stars": { "title": "Κέρδισε Αστέρια", "description": "Συλλέξτε αστέρια και ξεκλειδώστε νέα επίπεδα" } }, "startButton": "Ξεκίνα να Παίζεις!", - "ageNote": "Ιδανικό για παιδιά 8-14 ετών που ξέρουν να διαβάζουν και να γράφουν" + "ageNote": "Ιδανικό για παιδιά 8-14 ετών που ξέρουν να διαβάζουν και να γράφουν", + "whatYouLearn": "Τι θα μάθεις", + "readyTitle": "Έτοιμος να ξεκινήσεις;", + "readyMessage": "Πάμε σε μια περιπέτεια και μάθουμε να μιλάμε με την AI!" + }, + "navigation": { + "back": "Πίσω", + "next": "Επόμενο" }, "map": { "title": "Χάρτης Κόσμου", "subtitle": "Επέλεξε ένα επίπεδο και ξεκίνα την περιπέτειά σου!", "worldLevels": "{count} επίπεδα", "levelNumber": "Επίπεδο {number}", "locked": "Ολοκλήρωσε το προηγούμενο επίπεδο για ξεκλείδωμα" }, "worlds": { "1": { "title": "Χωριό Εκκίνησης" }, "2": { "title": "Κάστρο Σαφήνειας" }, "3": { "title": "Σπηλιές Πλαισίου" }, "4": { "title": "Φαράγγι Δημιουργικότητας" }, "5": { "title": "Βουνό Μαεστρίας" } }, diff --git a/messages/en.json b/messages/en.json index 0f895a20..b9d29eb3 100644 --- a/messages/en.json +++ b/messages/en.json @@ -1417,7 +1417,14 @@ } }, "startButton": "Start Playing!", - "ageNote": "Best for kids ages 8-14 who can read and write" + "ageNote": "Best for kids ages 8-14 who can read and write", + "whatYouLearn": "What You'll Learn", + "readyTitle": "Ready to Start?", + "readyMessage": "Let's go on an adventure and learn how to talk to AI!" + }, + "navigation": { + "back": "Back", + "next": "Next" }, "map": { "title": "World Map", @@ -1455,6 +1462,70 @@ "1_3_being_clear": { "title": "Being Clear", "description": "Learn why clear instructions work better" + }, + "2_1_missing_details": { + "title": "The Missing Details", + "description": "Discover why details matter - vague vs specific prompts" + }, + "2_2_who_and_what": { + "title": "Who & What", + "description": "Add characters and objects to make prompts come alive" + }, + "2_3_when_and_where": { + "title": "When & Where", + "description": "Learn to add time and place to your prompts" + }, + "2_4_detail_detective": { + "title": "The Detail Detective", + "description": "Become a master of adding all the right details" + }, + "3_1_setting_the_scene": { + "title": "Setting the Scene", + "description": "Learn why background info helps AI understand you" + }, + "3_2_show_dont_tell": { + "title": "Show, Don't Tell", + "description": "Use examples to show AI exactly what you want" + }, + "3_3_format_finder": { + "title": "The Format Finder", + "description": "Ask for lists, stories, poems, and more!" + }, + "3_4_context_champion": { + "title": "Context Champion", + "description": "Combine all context techniques like a pro" + }, + "4_1_pretend_time": { + "title": "Pretend Time!", + "description": "Learn role-play prompts - 'Act as...'" + }, + "4_2_story_starters": { + "title": "Story Starters", + "description": "Create amazing stories with AI as your co-author" + }, + "4_3_character_creator": { + "title": "Character Creator", + "description": "Give AI a personality and watch it come alive" + }, + "4_4_world_builder": { + "title": "World Builder", + "description": "Create imaginative worlds and scenarios" + }, + "5_1_perfect_prompt": { + "title": "The Perfect Prompt", + "description": "Combine clarity, details, and context together" + }, + "5_2_fix_it_up": { + "title": "Fix It Up!", + "description": "Find and improve weak prompts" + }, + "5_3_prompt_remix": { + "title": "Prompt Remix", + "description": "Rewrite prompts for different outcomes" + }, + "5_4_graduation_day": { + "title": "Graduation Day", + "description": "The final challenge - become a Prompt Master!" } }, "level": { @@ -1470,6 +1541,105 @@ "nextLevel": "Next Level", "backToMap": "Back to Map", "allDone": "Back to Map" + }, + "quiz": { + "goodLabel": "Great prompt!", + "badLabel": "Not the best", + "correct": "You got it!", + "incorrect": "Good try!", + "tryAgain": "Try Again" + }, + "magicWords": { + "title": "Drag the magic words! ✨", + "dragOrTap": "🎯 Drag or tap words:", + "check": "Check!", + "retry": "Retry", + "correct": "correct", + "tryAgain": "Try again!" + }, + "dragDrop": { + "title": "Build the prompt!", + "instruction": "Use arrows to move pieces, or tap two pieces to swap!", + "result": "Result", + "check": "Check!", + "retry": "Retry", + "success": "Perfect! You built a great prompt!", + "almost": "Almost! Keep reordering.", + "tapToSwap": "Tap another piece to swap positions!" + }, + "promptParts": { + "title": "Sort the Prompt Parts!", + "instruction": "Tap each piece, then pick which type it is!", + "score": "Score", + "pickCategory": "What type is this?", + "success": "You sorted all the parts correctly!", + "retry": "Try Again", + "types": { + "role": "Role", + "task": "Task", + "context": "Context", + "constraint": "Constraint" + } + }, + "exampleMatcher": { + "title": "Pattern Matcher", + "instruction": "Look at the pattern and pick what comes next!", + "pattern": "The Pattern:", + "check": "Check!", + "retry": "Try Again", + "correct": "You got it! 🎉", + "tryAgain": "Not quite - look at the pattern again!" + }, + "promptDoctor": { + "title": "Prompt Doctor", + "health": "Prompt Health", + "sick": "Sick Prompt", + "healthy": "Healthy Prompt!", + "diagnose": "Click a problem to fix it:", + "success": "The prompt is all better now!", + "retry": "Start Over" + }, + "stepByStep": { + "title": "Think Step by Step", + "problem": "The Problem:", + "withoutMagic": "Without magic words:", + "addMagicWords": "Add the Magic Words!", + "magicWordsActive": "Magic words added!", + "nextStep": "Reveal Next Step", + "withMagic": "With step-by-step thinking:", + "retry": "Try Again" + }, + "promptLab": { + "title": "Prompt Lab", + "progress": "Improvements", + "yourPrompt": "Your Prompt:", + "aiSays": "AI Response:", + "addDetails": "Add improvements:", + "success": "Your prompt is now super specific!", + "retry": "Start Over" + }, + "wordPredictor": { + "title": "How AI Thinks", + "instruction": "AI guesses the most likely next word. Can you think like AI?", + "aiThinks": "AI is reading:", + "thinkingDefault": "Hmm, what word would make the most sense here?", + "check": "Check My Guess!", + "correct": "You think like AI!", + "tryAgain": "Not quite! AI picks the most likely word.", + "retry": "Try Again" + }, + "settings": { + "title": "Settings", + "language": "Language", + "progress": "Your Progress", + "stars": "Stars", + "completed": "Completed", + "resetTitle": "Reset Progress", + "resetButton": "Reset All Progress", + "resetWarning": "This will delete all your stars and progress. Are you sure?", + "resetConfirm": "Yes, Reset Everything", + "resetComplete": "Progress reset! Reloading...", + "cancel": "Cancel" } } } diff --git a/messages/es.json b/messages/es.json index 2a086573..ff2f9b80 100644 --- a/messages/es.json +++ b/messages/es.json @@ -1399,7 +1399,14 @@ "stars": { "title": "Gana Estrellas", "description": "Colecciona estrellas y desbloquea nuevos niveles" } }, "startButton": "¡Empezar a Jugar!", - "ageNote": "Ideal para niños de 8-14 años que saben leer y escribir" + "ageNote": "Ideal para niños de 8-14 años que saben leer y escribir", + "whatYouLearn": "Lo Que Aprenderás", + "readyTitle": "¿Listo para Empezar?", + "readyMessage": "¡Vamos a una aventura y aprendamos a hablar con la IA!" + }, + "navigation": { + "back": "Atrás", + "next": "Siguiente" }, "map": { "title": "Mapa del Mundo", "subtitle": "¡Elige un nivel y comienza tu aventura!", "worldLevels": "{count} niveles", "levelNumber": "Nivel {number}", "locked": "Completa el nivel anterior para desbloquear" }, "worlds": { "1": { "title": "Aldea Inicial" }, "2": { "title": "Castillo de Claridad" }, "3": { "title": "Cuevas de Contexto" }, "4": { "title": "Cañón Creativo" }, "5": { "title": "Montaña Maestra" } }, diff --git a/messages/fa.json b/messages/fa.json index c68153f5..07b99cd0 100644 --- a/messages/fa.json +++ b/messages/fa.json @@ -1399,7 +1399,14 @@ "stars": { "title": "ستاره جمع کن", "description": "ستاره جمع کن و مراحل جدید را باز کن" } }, "startButton": "شروع بازی!", - "ageNote": "مناسب برای کودکان ۸-۱۴ ساله که می‌توانند بخوانند و بنویسند" + "ageNote": "مناسب برای کودکان ۸-۱۴ ساله که می‌توانند بخوانند و بنویسند", + "whatYouLearn": "چه چیزی یاد می‌گیری", + "readyTitle": "آماده شروع هستی؟", + "readyMessage": "بیا به ماجراجویی برویم و یاد بگیریم چطور با هوش مصنوعی صحبت کنیم!" + }, + "navigation": { + "back": "برگشت", + "next": "بعدی" }, "map": { "title": "نقشه جهان", "subtitle": "یک مرحله انتخاب کن و ماجراجویی‌ات را شروع کن!", "worldLevels": "{count} مرحله", "levelNumber": "مرحله {number}", "locked": "برای باز کردن، مرحله قبلی را کامل کن" }, "worlds": { "1": { "title": "دهکده شروع" }, "2": { "title": "قلعه شفافیت" }, "3": { "title": "غارهای زمینه" }, "4": { "title": "دره خلاقیت" }, "5": { "title": "کوه استادی" } }, diff --git a/messages/fr.json b/messages/fr.json index 636da940..7cb44efc 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -1399,7 +1399,14 @@ "stars": { "title": "Gagne des Étoiles", "description": "Collectionne des étoiles et débloque de nouveaux niveaux" } }, "startButton": "Commencer à Jouer !", - "ageNote": "Idéal pour les enfants de 8-14 ans qui savent lire et écrire" + "ageNote": "Idéal pour les enfants de 8-14 ans qui savent lire et écrire", + "whatYouLearn": "Ce que tu vas apprendre", + "readyTitle": "Prêt à commencer ?", + "readyMessage": "Partons à l'aventure et apprenons à parler avec l'IA !" + }, + "navigation": { + "back": "Retour", + "next": "Suivant" }, "map": { "title": "Carte du Monde", "subtitle": "Choisis un niveau et commence ton aventure !", "worldLevels": "{count} niveaux", "levelNumber": "Niveau {number}", "locked": "Termine le niveau précédent pour débloquer" }, "worlds": { "1": { "title": "Village de Départ" }, "2": { "title": "Château de la Clarté" }, "3": { "title": "Grottes du Contexte" }, "4": { "title": "Canyon Créatif" }, "5": { "title": "Montagne du Maître" } }, diff --git a/messages/he.json b/messages/he.json index cf77476f..8e99970b 100644 --- a/messages/he.json +++ b/messages/he.json @@ -1399,7 +1399,14 @@ "stars": { "title": "אסוף כוכבים", "description": "אסוף כוכבים ופתח שלבים חדשים" } }, "startButton": "התחל לשחק!", - "ageNote": "מתאים לילדים בגילאי 8-14 שיודעים לקרוא ולכתוב" + "ageNote": "מתאים לילדים בגילאי 8-14 שיודעים לקרוא ולכתוב", + "whatYouLearn": "מה תלמד", + "readyTitle": "מוכן להתחיל?", + "readyMessage": "בוא נצא להרפתקה ונלמד איך לדבר עם AI!" + }, + "navigation": { + "back": "אחורה", + "next": "הבא" }, "map": { "title": "מפת העולם", "subtitle": "בחר שלב והתחל את ההרפתקה שלך!", "worldLevels": "{count} שלבים", "levelNumber": "שלב {number}", "locked": "השלם את השלב הקודם לפתיחה" }, "worlds": { "1": { "title": "כפר ההתחלה" }, "2": { "title": "טירת הבהירות" }, "3": { "title": "מערות ההקשר" }, "4": { "title": "קניון היצירתיות" }, "5": { "title": "הר המומחיות" } }, diff --git a/messages/it.json b/messages/it.json index 164cd2b5..ca11af61 100644 --- a/messages/it.json +++ b/messages/it.json @@ -1399,7 +1399,14 @@ "stars": { "title": "Guadagna Stelle", "description": "Raccogli stelle e sblocca nuovi livelli" } }, "startButton": "Inizia a Giocare!", - "ageNote": "Ideale per bambini di 8-14 anni che sanno leggere e scrivere" + "ageNote": "Ideale per bambini di 8-14 anni che sanno leggere e scrivere", + "whatYouLearn": "Cosa imparerai", + "readyTitle": "Pronto per iniziare?", + "readyMessage": "Andiamo all'avventura e impariamo a parlare con l'IA!" + }, + "navigation": { + "back": "Indietro", + "next": "Avanti" }, "map": { "title": "Mappa del Mondo", "subtitle": "Scegli un livello e inizia la tua avventura!", "worldLevels": "{count} livelli", "levelNumber": "Livello {number}", "locked": "Completa il livello precedente per sbloccare" }, "worlds": { "1": { "title": "Villaggio Iniziale" }, "2": { "title": "Castello della Chiarezza" }, "3": { "title": "Caverne del Contesto" }, "4": { "title": "Canyon Creativo" }, "5": { "title": "Montagna del Maestro" } }, diff --git a/messages/ja.json b/messages/ja.json index a4010951..f50e81e0 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -1399,7 +1399,14 @@ "stars": { "title": "スターを集めよう", "description": "スターを集めて新しいレベルをアンロック" } }, "startButton": "遊び始めよう!", - "ageNote": "読み書きができる8〜14歳のお子様に最適" + "ageNote": "読み書きができる8〜14歳のお子様に最適", + "whatYouLearn": "学べること", + "readyTitle": "始める準備はできた?", + "readyMessage": "冒険に出かけて、AIと話す方法を学ぼう!" + }, + "navigation": { + "back": "戻る", + "next": "次へ" }, "map": { "title": "ワールドマップ", "subtitle": "レベルを選んで冒険を始めよう!", "worldLevels": "{count}レベル", "levelNumber": "レベル{number}", "locked": "前のレベルをクリアしてアンロック" }, "worlds": { "1": { "title": "はじまりの村" }, "2": { "title": "明確城" }, "3": { "title": "コンテキスト洞窟" }, "4": { "title": "クリエイティブ渓谷" }, "5": { "title": "マスター山" } }, diff --git a/messages/ko.json b/messages/ko.json index 4bc94c2e..a27cc30b 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -1399,7 +1399,14 @@ "stars": { "title": "별 모으기", "description": "별을 모아 새로운 레벨을 열어요" } }, "startButton": "게임 시작!", - "ageNote": "읽고 쓸 수 있는 8-14세 어린이에게 적합해요" + "ageNote": "읽고 쓸 수 있는 8-14세 어린이에게 적합해요", + "whatYouLearn": "배울 내용", + "readyTitle": "시작할 준비됐어?", + "readyMessage": "모험을 떠나 AI와 대화하는 법을 배워보자!" + }, + "navigation": { + "back": "뒤로", + "next": "다음" }, "map": { "title": "세계 지도", "subtitle": "레벨을 선택하고 모험을 시작하세요!", "worldLevels": "{count}개 레벨", "levelNumber": "레벨 {number}", "locked": "이전 레벨을 완료하면 열립니다" }, "worlds": { "1": { "title": "시작 마을" }, "2": { "title": "명확성의 성" }, "3": { "title": "맥락 동굴" }, "4": { "title": "창의력 협곡" }, "5": { "title": "마스터 산" } }, diff --git a/messages/pt.json b/messages/pt.json index 2fbccfc4..73523c50 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -1399,7 +1399,14 @@ "stars": { "title": "Ganhe Estrelas", "description": "Colete estrelas e desbloqueie novos níveis" } }, "startButton": "Começar a Jogar!", - "ageNote": "Ideal para crianças de 8-14 anos que sabem ler e escrever" + "ageNote": "Ideal para crianças de 8-14 anos que sabem ler e escrever", + "whatYouLearn": "O que você vai aprender", + "readyTitle": "Pronto para começar?", + "readyMessage": "Vamos em uma aventura e aprender a falar com a IA!" + }, + "navigation": { + "back": "Voltar", + "next": "Próximo" }, "map": { "title": "Mapa do Mundo", "subtitle": "Escolha um nível e comece sua aventura!", "worldLevels": "{count} níveis", "levelNumber": "Nível {number}", "locked": "Complete o nível anterior para desbloquear" }, "worlds": { "1": { "title": "Vila Inicial" }, "2": { "title": "Castelo da Clareza" }, "3": { "title": "Cavernas de Contexto" }, "4": { "title": "Cânion Criativo" }, "5": { "title": "Montanha Mestre" } }, diff --git a/messages/ru.json b/messages/ru.json index bf49c78f..c854c5b4 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -1399,7 +1399,14 @@ "stars": { "title": "Собирай звёзды", "description": "Собирай звёзды и открывай новые уровни" } }, "startButton": "Начать играть!", - "ageNote": "Лучше всего подходит для детей 8-14 лет, умеющих читать и писать" + "ageNote": "Лучше всего подходит для детей 8-14 лет, умеющих читать и писать", + "whatYouLearn": "Что ты узнаешь", + "readyTitle": "Готов начать?", + "readyMessage": "Отправимся в приключение и научимся разговаривать с ИИ!" + }, + "navigation": { + "back": "Назад", + "next": "Далее" }, "map": { "title": "Карта мира", "subtitle": "Выбери уровень и начни своё приключение!", "worldLevels": "{count} уровней", "levelNumber": "Уровень {number}", "locked": "Пройди предыдущий уровень для разблокировки" }, "worlds": { "1": { "title": "Стартовая деревня" }, "2": { "title": "Замок ясности" }, "3": { "title": "Пещеры контекста" }, "4": { "title": "Каньон творчества" }, "5": { "title": "Гора мастерства" } }, diff --git a/messages/tr.json b/messages/tr.json index 1894dc2e..bb920540 100644 --- a/messages/tr.json +++ b/messages/tr.json @@ -1417,7 +1417,14 @@ } }, "startButton": "Oynamaya Başla!", - "ageNote": "Okuma yazma bilen 8-14 yaş çocuklar için en uygun" + "ageNote": "Okuma yazma bilen 8-14 yaş çocuklar için en uygun", + "whatYouLearn": "Ne Öğreneceksin", + "readyTitle": "Başlamaya Hazır mısın?", + "readyMessage": "Haydi bir maceraya çıkalım ve yapay zeka ile nasıl konuşulacağını öğrenelim!" + }, + "navigation": { + "back": "Geri", + "next": "İleri" }, "map": { "title": "Dünya Haritası", @@ -1436,7 +1443,23 @@ "levels": { "1_1_meet_promi": { "title": "Promi ile Tanış!", "description": "Robot arkadaşınla tanış ve yapay zekanın ne olduğunu öğren" }, "1_2_first_words": { "title": "Promi'in İlk Sözleri", "description": "İlk promptunu yazarak Promi'in anlamasına yardım et" }, - "1_3_being_clear": { "title": "Net Olmak", "description": "Net talimatların neden daha iyi çalıştığını öğren" } + "1_3_being_clear": { "title": "Net Olmak", "description": "Net talimatların neden daha iyi çalıştığını öğren" }, + "2_1_missing_details": { "title": "Eksik Detaylar", "description": "Detayların neden önemli olduğunu keşfet" }, + "2_2_who_and_what": { "title": "Kim ve Ne", "description": "Promptlarına karakter ve nesne ekle" }, + "2_3_when_and_where": { "title": "Ne Zaman ve Nerede", "description": "Promptlarına zaman ve yer eklemeyi öğren" }, + "2_4_detail_detective": { "title": "Detay Dedektifi", "description": "Doğru detayları ekleme ustası ol" }, + "3_1_setting_the_scene": { "title": "Sahneyi Hazırlamak", "description": "Arka plan bilgisinin yapay zekaya nasıl yardımcı olduğunu öğren" }, + "3_2_show_dont_tell": { "title": "Göster, Anlatma", "description": "Örnekler kullanarak tam olarak ne istediğini göster" }, + "3_3_format_finder": { "title": "Format Bulucu", "description": "Liste, hikaye, şiir ve daha fazlasını iste!" }, + "3_4_context_champion": { "title": "Bağlam Şampiyonu", "description": "Tüm bağlam tekniklerini bir profesyonel gibi birleştir" }, + "4_1_pretend_time": { "title": "Hayal Zamanı!", "description": "Rol yapma promptlarını öğren" }, + "4_2_story_starters": { "title": "Hikaye Başlatıcılar", "description": "Yapay zeka ile harika hikayeler oluştur" }, + "4_3_character_creator": { "title": "Karakter Yaratıcı", "description": "Yapay zekaya kişilik ver" }, + "4_4_world_builder": { "title": "Dünya Oluşturucu", "description": "Hayal gücüyle dolu dünyalar yarat" }, + "5_1_perfect_prompt": { "title": "Mükemmel Prompt", "description": "Netlik, detay ve bağlamı birleştir" }, + "5_2_fix_it_up": { "title": "Düzelt!", "description": "Zayıf promptları bul ve geliştir" }, + "5_3_prompt_remix": { "title": "Prompt Remix", "description": "Farklı sonuçlar için promptları yeniden yaz" }, + "5_4_graduation_day": { "title": "Mezuniyet Günü", "description": "Son mücadele - Prompt Ustası ol!" } }, "level": { "backToMap": "Haritaya Dön", @@ -1451,6 +1474,105 @@ "nextLevel": "Sonraki Seviye", "backToMap": "Haritaya Dön", "allDone": "Haritaya Dön" + }, + "quiz": { + "goodLabel": "Harika prompt!", + "badLabel": "Pek iyi değil", + "correct": "Doğru bildin!", + "incorrect": "İyi deneme!", + "tryAgain": "Tekrar Dene" + }, + "magicWords": { + "title": "Sihirli kelimeleri sürükle! ✨", + "dragOrTap": "🎯 Kelimeleri sürükle veya tıkla:", + "check": "Kontrol Et!", + "retry": "Tekrar Dene", + "correct": "doğru", + "tryAgain": "Tekrar dene!" + }, + "dragDrop": { + "title": "Promptu oluştur!", + "instruction": "Okları kullanarak taşı veya iki parçaya tıklayarak yer değiştir!", + "result": "Sonuç", + "check": "Kontrol Et!", + "retry": "Tekrar Dene", + "success": "Mükemmel! Harika bir prompt oluşturdun!", + "almost": "Neredeyse! Sıralamaya devam et.", + "tapToSwap": "Yer değiştirmek için başka bir parçaya tıkla!" + }, + "promptParts": { + "title": "Prompt Parçalarını Sırala!", + "instruction": "Her parçaya tıkla, sonra türünü seç!", + "score": "Puan", + "pickCategory": "Bu ne türü?", + "success": "Tüm parçaları doğru sıraladın!", + "retry": "Tekrar Dene", + "types": { + "role": "Rol", + "task": "Görev", + "context": "Bağlam", + "constraint": "Kısıtlama" + } + }, + "exampleMatcher": { + "title": "Desen Eşleştirici", + "instruction": "Desene bak ve sıradaki ne olmalı seç!", + "pattern": "Desen:", + "check": "Kontrol Et!", + "retry": "Tekrar Dene", + "correct": "Doğru bildin! 🎉", + "tryAgain": "Tam değil - desene tekrar bak!" + }, + "promptDoctor": { + "title": "Prompt Doktoru", + "health": "Prompt Sağlığı", + "sick": "Hasta Prompt", + "healthy": "Sağlıklı Prompt!", + "diagnose": "Düzeltmek için bir soruna tıkla:", + "success": "Prompt artık tamamen iyileşti!", + "retry": "Baştan Başla" + }, + "stepByStep": { + "title": "Adım Adım Düşün", + "problem": "Problem:", + "withoutMagic": "Sihirli kelimeler olmadan:", + "addMagicWords": "Sihirli Kelimeleri Ekle!", + "magicWordsActive": "Sihirli kelimeler eklendi!", + "nextStep": "Sonraki Adımı Göster", + "withMagic": "Adım adım düşünme ile:", + "retry": "Tekrar Dene" + }, + "promptLab": { + "title": "Prompt Laboratuvarı", + "progress": "İyileştirmeler", + "yourPrompt": "Promptun:", + "aiSays": "Yapay Zeka Yanıtı:", + "addDetails": "İyileştirme ekle:", + "success": "Promptun artık süper detaylı!", + "retry": "Baştan Başla" + }, + "wordPredictor": { + "title": "Yapay Zeka Nasıl Düşünür", + "instruction": "Yapay zeka en mantıklı kelimeyi tahmin eder. Sen de yapay zeka gibi düşünebilir misin?", + "aiThinks": "Yapay zeka okuyor:", + "thinkingDefault": "Hmm, buraya hangi kelime en çok uyar?", + "check": "Tahminimi Kontrol Et!", + "correct": "Yapay zeka gibi düşünüyorsun!", + "tryAgain": "Tam değil! Yapay zeka en olası kelimeyi seçer.", + "retry": "Tekrar Dene" + }, + "settings": { + "title": "Ayarlar", + "language": "Dil", + "progress": "İlerlemeniz", + "stars": "Yıldız", + "completed": "Tamamlanan", + "resetTitle": "İlerlemeyi Sıfırla", + "resetButton": "Tüm İlerlemeyi Sıfırla", + "resetWarning": "Bu tüm yıldızlarını ve ilerlemenizi silecek. Emin misiniz?", + "resetConfirm": "Evet, Her Şeyi Sıfırla", + "resetComplete": "İlerleme sıfırlandı! Yeniden yükleniyor...", + "cancel": "İptal" } } } diff --git a/messages/zh.json b/messages/zh.json index 91d6d12c..b76d3108 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -1399,7 +1399,14 @@ "stars": { "title": "赚取星星", "description": "收集星星,解锁新关卡" } }, "startButton": "开始游戏!", - "ageNote": "适合8-14岁会读写的儿童" + "ageNote": "适合8-14岁会读写的儿童", + "whatYouLearn": "你将学到什么", + "readyTitle": "准备好开始了吗?", + "readyMessage": "让我们踏上冒险,学习如何与AI对话!" + }, + "navigation": { + "back": "返回", + "next": "下一步" }, "map": { "title": "世界地图", "subtitle": "选择一个关卡,开始你的冒险!", "worldLevels": "{count}个关卡", "levelNumber": "关卡{number}", "locked": "完成上一关以解锁" }, "worlds": { "1": { "title": "新手村" }, "2": { "title": "清晰城堡" }, "3": { "title": "上下文洞穴" }, "4": { "title": "创意峡谷" }, "5": { "title": "大师山" } }, diff --git a/public/sounds/README.md b/public/sounds/README.md new file mode 100644 index 00000000..5102248b --- /dev/null +++ b/public/sounds/README.md @@ -0,0 +1,16 @@ +# Kids Game Background Music + +Add an 8-bit dubstep/chiptune music file here named `8bit-game-music.mp3`. + +## Recommended Sources (Royalty-Free) + +- [OpenGameArt.org](https://opengameart.org/) - Free game assets including music +- [FreeMusicArchive.org](https://freemusicarchive.org/) - CC-licensed music +- [Incompetech.com](https://incompetech.com/) - Royalty-free music by Kevin MacLeod + +## File Requirements + +- **Filename:** `8bit-game-music.mp3` +- **Format:** MP3 +- **Style:** 8-bit / Chiptune / Retro game music +- **Loop-friendly:** Ideally seamless loop for background music diff --git a/src/app/globals.css b/src/app/globals.css index d07fe38f..edba4de0 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -452,3 +452,260 @@ margin: 1rem 0; } +/* Kids Map Animations */ +@keyframes bounce-slow { + 0%, 100% { + transform: translateY(0); + } + 50% { + transform: translateY(-8px); + } +} + +@keyframes draw-path { + from { + stroke-dashoffset: 200; + } + to { + stroke-dashoffset: 0; + } +} + +@keyframes float { + 0%, 100% { + transform: translateY(0) rotate(0deg); + } + 25% { + transform: translateY(-5px) rotate(2deg); + } + 75% { + transform: translateY(3px) rotate(-2deg); + } +} + +.animate-bounce-slow { + animation: bounce-slow 3s ease-in-out infinite; +} + +.animate-draw-path { + animation: draw-path 2s ease-out forwards; +} + +.animate-float { + animation: float 4s ease-in-out infinite; +} + +/* Cloud animations for kids background */ +@keyframes cloud-drift { + 0% { + transform: translateX(-100%); + } + 100% { + transform: translateX(100vw); + } +} + +.animate-cloud-slow { + animation: cloud-drift 45s linear infinite; +} + +.animate-cloud-medium { + animation: cloud-drift 30s linear infinite; +} + +.animate-cloud-fast { + animation: cloud-drift 20s linear infinite; +} + +.animation-delay-500 { + animation-delay: 500ms; +} + +.animation-delay-1000 { + animation-delay: 1000ms; +} + +.animation-delay-1500 { + animation-delay: 1500ms; +} + +/* Pixel Art Styles for Kids Game */ +.pixel-font { + font-family: 'Courier New', Courier, monospace; + font-weight: bold; + letter-spacing: 0.5px; +} + +.pixel-border { + clip-path: polygon( + 0 4px, 4px 4px, 4px 0, + calc(100% - 4px) 0, calc(100% - 4px) 4px, 100% 4px, + 100% calc(100% - 4px), calc(100% - 4px) calc(100% - 4px), calc(100% - 4px) 100%, + 4px 100%, 4px calc(100% - 4px), 0 calc(100% - 4px) + ); +} + +.pixel-border-sm { + clip-path: polygon( + 0 2px, 2px 2px, 2px 0, + calc(100% - 2px) 0, calc(100% - 2px) 2px, 100% 2px, + 100% calc(100% - 2px), calc(100% - 2px) calc(100% - 2px), calc(100% - 2px) 100%, + 2px 100%, 2px calc(100% - 2px), 0 calc(100% - 2px) + ); +} + +.pixel-btn { + position: relative; + border: none; + background: linear-gradient(180deg, #4A90D9 0%, #357ABD 100%); + color: white !important; + text-decoration: none !important; + color: white; + font-weight: bold; + padding: 8px 16px; + clip-path: polygon( + 0 4px, 4px 4px, 4px 0, + calc(100% - 4px) 0, calc(100% - 4px) 4px, 100% 4px, + 100% calc(100% - 4px), calc(100% - 4px) calc(100% - 4px), calc(100% - 4px) 100%, + 4px 100%, 4px calc(100% - 4px), 0 calc(100% - 4px) + ); + box-shadow: 0 4px 0 #2563EB; + transition: all 0.1s; +} + +.pixel-btn:hover { + transform: translateY(-2px); + box-shadow: 0 6px 0 #2563EB; +} + +.pixel-btn:active { + transform: translateY(2px); + box-shadow: 0 2px 0 #2563EB; +} + +.pixel-btn-green { + background: linear-gradient(180deg, #22C55E 0%, #16A34A 100%); + box-shadow: 0 4px 0 #15803D; +} + +.pixel-btn-green:hover { + box-shadow: 0 6px 0 #15803D; +} + +.pixel-btn-green:active { + box-shadow: 0 2px 0 #15803D; +} + +.pixel-btn-amber { + background: linear-gradient(180deg, #F59E0B 0%, #D97706 100%); + box-shadow: 0 4px 0 #B45309; +} + +.pixel-btn-amber:hover { + box-shadow: 0 6px 0 #B45309; +} + +.pixel-btn-amber:active { + box-shadow: 0 2px 0 #B45309; +} + +.pixel-panel { + background: linear-gradient(180deg, #FEF3C7 0%, #FDE68A 100%); + border: 4px solid #D97706; + clip-path: polygon( + 0 8px, 8px 8px, 8px 0, + calc(100% - 8px) 0, calc(100% - 8px) 8px, 100% 8px, + 100% calc(100% - 8px), calc(100% - 8px) calc(100% - 8px), calc(100% - 8px) 100%, + 8px 100%, 8px calc(100% - 8px), 0 calc(100% - 8px) + ); +} + +.pixel-panel-blue { + background: linear-gradient(180deg, #DBEAFE 0%, #BFDBFE 100%); + border-color: #2563EB; +} + +.pixel-panel-green { + background: linear-gradient(180deg, #DCFCE7 0%, #BBF7D0 100%); + border-color: #16A34A; +} + +.pixel-panel-red { + background: linear-gradient(180deg, #FEE2E2 0%, #FECACA 100%); + border-color: #DC2626; +} + +.pixel-text-shadow { + text-shadow: 2px 2px 0 rgba(0,0,0,0.3); +} + +/* Pixelated image rendering */ +.pixel-render { + image-rendering: pixelated; + image-rendering: crisp-edges; +} + +/* Pixel art prose styles for kids levels */ +.kids-prose-pixel { + color: #2C1810; + font-size: 1.5rem; +} + +.kids-prose-pixel h1, +.kids-prose-pixel h2, +.kids-prose-pixel h3 { + color: #2C1810; + text-shadow: 2px 2px 0 rgba(0,0,0,0.2); + margin-bottom: 1rem; + border-bottom: none; + padding-bottom: 0; +} + +.kids-prose-pixel h1 { + font-size: 2.75rem; +} + +.kids-prose-pixel h2 { + font-size: 2.25rem; +} + +.kids-prose-pixel h3 { + font-size: 1.875rem; +} + +.kids-prose-pixel p { + color: #5D4037; + margin-bottom: 1.25rem; + line-height: 1.8; + font-size: 1.5rem; +} + +.kids-prose-pixel ul, +.kids-prose-pixel ol { + color: #5D4037; + margin-bottom: 1.25rem; + padding-left: 2rem; + font-size: 1.5rem; +} + +.kids-prose-pixel li { + margin-bottom: 0.75rem; +} + +.kids-prose-pixel strong { + color: #2C1810; + font-weight: bold; +} + +.kids-prose-pixel em { + color: #8B4513; +} + +/* Reset margins for p tags inside interactive kids components */ +.kids-prose-pixel [class*="rounded-xl"] p, +.kids-prose-pixel [class*="rounded-lg"] p, +.kids-prose-pixel .pixel-panel p { + margin: 0; + padding: 0; +} + diff --git a/src/app/kids/layout.tsx b/src/app/kids/layout.tsx index 08d5f510..145a7f56 100644 --- a/src/app/kids/layout.tsx +++ b/src/app/kids/layout.tsx @@ -1,4 +1,31 @@ +import { Schoolbell } from "next/font/google"; import { KidsHeader } from "@/components/kids/layout/kids-header"; +import { BackgroundMusic } from "@/components/kids/layout/background-music"; +import { LevelProvider } from "@/components/kids/providers/level-context"; + +const kidsFont = Schoolbell({ + subsets: ["latin"], + weight: "400", + variable: "--font-kids", +}); + +// Pixel art cloud component for background +function PixelCloudBg({ className, style }: { className?: string; style?: React.CSSProperties }) { + return ( + + + + + + + + + ); +} export default function KidsLayout({ children, @@ -6,11 +33,50 @@ export default function KidsLayout({ children: React.ReactNode; }) { return ( -
+ +
+ {/* Smooth gradient sky background */} +
+ + {/* Animated pixel clouds - drift from left to right */} +
+ + + + + + +
+ -
+
{children}
+
+ ); } diff --git a/src/app/kids/level/[slug]/page.tsx b/src/app/kids/level/[slug]/page.tsx index f3750b8b..a3ef42fb 100644 --- a/src/app/kids/level/[slug]/page.tsx +++ b/src/app/kids/level/[slug]/page.tsx @@ -1,9 +1,7 @@ import { notFound } from "next/navigation"; -import Link from "next/link"; -import { getTranslations, getLocale } from "next-intl/server"; -import { getLevelBySlug, getAdjacentLevels, getAllLevels } from "@/lib/kids/levels"; -import { ChevronLeft, ChevronRight, Map } from "lucide-react"; -import { Button } from "@/components/ui/button"; +import { getLocale } from "next-intl/server"; +import { getLevelBySlug, getAllLevels } from "@/lib/kids/levels"; +import { LevelContentWrapper } from "@/components/kids/layout/level-content-wrapper"; import type { Metadata } from "next"; interface LevelPageProps { @@ -33,15 +31,12 @@ export async function generateMetadata({ params }: LevelPageProps): Promise ( -
-

- {t("level.comingSoon")} -

-
- ); + Content = null; } } return ( -
- {/* Level Header */} -
- - - {t("level.backToMap")} - - -
- - {t("level.levelLabel", { number: `${level.world}-${level.levelNumber}` })} - -
- -

- {level.title} -

-

- {level.description} -

-
- - {/* Level Content */} -
- -
- - {/* Navigation */} - -
+ + {Content ? : null} + ); } diff --git a/src/app/kids/map/page.tsx b/src/app/kids/map/page.tsx index d7c6ae0c..0304660d 100644 --- a/src/app/kids/map/page.tsx +++ b/src/app/kids/map/page.tsx @@ -11,12 +11,7 @@ export default async function KidsMapPage() { const t = await getTranslations("kids"); return ( -
-
-

{t("map.title")}

-

{t("map.subtitle")}

-
- +
); diff --git a/src/app/kids/page.tsx b/src/app/kids/page.tsx index 2a256b7a..562d4ee6 100644 --- a/src/app/kids/page.tsx +++ b/src/app/kids/page.tsx @@ -1,84 +1,11 @@ -import Link from "next/link"; -import { getTranslations } from "next-intl/server"; -import { Play, Sparkles, Star, Bot } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { PromiCharacter } from "@/components/kids/elements/character-guide"; import type { Metadata } from "next"; +import { KidsHomeContent } from "@/components/kids/layout/kids-home-content"; export const metadata: Metadata = { title: "Learn Prompting for Kids | prompts.chat", description: "A fun, game-based way for kids to learn how to talk to AI. Join Promi the robot on an adventure through Prompt Land!", }; -export default async function KidsHomePage() { - const t = await getTranslations("kids"); - - return ( -
- {/* Hero */} -
-
- - {t("home.badge")} -
- -

- {t("home.title")} -

- -

- {t("home.subtitle")} -

-
- - {/* Promi Introduction */} -
-
-
- -
-
-

{t("home.promiIntro.greeting")}

-

- {t("home.promiIntro.message")} -

-
-
-
- - {/* Features */} -
-
-
🎮
-

{t("home.features.games.title")}

-

{t("home.features.games.description")}

-
-
-
📖
-

{t("home.features.stories.title")}

-

{t("home.features.stories.description")}

-
-
-
-

{t("home.features.stars.title")}

-

{t("home.features.stars.description")}

-
-
- - {/* CTA */} -
- -
- - {/* Age note */} -

- {t("home.ageNote")} -

-
- ); +export default function KidsHomePage() { + return ; } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index fbb7746b..ba8bc71e 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -150,6 +150,7 @@ export default async function RootLayout({ const headersList = await headers(); const pathname = headersList.get("x-pathname") || headersList.get("x-invoke-path") || ""; const isEmbedRoute = pathname.startsWith("/embed"); + const isKidsRoute = pathname.startsWith("/kids"); const locale = await getLocale(); const messages = await getMessages(); @@ -198,7 +199,7 @@ export default async function RootLayout({ )} - {isEmbedRoute ? ( + {isEmbedRoute || isKidsRoute ? ( children ) : ( <> diff --git a/src/components/kids/elements/drag-drop-prompt.tsx b/src/components/kids/elements/drag-drop-prompt.tsx index e55a68ef..0293f306 100644 --- a/src/components/kids/elements/drag-drop-prompt.tsx +++ b/src/components/kids/elements/drag-drop-prompt.tsx @@ -1,189 +1,290 @@ "use client"; -import { useState, useCallback } from "react"; -import { Check, RefreshCw, GripVertical } from "lucide-react"; -import { Button } from "@/components/ui/button"; +import { useState, useCallback, useEffect, useId } from "react"; +import { useTranslations } from "next-intl"; +import { ChevronLeft, ChevronRight } from "lucide-react"; import { cn } from "@/lib/utils"; +import { useLevelSlug } from "@/components/kids/providers/level-context"; +import { getComponentState, saveComponentState } from "@/lib/kids/progress"; interface DragDropPromptProps { title?: string; instruction?: string; pieces: string[]; - correctOrder: number[]; // Indices of pieces in correct order + correctOrder: number[]; successMessage?: string; } +interface SavedState { + currentOrder: number[]; + submitted: boolean; + shuffledPieces: number[]; +} + export function DragDropPrompt({ - title = "Build the prompt! 🧩", - instruction = "Drag the pieces into the right order to make a good prompt.", + title, + instruction, pieces, correctOrder, - successMessage = "Perfect! You built a great prompt!", + successMessage, }: DragDropPromptProps) { - const [shuffledPieces] = useState(() => { - // Create array of indices and shuffle - const indices = pieces.map((_, i) => i); - for (let i = indices.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [indices[i], indices[j]] = [indices[j], indices[i]]; - } - return indices; - }); + const t = useTranslations("kids.dragDrop"); + const levelSlug = useLevelSlug(); + const componentId = useId(); + const displayTitle = title || t("title"); + const displayInstruction = instruction || t("instruction"); - const [currentOrder, setCurrentOrder] = useState(shuffledPieces); + const [shuffledPieces, setShuffledPieces] = useState([]); + const [currentOrder, setCurrentOrder] = useState([]); const [submitted, setSubmitted] = useState(false); - const [draggedIndex, setDraggedIndex] = useState(null); + const [selectedIndex, setSelectedIndex] = useState(null); + const [isLoaded, setIsLoaded] = useState(false); - const isCorrect = useCallback(() => { + // Load saved state on mount + useEffect(() => { + const shuffle = () => { + const indices = pieces.map((_, i) => i); + for (let i = indices.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [indices[i], indices[j]] = [indices[j], indices[i]]; + } + return indices; + }; + + if (!levelSlug) { + const shuffled = shuffle(); + setShuffledPieces(shuffled); + setCurrentOrder(shuffled); + setIsLoaded(true); + return; + } + + const saved = getComponentState(levelSlug, componentId); + if (saved && saved.shuffledPieces && saved.shuffledPieces.length > 0 && saved.currentOrder) { + setShuffledPieces(saved.shuffledPieces); + setCurrentOrder(saved.currentOrder); + setSubmitted(saved.submitted || false); + } else { + const shuffled = shuffle(); + setShuffledPieces(shuffled); + setCurrentOrder(shuffled); + } + setIsLoaded(true); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [levelSlug, componentId]); + + // Save state when it changes + useEffect(() => { + if (!levelSlug || !isLoaded || currentOrder.length === 0) return; + + saveComponentState(levelSlug, componentId, { + currentOrder, + submitted, + shuffledPieces, + }); + }, [levelSlug, componentId, currentOrder, submitted, shuffledPieces, isLoaded]); + + // Don't render until loaded to prevent hydration mismatch + if (!isLoaded) return null; + + const isCorrect = () => { return currentOrder.every((pieceIndex, position) => pieceIndex === correctOrder[position]); - }, [currentOrder, correctOrder]); - - const handleDragStart = (index: number) => { - setDraggedIndex(index); }; - const handleDragOver = (e: React.DragEvent, index: number) => { - e.preventDefault(); - if (draggedIndex === null || draggedIndex === index) return; - + // Move piece left (swap with previous) + const moveLeft = (position: number) => { + if (submitted || position === 0) return; const newOrder = [...currentOrder]; - const draggedItem = newOrder[draggedIndex]; - newOrder.splice(draggedIndex, 1); - newOrder.splice(index, 0, draggedItem); + [newOrder[position - 1], newOrder[position]] = [newOrder[position], newOrder[position - 1]]; setCurrentOrder(newOrder); - setDraggedIndex(index); }; - const handleDragEnd = () => { - setDraggedIndex(null); - }; - - const moveItem = (fromIndex: number, direction: "up" | "down") => { - const toIndex = direction === "up" ? fromIndex - 1 : fromIndex + 1; - if (toIndex < 0 || toIndex >= currentOrder.length) return; - + // Move piece right (swap with next) + const moveRight = (position: number) => { + if (submitted || position === currentOrder.length - 1) return; const newOrder = [...currentOrder]; - [newOrder[fromIndex], newOrder[toIndex]] = [newOrder[toIndex], newOrder[fromIndex]]; + [newOrder[position], newOrder[position + 1]] = [newOrder[position + 1], newOrder[position]]; setCurrentOrder(newOrder); }; + // Tap to select, tap another to swap + const handleTap = (position: number) => { + if (submitted) return; + + if (selectedIndex === null) { + // Select this piece + setSelectedIndex(position); + } else if (selectedIndex === position) { + // Deselect + setSelectedIndex(null); + } else { + // Swap with selected piece + const newOrder = [...currentOrder]; + [newOrder[selectedIndex], newOrder[position]] = [newOrder[position], newOrder[selectedIndex]]; + setCurrentOrder(newOrder); + setSelectedIndex(null); + } + }; + const handleSubmit = () => { setSubmitted(true); + setSelectedIndex(null); }; const handleReset = () => { setCurrentOrder(shuffledPieces); setSubmitted(false); + setSelectedIndex(null); }; const correct = isCorrect(); return ( -
+
{/* Header */} -
-

{title}

-

{instruction}

+
+ + {displayTitle}
+

{displayInstruction}

-
- {/* Draggable pieces */} -
- {currentOrder.map((pieceIndex, position) => ( + {/* Pieces with arrow controls */} +
+ {currentOrder.map((pieceIndex, position) => { + const isSelected = selectedIndex === position; + const isCorrectPiece = submitted && pieceIndex === correctOrder[position]; + const isWrongPiece = submitted && pieceIndex !== correctOrder[position]; + + return (
handleDragStart(position)} - onDragOver={(e) => handleDragOver(e, position)} - onDragEnd={handleDragEnd} className={cn( - "flex items-center gap-3 p-3 rounded-xl border-2 transition-all", - !submitted && "cursor-grab active:cursor-grabbing hover:border-primary hover:shadow-md", - submitted && pieceIndex === correctOrder[position] && "border-green-500 bg-green-50 dark:bg-green-950/30", - submitted && pieceIndex !== correctOrder[position] && "border-red-400 bg-red-50 dark:bg-red-950/30", - !submitted && "border-muted-foreground/20 bg-white dark:bg-card", - draggedIndex === position && "opacity-50 scale-95" + "flex items-center gap-2 p-2 rounded-lg border-2 transition-all", + !submitted && !isSelected && "bg-white border-[#D97706] hover:bg-[#FEF3C7]", + !submitted && isSelected && "bg-[#DBEAFE] border-[#3B82F6] ring-2 ring-[#3B82F6] scale-[1.02]", + isCorrectPiece && "bg-[#DCFCE7] border-[#16A34A]", + isWrongPiece && "bg-[#FEE2E2] border-[#DC2626]" )} > - {!submitted && ( -
- - -
- )} - - - - {pieces[pieceIndex]} - - + {/* Position number */} + {position + 1} + + {/* Left arrow */} + + + {/* Piece content - tappable */} + + + {/* Right arrow */} + + + {/* Status indicator */} + {submitted && ( + + {isCorrectPiece ? "✓" : "✗"} + + )}
- ))} + ); + })} +
+ + {/* Hint for tap-to-swap */} + {selectedIndex !== null && ( +
+

+ 👆 {t("tapToSwap")} +

+ )} - {/* Preview */} -
-

Your prompt will look like:

-
-            {currentOrder.map((i) => pieces[i]).join(" ")}
-          
-
+ {/* Preview */} +
+ {t("result")}: + + {currentOrder.map((i) => pieces[i]).join(" ")} + +
- {/* Result */} - {submitted && ( -
- {correct ? ( - <> -

🎉

-

{successMessage}

- - ) : ( - <> -

Almost there!

-

- Try moving the pieces around to find the best order. -

- - )} -
- )} - - {/* Actions */} -
- {!submitted ? ( - + {/* Result feedback */} + {submitted && ( +
+ {correct ? ( +

🎉 {successMessage || t("success")}

) : ( - +

{t("almost")}

)}
+ )} + + {/* Actions */} +
+ {!submitted ? ( + + ) : ( + + )}
); } + +function PixelPuzzleIcon() { + return ( + + + + + + + + + ); +} diff --git a/src/components/kids/elements/example-matcher.tsx b/src/components/kids/elements/example-matcher.tsx new file mode 100644 index 00000000..8e9f119f --- /dev/null +++ b/src/components/kids/elements/example-matcher.tsx @@ -0,0 +1,196 @@ +"use client"; + +import { useState, useEffect, useId } from "react"; +import { useTranslations } from "next-intl"; +import { cn } from "@/lib/utils"; +import { useLevelSlug } from "@/components/kids/providers/level-context"; +import { getComponentState, saveComponentState } from "@/lib/kids/progress"; + +interface Example { + input: string; + output: string; +} + +interface ExampleMatcherProps { + title?: string; + instruction?: string; + examples: Example[]; + question: string; + options: string[]; + correctAnswer: string; + explanation?: string; +} + +interface SavedState { + selectedAnswer: string | null; + submitted: boolean; +} + +export function ExampleMatcher({ + title, + instruction, + examples, + question, + options, + correctAnswer, + explanation, +}: ExampleMatcherProps) { + const t = useTranslations("kids.exampleMatcher"); + const levelSlug = useLevelSlug(); + const componentId = useId(); + + const displayTitle = title || t("title"); + const displayInstruction = instruction || t("instruction"); + + const [selectedAnswer, setSelectedAnswer] = useState(null); + const [submitted, setSubmitted] = useState(false); + const [isLoaded, setIsLoaded] = useState(false); + + // Load saved state + useEffect(() => { + if (!levelSlug) { + setIsLoaded(true); + return; + } + const saved = getComponentState(levelSlug, componentId); + if (saved) { + setSelectedAnswer(saved.selectedAnswer); + setSubmitted(saved.submitted); + } + setIsLoaded(true); + }, [levelSlug, componentId]); + + // Save state + useEffect(() => { + if (!levelSlug || !isLoaded) return; + saveComponentState(levelSlug, componentId, { + selectedAnswer, + submitted, + }); + }, [levelSlug, componentId, selectedAnswer, submitted, isLoaded]); + + if (!isLoaded) return null; + + const isCorrect = selectedAnswer === correctAnswer; + + const handleSelect = (option: string) => { + if (submitted) return; + setSelectedAnswer(option); + }; + + const handleSubmit = () => { + if (!selectedAnswer) return; + setSubmitted(true); + }; + + const handleReset = () => { + setSelectedAnswer(null); + setSubmitted(false); + }; + + return ( +
+ {/* Title */} +

+ 🧩 {displayTitle} +

+

{displayInstruction}

+ + {/* Examples Pattern */} +
+
{t("pattern")}
+
+ {examples.map((example, index) => ( +
+ {example.input} + + {example.output} +
+ ))} + {/* Question row */} +
+ + {question} + + + + {submitted ? (isCorrect ? selectedAnswer : `${selectedAnswer} ❌`) : "???"} + +
+
+
+ + {/* Options */} +
+ {options.map((option) => { + const isSelected = selectedAnswer === option; + const showCorrect = submitted && option === correctAnswer; + const showWrong = submitted && isSelected && !isCorrect; + + return ( + + ); + })} +
+ + {/* Submit/Reset buttons */} +
+ {!submitted ? ( + + ) : ( + + )} +
+ + {/* Result feedback */} + {submitted && ( +
+

+ {isCorrect ? t("correct") : t("tryAgain")} +

+ {explanation && ( +

{explanation}

+ )} +
+ )} +
+ ); +} diff --git a/src/components/kids/elements/index.ts b/src/components/kids/elements/index.ts index 541fc90a..c9f0cf2d 100644 --- a/src/components/kids/elements/index.ts +++ b/src/components/kids/elements/index.ts @@ -1,7 +1,14 @@ -export { PromiCharacter, SpeechBubble, PromiWithMessage } from "./character-guide"; +export { PromiCharacter, PromiWithMessage } from './character-guide'; +export { Section, LevelSlides } from './level-slides'; export { StoryScene, Panel } from "./story-scene"; export { ProgressMap } from "./progress-map"; export { PromptVsMistake } from "./prompt-vs-mistake"; export { MagicWords } from "./magic-words"; export { DragDropPrompt } from "./drag-drop-prompt"; export { LevelComplete } from "./level-complete"; +export { PromptParts } from "./prompt-parts"; +export { ExampleMatcher } from "./example-matcher"; +export { PromptDoctor } from "./prompt-doctor"; +export { StepByStep } from "./step-by-step"; +export { PromptLab } from "./prompt-lab"; +export { WordPredictor } from "./word-predictor"; diff --git a/src/components/kids/elements/level-complete.tsx b/src/components/kids/elements/level-complete.tsx index 94582a8f..af120487 100644 --- a/src/components/kids/elements/level-complete.tsx +++ b/src/components/kids/elements/level-complete.tsx @@ -3,16 +3,15 @@ import { useEffect, useState } from "react"; import Link from "next/link"; import { useTranslations } from "next-intl"; -import { Star, ArrowRight, Map, RotateCcw } from "lucide-react"; -import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; import { completeLevel, getLevelProgress } from "@/lib/kids/progress"; -import { getAdjacentLevels } from "@/lib/kids/levels"; -import { PromiCharacter } from "./character-guide"; +import { getAdjacentLevels, getLevelBySlug } from "@/lib/kids/levels"; +import { analyticsKids } from "@/lib/analytics"; +import { PixelRobot, PixelStar } from "./pixel-art"; interface LevelCompleteProps { levelSlug: string; - stars?: number; // 1-3, calculated based on performance + stars?: number; message?: string; } @@ -27,58 +26,63 @@ export function LevelComplete({ const { next } = getAdjacentLevels(levelSlug); useEffect(() => { - // Check if already completed with higher stars const existingProgress = getLevelProgress(levelSlug); const existingStars = existingProgress?.stars || 0; if (stars > existingStars) { - // Save progress completeLevel(levelSlug, stars); setShowConfetti(true); + + // Track level completion + const level = getLevelBySlug(levelSlug); + if (level) { + analyticsKids.completeLevel(levelSlug, level.world, stars); + } } setSavedStars(Math.max(stars, existingStars)); - // Hide confetti after animation const timer = setTimeout(() => setShowConfetti(false), 3000); return () => clearTimeout(timer); }, [levelSlug, stars]); return (
- {/* Confetti effect */} + {/* Pixel confetti effect */} {showConfetti && (
- {Array.from({ length: 20 }).map((_, i) => ( + {Array.from({ length: 15 }).map((_, i) => (
- {["🎉", "⭐", "🌟", "✨", "🎊"][Math.floor(Math.random() * 5)]} +
))}
)} -
+
{/* Header */}
- +
-

🎉 {t("levelComplete.title")}

-

{message}

+

+ {t("levelComplete.title")} +

+

{message}

- {/* Stars */} -
+ {/* Pixel Stars */} +
{[1, 2, 3].map((star) => (
- +
))}
- {/* Actions */} -
+ {/* Actions - pixel style */} +
{next ? ( - + + + ) : ( - + + {t("levelComplete.allDone")} + )} - + +
); } + +function PixelArrowRight() { + return ( + + + + + + + ); +} + +function PixelMapIcon() { + return ( + + {/* Pin head - circle */} + + + + + + {/* Pin point */} + + + {/* Inner highlight */} + + + ); +} diff --git a/src/components/kids/elements/level-slides.tsx b/src/components/kids/elements/level-slides.tsx new file mode 100644 index 00000000..66fb2759 --- /dev/null +++ b/src/components/kids/elements/level-slides.tsx @@ -0,0 +1,134 @@ +"use client"; + +import { useState, Children, isValidElement, ReactNode, ReactElement } from "react"; +import { ChevronLeft, ChevronRight, Map } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { cn } from "@/lib/utils"; +import Link from "next/link"; +import { useTranslations } from "next-intl"; + +interface SectionProps { + children: ReactNode; +} + +export function Section({ children }: SectionProps) { + return <>{children}; +} + +interface LevelSlidesProps { + children: ReactNode; + levelSlug: string; +} + +export function LevelSlides({ children, levelSlug }: LevelSlidesProps) { + const t = useTranslations("kids"); + const [currentSection, setCurrentSection] = useState(0); + + // Extract Section components from children + const sections: ReactElement[] = []; + Children.forEach(children, (child) => { + if (isValidElement(child) && child.type === Section) { + sections.push(child); + } + }); + + // If no sections found, wrap all content in one section + if (sections.length === 0) { + sections.push(
{children}
); + } + + const totalSections = sections.length; + const isFirstSection = currentSection === 0; + const isLastSection = currentSection === totalSections - 1; + + const goToNext = () => { + if (!isLastSection) { + setCurrentSection((prev) => prev + 1); + } + }; + + const goToPrev = () => { + if (!isFirstSection) { + setCurrentSection((prev) => prev - 1); + } + }; + + return ( +
+ {/* Content area */} +
+
+
+ {sections[currentSection]} +
+
+
+ + {/* Navigation footer */} +
+
+ {/* Back button */} + + + {/* Progress indicators */} +
+ {Array.from({ length: totalSections }).map((_, i) => ( +
+ + {/* Next button or Map link */} + {!isLastSection ? ( + + ) : ( + + )} +
+
+
+ ); +} diff --git a/src/components/kids/elements/magic-words.tsx b/src/components/kids/elements/magic-words.tsx index 90915f03..050d41d8 100644 --- a/src/components/kids/elements/magic-words.tsx +++ b/src/components/kids/elements/magic-words.tsx @@ -1,55 +1,111 @@ "use client"; -import { useState, useCallback } from "react"; +import { useState, useCallback, useEffect, useId } from "react"; +import { useTranslations } from "next-intl"; import { Check, RefreshCw, Sparkles, GripVertical } from "lucide-react"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; +import { useLevelSlug } from "@/components/kids/providers/level-context"; +import { getComponentState, saveComponentState } from "@/lib/kids/progress"; interface BlankConfig { - id: string; + id?: string; hint: string; - answers: string[]; // Words to choose from (first one is correct) + answers: string[]; // Words to choose from (all are correct) emoji?: string; } interface MagicWordsProps { title?: string; - sentence: string; // Use {{id}} for blanks + sentence: string; // Use _ for blanks blanks: BlankConfig[]; successMessage?: string; } +interface SavedState { + placements: Record; + submitted: boolean; + availableWords: { word: string; blankId: string }[]; +} + export function MagicWords({ - title = "Drag the magic words! ✨", + title, sentence, blanks, - successMessage = "Amazing! You created a great prompt!", + successMessage, }: MagicWordsProps) { + const t = useTranslations("kids.magicWords"); + const levelSlug = useLevelSlug(); + const componentId = useId(); + const displayTitle = title || t("title"); + const [placements, setPlacements] = useState>({}); const [submitted, setSubmitted] = useState(false); const [draggedWord, setDraggedWord] = useState(null); + const [availableWords, setAvailableWords] = useState<{ word: string; blankId: string }[]>([]); + const [isLoaded, setIsLoaded] = useState(false); - // Get all available words from blanks (shuffled) - const [availableWords] = useState(() => { - const words = blanks.flatMap((blank) => - blank.answers.map((answer) => ({ word: answer, blankId: blank.id })) - ); - // Shuffle - for (let i = words.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [words[i], words[j]] = [words[j], words[i]]; + // Generate IDs for blanks if not provided + const blanksWithIds = blanks.map((blank, index) => ({ + ...blank, + id: blank.id || `blank-${index}`, + })); + + // Load saved state on mount + useEffect(() => { + const shuffleWords = () => { + const words = blanksWithIds.flatMap((blank) => + blank.answers.map((answer) => ({ word: answer, blankId: blank.id! })) + ); + for (let i = words.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [words[i], words[j]] = [words[j], words[i]]; + } + return words; + }; + + if (!levelSlug) { + setPlacements({}); + setAvailableWords(shuffleWords()); + setIsLoaded(true); + return; } - return words; - }); + + const saved = getComponentState(levelSlug, componentId); + if (saved && saved.placements && saved.availableWords && saved.availableWords.length > 0) { + setPlacements(saved.placements); + setSubmitted(saved.submitted || false); + setAvailableWords(saved.availableWords); + } else { + setPlacements({}); + setAvailableWords(shuffleWords()); + } + setIsLoaded(true); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [levelSlug, componentId]); + + // Save state when it changes + useEffect(() => { + if (!levelSlug || !isLoaded || availableWords.length === 0) return; + + saveComponentState(levelSlug, componentId, { + placements, + submitted, + availableWords, + }); + }, [levelSlug, componentId, placements, submitted, availableWords, isLoaded]); const checkAnswer = useCallback((blankId: string, value: string): boolean => { - const blank = blanks.find((b) => b.id === blankId); + const blank = blanksWithIds.find((b) => b.id === blankId); if (!blank) return false; return blank.answers.some((answer) => answer.toLowerCase() === value.toLowerCase()); - }, [blanks]); + }, [blanksWithIds]); - const allCorrect = submitted && blanks.every((blank) => checkAnswer(blank.id, placements[blank.id] || "")); - const score = blanks.filter((blank) => checkAnswer(blank.id, placements[blank.id] || "")).length; + // Don't render until loaded to prevent hydration mismatch + if (!isLoaded) return null; + + const allCorrect = submitted && blanksWithIds.every((blank) => checkAnswer(blank.id, placements[blank.id] || "")); + const score = blanksWithIds.filter((blank) => checkAnswer(blank.id, placements[blank.id] || "")).length; const usedWords = Object.values(placements); @@ -80,7 +136,7 @@ export function MagicWords({ if (submitted) return; // Find first empty blank - const emptyBlank = blanks.find((blank) => !placements[blank.id]); + const emptyBlank = blanksWithIds.find((blank) => !placements[blank.id]); if (emptyBlank) { // Remove word from previous placement const newPlacements = { ...placements }; @@ -113,36 +169,42 @@ export function MagicWords({ // Parse sentence and render with drop zones const renderSentence = () => { - const parts = sentence.split(/(\{\{[^}]+\}\})/g); + // Split by underscore placeholders + const parts = sentence.split(/(_+)/g); + let blankIndex = 0; return parts.map((part, index) => { - const match = part.match(/\{\{([^}]+)\}\}/); - if (match) { - const blankId = match[1]; - const blank = blanks.find((b) => b.id === blankId); + // Check if this is a blank placeholder (one or more underscores) + if (/^_+$/.test(part)) { + const blank = blanksWithIds[blankIndex]; + if (!blank) return {part}; + + const blankId = blank.id; const placedWord = placements[blankId]; const isCorrect = submitted && checkAnswer(blankId, placedWord || ""); const isWrong = submitted && !isCorrect; + blankIndex++; + return ( - {blank?.emoji && {blank.emoji}} placedWord && handleClickBlank(blankId)} onDragOver={(e) => e.preventDefault()} onDrop={() => handleDrop(blankId)} className={cn( - "px-3 py-2 border-2 border-dashed rounded-xl min-w-[100px] text-center font-medium transition-all cursor-pointer", - !placedWord && "bg-white dark:bg-card border-primary/50", - placedWord && !submitted && "bg-primary/10 border-primary border-solid", - isCorrect && "border-green-500 border-solid bg-green-50 dark:bg-green-950/30", - isWrong && "border-red-400 border-solid bg-red-50 dark:bg-red-950/30", - draggedWord && !placedWord && "border-primary bg-primary/5 scale-105" + "px-3 py-2 border-2 border-dashed rounded-lg min-w-[100px] text-xl text-center font-medium transition-all cursor-pointer text-[#2C1810]", + !placedWord && "bg-white border-purple-400", + placedWord && !submitted && "bg-purple-100 border-purple-500 border-solid", + isCorrect && "border-green-500 border-solid bg-green-50", + isWrong && "border-red-400 border-solid bg-red-50", + draggedWord && !placedWord && "border-purple-500 bg-purple-50 scale-105" )} + title={blank.hint} > - {placedWord || "___"} + {placedWord || blank.hint} - {submitted && isCorrect && } + {submitted && isCorrect && } ); } @@ -151,25 +213,25 @@ export function MagicWords({ }; return ( -
+
{/* Header */} -
+
- - {title} + + {displayTitle}
{/* Sentence with blanks */} -
+
{renderSentence()}
{/* Word bank */} -
-

- 🎯 Drag or tap words to fill the blanks: +

+

+ {t("dragOrTap")}

{availableWords.map(({ word }, index) => { @@ -180,16 +242,18 @@ export function MagicWords({ draggable={!submitted && !isUsed} onDragStart={() => handleDragStart(word)} onDragEnd={handleDragEnd} + onTouchStart={() => !isUsed && !submitted && handleDragStart(word)} + onTouchEnd={() => handleDragEnd()} onClick={() => !isUsed && handleClickWord(word)} disabled={submitted || isUsed} className={cn( - "flex items-center gap-1 px-3 py-2 rounded-lg border-2 font-medium transition-all", - !isUsed && !submitted && "bg-white dark:bg-card border-purple-300 hover:border-purple-500 hover:shadow-md cursor-grab active:cursor-grabbing", - isUsed && "bg-muted/50 border-muted text-muted-foreground opacity-50 cursor-not-allowed", + "flex items-center gap-2 px-4 py-3 rounded-lg border-2 text-xl font-medium transition-all text-[#2C1810]", + !isUsed && !submitted && "bg-white border-purple-300 hover:border-purple-500 hover:shadow-md cursor-grab active:cursor-grabbing", + isUsed && "bg-gray-100 border-gray-300 text-gray-400 opacity-50 cursor-not-allowed", submitted && "cursor-default" )} > - {!submitted && !isUsed && } + {!submitted && !isUsed && } {word} ); @@ -201,45 +265,37 @@ export function MagicWords({ {submitted && (
{allCorrect ? ( - <> -

🎉

-

{successMessage}

- +

🎉 {successMessage || "Amazing!"}

) : ( - <> -

- {score} of {blanks.length} correct! -

-

- Try different words! -

- +

+ {score} / {blanksWithIds.length} {t("correct")}! {t("tryAgain")} +

)}
)} {/* Actions */} -
+
{!submitted ? ( ) : ( - )}
diff --git a/src/components/kids/elements/pixel-art.tsx b/src/components/kids/elements/pixel-art.tsx new file mode 100644 index 00000000..1b99c02c --- /dev/null +++ b/src/components/kids/elements/pixel-art.tsx @@ -0,0 +1,287 @@ +"use client"; + +import { cn } from "@/lib/utils"; + +// Pixel Art Tree (Pine) +export function PixelTree({ className }: { className?: string }) { + return ( + + {/* Tree top */} + + + + + + + + + {/* Trunk */} + + + ); +} + +// Pixel Art Bush +export function PixelBush({ className }: { className?: string }) { + return ( + + + + + + + ); +} + +// Pixel Art Cloud +export function PixelCloud({ className }: { className?: string }) { + return ( + + + + + + + + + + ); +} + +// Pixel Art Castle +export function PixelCastle({ className }: { className?: string }) { + return ( + + {/* Towers */} + + + + + + + {/* Main body */} + + + {/* Windows */} + + + {/* Door */} + + + {/* Flag */} + + + {/* Base */} + + + ); +} + +// Pixel Art Mountain +export function PixelMountain({ className }: { className?: string }) { + return ( + + {/* Snow cap */} + + + {/* Mountain body */} + + + + + + ); +} + +// Pixel Art Flower +export function PixelFlower({ className, color = "#FF69B4" }: { className?: string; color?: string }) { + return ( + + {/* Petals */} + + + + + {/* Center */} + + {/* Stem */} + + + ); +} + +// Pixel Art Star +export function PixelStar({ className, filled = false }: { className?: string; filled?: boolean }) { + const color = filled ? "#FFD700" : "#D3D3D3"; + return ( + + + + + + + + + + + ); +} + +// Pixel Art Robot (Promi) +export function PixelRobot({ className }: { className?: string }) { + return ( + + {/* Antenna */} + + + {/* Head */} + + + + + + + {/* Body */} + + + {/* Arms */} + + + {/* Feet */} + + + + ); +} + +// Pixel Art Level Node +export function PixelLevelNode({ + state, + levelNumber, + className +}: { + state: "locked" | "available" | "completed"; + levelNumber: string; + className?: string; +}) { + const bgColor = state === "completed" ? "#22C55E" : state === "available" ? "#3B82F6" : "#6B7280"; + const borderColor = state === "completed" ? "#16A34A" : state === "available" ? "#2563EB" : "#4B5563"; + const glowColor = state === "available" ? "rgba(59, 130, 246, 0.4)" : state === "completed" ? "rgba(34, 197, 94, 0.3)" : "transparent"; + + return ( +
+ {/* Glow effect */} + {state !== "locked" && ( +
+ )} + + {/* Outer border */} + + + + + {/* Inner fill */} + + {/* Icon based on state */} + {state === "locked" && ( + <> + {/* Lock icon */} + + + + + )} + {state === "available" && ( + <> + {/* Play icon */} + + + + + )} + {state === "completed" && ( + <> + {/* Checkmark */} + + + + + + + + )} + + {/* Level number badge */} +
+ {levelNumber} +
+
+ ); +} + +// Pixel Art Path Segment +export function PixelPath({ width = 100, className }: { width?: number; className?: string }) { + const segments = Math.ceil(width / 8); + return ( + + {Array.from({ length: segments }).map((_, i) => ( + + ))} + + ); +} diff --git a/src/components/kids/elements/progress-map.tsx b/src/components/kids/elements/progress-map.tsx index 11b3711b..d012e41c 100644 --- a/src/components/kids/elements/progress-map.tsx +++ b/src/components/kids/elements/progress-map.tsx @@ -1,99 +1,266 @@ "use client"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useRef } from "react"; import Link from "next/link"; import { useTranslations } from "next-intl"; -import { Star, Lock, Check, Play } from "lucide-react"; +import { ChevronLeft, ChevronRight } from "lucide-react"; import { cn } from "@/lib/utils"; -import { worlds, type Level } from "@/lib/kids/levels"; +import { worlds, type Level, getAllLevels } from "@/lib/kids/levels"; import { getProgress, isLevelUnlocked, type KidsProgress } from "@/lib/kids/progress"; +import { analyticsKids } from "@/lib/analytics"; +import { Button } from "@/components/ui/button"; +import { + PixelTree, + PixelBush, + PixelCastle, + PixelMountain, + PixelFlower, + PixelStar, + PixelRobot, + PixelLevelNode +} from "./pixel-art"; export function ProgressMap() { const t = useTranslations("kids"); const [progress, setProgress] = useState(null); + const scrollRef = useRef(null); + const allLevels = getAllLevels(); useEffect(() => { setProgress(getProgress()); + analyticsKids.viewMap(); }, []); - return ( -
- {worlds.map((world) => ( - - ))} -
- ); -} + // Calculate positions for all levels in a continuous horizontal path + const levelPositions = allLevels.map((_, index) => { + const spacing = 200; // pixels between levels + const x = 120 + index * spacing; + // Create a gentle wave pattern - centered around 55% + const y = 55 + Math.sin(index * 0.8) * 15; + return { x, y }; + }); -interface WorldSectionProps { - world: typeof worlds[0]; - progress: KidsProgress | null; - t: ReturnType; -} + // Calculate map width - ensure it fits content but also works on large screens + const calculatedWidth = (allLevels.length * 200) + 240; + const mapWidth = Math.max(calculatedWidth, 800); -function WorldSection({ world, progress, t }: WorldSectionProps) { - const colorClasses = { - emerald: { - bg: "bg-emerald-50 dark:bg-emerald-950/30", - border: "border-emerald-200 dark:border-emerald-800", - text: "text-emerald-700 dark:text-emerald-300", - badge: "bg-emerald-100 dark:bg-emerald-900/50", - }, - blue: { - bg: "bg-blue-50 dark:bg-blue-950/30", - border: "border-blue-200 dark:border-blue-800", - text: "text-blue-700 dark:text-blue-300", - badge: "bg-blue-100 dark:bg-blue-900/50", - }, - }[world.color] || { - bg: "bg-gray-50 dark:bg-gray-950/30", - border: "border-gray-200 dark:border-gray-800", - text: "text-gray-700 dark:text-gray-300", - badge: "bg-gray-100 dark:bg-gray-900/50", + const scrollLeft = () => { + scrollRef.current?.scrollBy({ left: -300, behavior: "smooth" }); + }; + + const scrollRight = () => { + scrollRef.current?.scrollBy({ left: 300, behavior: "smooth" }); }; return ( -
- {/* World Header */} -
- {world.emoji} -
-

{t(`worlds.${world.number}.title`)}

-

- {t("map.worldLevels", { count: world.levels.length })} -

+
+ {/* Scroll controls for desktop */} +
+ +
+
+ +
+ + {/* Horizontal scrolling map container */} +
+
+ {/* Sky is handled by kids layout - no additional background needed */} + + {/* Pixel art ground layers - use full width (max of mapWidth or 100%) */} +
+
+
+ + {/* Pixel art path connecting all levels */} + + {/* Draw dotted path between levels - pixel style */} + + {/* Path border for depth */} + + + + {/* Decorative elements - rendered after path so clouds appear on top */} + + + {/* World labels - pixel art style */} + {worlds.map((world) => { + const firstLevelIndex = allLevels.findIndex(l => l.world === world.number); + if (firstLevelIndex === -1) return null; + const pos = levelPositions[firstLevelIndex]; + return ( +
+
+ {t(`worlds.${world.number}.title`)} +
+
+ ); + })} + + {/* Level nodes */} + {allLevels.map((level, index) => ( + + ))}
- {/* Levels */} -
- {world.levels.map((level) => ( - - ))} + {/* Progress bar at bottom - pixel art style */} +
+
+
+ {t("map.title")} +
+ + + {getCompletedCount(progress, allLevels)} / {allLevels.length} + +
+
+ {/* Pixel art progress bar */} +
+
+ {/* Pixel segments overlay */} +
+ {Array.from({ length: allLevels.length }).map((_, i) => ( +
+ ))} +
+
+
); } -interface LevelCardProps { +function generatePathD(positions: { x: number; y: number }[]): string { + if (positions.length === 0) return ""; + + let d = `M ${positions[0].x} ${positions[0].y}`; + + for (let i = 1; i < positions.length; i++) { + const prev = positions[i - 1]; + const curr = positions[i]; + const midX = (prev.x + curr.x) / 2; + // Create smooth curves + d += ` Q ${midX} ${prev.y}, ${midX} ${(prev.y + curr.y) / 2}`; + d += ` Q ${midX} ${curr.y}, ${curr.x} ${curr.y}`; + } + + return d; +} + +function MapDecorations({ mapWidth }: { mapWidth: number }) { + // Generate decorations along the map - using seeded positions for consistency + const decorations = []; + const spacing = 100; + + for (let i = 0; i < Math.floor(mapWidth / spacing); i++) { + const x = 50 + i * spacing; + const type = i % 5; + const yOffset = Math.sin(i * 0.8) * 10; + + decorations.push( +
+ {type === 0 && } + {type === 1 && } + {type === 2 && } + {type === 3 && } + {type === 4 && } +
+ ); + } + +// Add castle at the end + decorations.push( +
+ +
+ ); + + return <>{decorations}; +} + +function getCompletedCount(progress: KidsProgress | null, levels: Level[]): number { + if (!progress) return 0; + return levels.filter(l => progress.levels[l.slug]?.completed).length; +} + +interface LevelNodeProps { level: Level; + position: { x: number; y: number }; progress: KidsProgress | null; - colorClasses: { - bg: string; - border: string; - text: string; - badge: string; - }; + index: number; t: ReturnType; } -function LevelCard({ level, progress, colorClasses, t }: LevelCardProps) { +function LevelNode({ level, position, progress, index, t }: LevelNodeProps) { const [unlocked, setUnlocked] = useState(false); const levelProgress = progress?.levels[level.slug]; const isCompleted = levelProgress?.completed; @@ -103,65 +270,56 @@ function LevelCard({ level, progress, colorClasses, t }: LevelCardProps) { setUnlocked(isLevelUnlocked(level.slug)); }, [level.slug, progress]); - if (!unlocked) { - return ( -
-
- -
-
-

{t(`levels.${level.slug.replace(/-/g, "_")}.title`)}

-

{t("map.locked")}

+ const state = !unlocked ? "locked" : isCompleted ? "completed" : "available"; + + const nodeContent = ( +
+ {/* Pixel art level node */} + + + {/* Stars for completed levels */} + {isCompleted && ( +
+ {[1, 2, 3].map((star) => ( + + ))}
+ )} + + {/* Level title label - pixel style */} +
+ {t(`levels.${level.slug.replace(/-/g, "_")}.title`)}
- ); +
+ ); + + if (!unlocked) { + return
{nodeContent}
; } return ( - - {/* Status badge */} -
- {isCompleted ? ( -
- -
- ) : ( -
- -
- )} -
- - {/* Level info */} -
- - {t("map.levelNumber", { number: `${level.world}-${level.levelNumber}` })} - -
- -

{level.title}

-

{level.description}

- - {/* Stars */} -
- {[1, 2, 3].map((star) => ( - - ))} -
+ + {nodeContent} ); } diff --git a/src/components/kids/elements/prompt-doctor.tsx b/src/components/kids/elements/prompt-doctor.tsx new file mode 100644 index 00000000..38061861 --- /dev/null +++ b/src/components/kids/elements/prompt-doctor.tsx @@ -0,0 +1,208 @@ +"use client"; + +import { useState, useEffect, useId } from "react"; +import { useTranslations } from "next-intl"; +import { cn } from "@/lib/utils"; +import { useLevelSlug } from "@/components/kids/providers/level-context"; +import { getComponentState, saveComponentState } from "@/lib/kids/progress"; + +interface Problem { + issue: string; + symptom: string; + fix: string; +} + +interface PromptDoctorProps { + title?: string; + brokenPrompt: string; + problems: Problem[]; + healedPrompt: string; + successMessage?: string; +} + +interface SavedState { + fixedProblems: number[]; + isHealed: boolean; +} + +export function PromptDoctor({ + title, + brokenPrompt, + problems, + healedPrompt, + successMessage, +}: PromptDoctorProps) { + const t = useTranslations("kids.promptDoctor"); + const levelSlug = useLevelSlug(); + const componentId = useId(); + + const displayTitle = title || t("title"); + + const [fixedProblems, setFixedProblems] = useState([]); + const [isHealed, setIsHealed] = useState(false); + const [isLoaded, setIsLoaded] = useState(false); + + // Load saved state + useEffect(() => { + if (!levelSlug) { + setIsLoaded(true); + return; + } + const saved = getComponentState(levelSlug, componentId); + if (saved && saved.fixedProblems) { + setFixedProblems(saved.fixedProblems); + setIsHealed(saved.isHealed || false); + } + setIsLoaded(true); + }, [levelSlug, componentId]); + + // Save state + useEffect(() => { + if (!levelSlug || !isLoaded) return; + saveComponentState(levelSlug, componentId, { + fixedProblems, + isHealed, + }); + }, [levelSlug, componentId, fixedProblems, isHealed, isLoaded]); + + if (!isLoaded) return null; + + const handleFixProblem = (index: number) => { + if (fixedProblems.includes(index) || isHealed) return; + + const newFixed = [...fixedProblems, index]; + setFixedProblems(newFixed); + + if (newFixed.length === problems.length) { + setIsHealed(true); + } + }; + + const handleReset = () => { + setFixedProblems([]); + setIsHealed(false); + }; + + // Calculate current prompt based on fixes applied + const getCurrentPrompt = () => { + if (isHealed) return healedPrompt; + + let currentPrompt = brokenPrompt; + // Apply fixes in order + problems.forEach((problem, index) => { + if (fixedProblems.includes(index)) { + // This is simplified - in reality you'd need smarter text manipulation + currentPrompt = problem.fix; + } + }); + + // Return the last applied fix or broken prompt + if (fixedProblems.length > 0) { + return problems[fixedProblems[fixedProblems.length - 1]].fix; + } + return brokenPrompt; + }; + + const healthPercentage = (fixedProblems.length / problems.length) * 100; + + return ( +
+ {/* Title */} +

+ 🏥 {displayTitle} +

+ + {/* Health bar */} +
+
+ {t("health")} + {Math.round(healthPercentage)}% +
+
+
+
+
+ + {/* Current prompt display */} +
+
+ {isHealed ? ( + 💚 + ) : ( + 🤒 + )} + + {isHealed ? t("healthy") : t("sick")} + +
+

+ "{getCurrentPrompt()}" +

+
+ + {/* Problems to fix */} + {!isHealed && ( +
+
{t("diagnose")}
+ {problems.map((problem, index) => { + const isFixed = fixedProblems.includes(index); + return ( + + ); + })} +
+ )} + + {/* Success message */} + {isHealed && ( +
+

+ ✨ {successMessage || t("success")} +

+
+ )} + + {/* Reset button */} + {(isHealed || fixedProblems.length > 0) && ( + + )} +
+ ); +} diff --git a/src/components/kids/elements/prompt-lab.tsx b/src/components/kids/elements/prompt-lab.tsx new file mode 100644 index 00000000..c2cc05c2 --- /dev/null +++ b/src/components/kids/elements/prompt-lab.tsx @@ -0,0 +1,203 @@ +"use client"; + +import { useState, useEffect, useId } from "react"; +import { useTranslations } from "next-intl"; +import { cn } from "@/lib/utils"; +import { useLevelSlug } from "@/components/kids/providers/level-context"; +import { getComponentState, saveComponentState } from "@/lib/kids/progress"; + +interface Improvement { + label: string; + prompt: string; + response: string; +} + +interface PromptLabProps { + title?: string; + scenario: string; + basePrompt: string; + baseResponse: string; + improvements: Improvement[]; + successMessage?: string; +} + +interface SavedState { + appliedImprovements: number[]; + completed: boolean; +} + +export function PromptLab({ + title, + scenario, + basePrompt, + baseResponse, + improvements, + successMessage, +}: PromptLabProps) { + const t = useTranslations("kids.promptLab"); + const levelSlug = useLevelSlug(); + const componentId = useId(); + + const displayTitle = title || t("title"); + + const [appliedImprovements, setAppliedImprovements] = useState([]); + const [completed, setCompleted] = useState(false); + const [isLoaded, setIsLoaded] = useState(false); + + // Load saved state + useEffect(() => { + if (!levelSlug) { + setIsLoaded(true); + return; + } + const saved = getComponentState(levelSlug, componentId); + if (saved && saved.appliedImprovements && Array.isArray(saved.appliedImprovements)) { + setAppliedImprovements(saved.appliedImprovements); + setCompleted(saved.completed || false); + } + setIsLoaded(true); + }, [levelSlug, componentId]); + + // Save state + useEffect(() => { + if (!levelSlug || !isLoaded) return; + saveComponentState(levelSlug, componentId, { + appliedImprovements, + completed, + }); + }, [levelSlug, componentId, appliedImprovements, completed, isLoaded]); + + if (!isLoaded) return null; + + const handleApplyImprovement = (index: number) => { + if (appliedImprovements.includes(index) || completed) return; + + const newApplied = [...appliedImprovements, index]; + setAppliedImprovements(newApplied); + + if (newApplied.length === improvements.length) { + setCompleted(true); + } + }; + + const handleReset = () => { + setAppliedImprovements([]); + setCompleted(false); + }; + + // Get current prompt based on applied improvements + const getCurrentPrompt = () => { + if (appliedImprovements.length === 0) return basePrompt; + // Return the prompt from the highest applied improvement + const maxApplied = Math.max(...appliedImprovements); + return improvements[maxApplied].prompt; + }; + + // Get current response based on improvements + const getCurrentResponse = () => { + if (appliedImprovements.length === 0) return baseResponse; + // Return the response from the highest applied improvement + const maxApplied = Math.max(...appliedImprovements); + return improvements[maxApplied].response; + }; + + const progressPercentage = (appliedImprovements.length / improvements.length) * 100; + + return ( +
+ {/* Title */} +

+ 🔬 {displayTitle} +

+

{scenario}

+ + {/* Progress bar */} +
+
+ {t("progress")} + {appliedImprovements.length}/{improvements.length} +
+
+
+
+
+ + {/* Current prompt */} +
+
{t("yourPrompt")}
+

+ "{getCurrentPrompt()}" +

+
+ + {/* AI Response */} +
+
+ 🤖 + + {t("aiSays")} + +
+

"{getCurrentResponse()}"

+
+ + {/* Improvement buttons */} + {!completed && ( +
+
{t("addDetails")}
+ {improvements.map((improvement, index) => { + const isApplied = appliedImprovements.includes(index); + return ( + + ); + })} +
+ )} + + {/* Success message */} + {completed && ( +
+

+ 🎉 {successMessage || t("success")} +

+
+ )} + + {/* Reset button */} + {(completed || appliedImprovements.length > 0) && ( + + )} +
+ ); +} diff --git a/src/components/kids/elements/prompt-parts.tsx b/src/components/kids/elements/prompt-parts.tsx new file mode 100644 index 00000000..a28c1dd0 --- /dev/null +++ b/src/components/kids/elements/prompt-parts.tsx @@ -0,0 +1,204 @@ +"use client"; + +import { useState, useEffect, useId } from "react"; +import { useTranslations } from "next-intl"; +import { cn } from "@/lib/utils"; +import { useLevelSlug } from "@/components/kids/providers/level-context"; +import { getComponentState, saveComponentState } from "@/lib/kids/progress"; + +type PartType = "role" | "task" | "context" | "constraint"; + +interface PromptPart { + text: string; + type: PartType; +} + +interface PromptPartsProps { + title?: string; + instruction?: string; + parts: PromptPart[]; + successMessage?: string; +} + +interface SavedState { + assignments: Record; + completed: boolean; +} + +const partColors: Record = { + role: { bg: "bg-purple-100", border: "border-purple-400", text: "text-purple-700", emoji: "🎭" }, + task: { bg: "bg-blue-100", border: "border-blue-400", text: "text-blue-700", emoji: "✏️" }, + context: { bg: "bg-green-100", border: "border-green-400", text: "text-green-700", emoji: "📖" }, + constraint: { bg: "bg-orange-100", border: "border-orange-400", text: "text-orange-700", emoji: "📏" }, +}; + +export function PromptParts({ title, instruction, parts, successMessage }: PromptPartsProps) { + const t = useTranslations("kids.promptParts"); + const levelSlug = useLevelSlug(); + const componentId = useId(); + + const displayTitle = title || t("title"); + const displayInstruction = instruction || t("instruction"); + + const [assignments, setAssignments] = useState>({}); + const [selectedPart, setSelectedPart] = useState(null); + const [completed, setCompleted] = useState(false); + const [isLoaded, setIsLoaded] = useState(false); + + // Load saved state + useEffect(() => { + if (!levelSlug) { + setIsLoaded(true); + return; + } + const saved = getComponentState(levelSlug, componentId); + if (saved) { + setAssignments(saved.assignments || {}); + setCompleted(saved.completed || false); + } + setIsLoaded(true); + }, [levelSlug, componentId]); + + // Save state + useEffect(() => { + if (!levelSlug || !isLoaded) return; + saveComponentState(levelSlug, componentId, { + assignments, + completed, + }); + }, [levelSlug, componentId, assignments, completed, isLoaded]); + + if (!isLoaded) return null; + + // Check if all parts are correctly assigned + const checkCompletion = (newAssignments: Record) => { + const allAssigned = parts.every((_, index) => newAssignments[index] !== undefined && newAssignments[index] !== null); + const allCorrect = parts.every((part, index) => newAssignments[index] === part.type); + if (allAssigned && allCorrect) { + setCompleted(true); + } + }; + + const handlePartClick = (index: number) => { + if (completed) return; + setSelectedPart(selectedPart === index ? null : index); + }; + + const handleCategoryClick = (category: PartType) => { + if (completed || selectedPart === null) return; + + const newAssignments = { ...assignments, [selectedPart]: category }; + setAssignments(newAssignments); + setSelectedPart(null); + checkCompletion(newAssignments); + }; + + const handleReset = () => { + setAssignments({}); + setCompleted(false); + setSelectedPart(null); + }; + + const getAssignmentStatus = (index: number): "correct" | "wrong" | "pending" | null => { + const assigned = assignments[index]; + if (assigned === undefined || assigned === null) return null; + return assigned === parts[index].type ? "correct" : "wrong"; + }; + + const score = parts.filter((part, index) => assignments[index] === part.type).length; + + return ( +
+ {/* Title */} +

+ 🧩 {displayTitle} +

+

{displayInstruction}

+ + {/* Score */} +
+ {t("score")}: {score}/{parts.length} +
+ + {/* Prompt pieces to categorize */} +
+
+ {parts.map((part, index) => { + const status = getAssignmentStatus(index); + const isSelected = selectedPart === index; + const assigned = assignments[index]; + const colors = assigned ? partColors[assigned] : null; + + return ( + + ); + })} +
+
+ + {/* Category buttons */} + {selectedPart !== null && !completed && ( +
+
{t("pickCategory")}
+
+ {(Object.keys(partColors) as PartType[]).map((type) => { + const colors = partColors[type]; + return ( + + ); + })} +
+
+ )} + + {/* Success message */} + {completed && ( +
+

+ 🎉 {successMessage || t("success")} +

+
+ )} + + {/* Reset button */} + {(Object.keys(assignments).length > 0 || completed) && ( + + )} +
+ ); +} diff --git a/src/components/kids/elements/prompt-vs-mistake.tsx b/src/components/kids/elements/prompt-vs-mistake.tsx index 7fccbe71..cf0a8702 100644 --- a/src/components/kids/elements/prompt-vs-mistake.tsx +++ b/src/components/kids/elements/prompt-vs-mistake.tsx @@ -1,35 +1,73 @@ "use client"; -import { useState } from "react"; -import { Check, X, RefreshCw } from "lucide-react"; -import { Button } from "@/components/ui/button"; +import { useState, useEffect, useId } from "react"; +import { useTranslations } from "next-intl"; import { cn } from "@/lib/utils"; -import { PromiWithMessage } from "./character-guide"; +import { PixelRobot, PixelStar } from "./pixel-art"; +import { useLevelSlug } from "@/components/kids/providers/level-context"; +import { getComponentState, saveComponentState } from "@/lib/kids/progress"; interface PromptVsMistakeProps { question: string; good: string; bad: string; - goodLabel?: string; - badLabel?: string; explanation?: string; promiMessage?: string; } +interface SavedState { + selected: "good" | "bad" | null; + showResult: boolean; + order: string[]; +} + export function PromptVsMistake({ question, good, bad, - goodLabel = "Good prompt ✓", - badLabel = "Not so good ✗", explanation, promiMessage, }: PromptVsMistakeProps) { + const t = useTranslations("kids.quiz"); + const levelSlug = useLevelSlug(); + const componentId = useId(); + const [selected, setSelected] = useState<"good" | "bad" | null>(null); const [showResult, setShowResult] = useState(false); + const [order, setOrder] = useState([]); + const [isLoaded, setIsLoaded] = useState(false); - // Randomize order - const [order] = useState(() => Math.random() > 0.5 ? ["good", "bad"] : ["bad", "good"]); + // Load saved state on mount + useEffect(() => { + const randomOrder = Math.random() > 0.5 ? ["good", "bad"] : ["bad", "good"]; + + if (!levelSlug) { + setOrder(randomOrder); + setIsLoaded(true); + return; + } + + const saved = getComponentState(levelSlug, componentId); + if (saved && saved.order && saved.order.length > 0) { + setSelected(saved.selected); + setShowResult(saved.showResult); + setOrder(saved.order); + } else { + setOrder(randomOrder); + } + setIsLoaded(true); + }, [levelSlug, componentId]); + + // Save state when it changes + useEffect(() => { + if (!levelSlug || !isLoaded || order.length === 0) return; + + saveComponentState(levelSlug, componentId, { + selected, + showResult, + order, + }); + }, [levelSlug, componentId, selected, showResult, order, isLoaded]); const handleSelect = (choice: "good" | "bad") => { setSelected(choice); @@ -40,6 +78,9 @@ export function PromptVsMistake({ setSelected(null); setShowResult(false); }; + + // Don't render until loaded to prevent hydration mismatch + if (!isLoaded) return null; const isCorrect = selected === "good"; @@ -49,83 +90,193 @@ export function PromptVsMistake({ })); return ( -
- {/* Question */} -
-

🤔 {question}

+
+ {/* Question card with Promi */} +
+
+ +
+
+ {/* Speech bubble */} +
+ {/* Arrow pointing left */} +
+
+

+ {question} +

+
+
-
- {/* Options */} -
- {options.map(({ type, text }) => ( + {/* Choice cards - side by side for compact layout */} +
+ {options.map(({ type, text }, index) => { + const isGood = type === "good"; + + return ( - ))} -
- - {/* Result */} - {showResult && ( -
-

- {isCorrect ? "🎉 Great job!" : "🤔 Not quite!"} -

- {explanation &&

{explanation}

} -
- )} - - {/* Promi message */} - {showResult && promiMessage && ( - - )} - - {/* Reset button */} - {showResult && ( - - )} + ); + })}
+ + {/* Result feedback */} + {showResult && ( +
+

+ {isCorrect ? ( + <> {t("correct")} + ) : t("incorrect")} +

+ {explanation && ( +

{explanation}

+ )} + {promiMessage && ( +
+ +

{promiMessage}

+
+ )} + +
+ )}
); } + +// Pixel art icons +function PixelCheckIcon() { + return ( + + + + + + + + ); +} + +function PixelXIcon() { + return ( + + + + + + + + + + + ); +} + +function PixelRefreshIcon() { + return ( + + + + + + + + + + + + + + + ); +} + +function PixelThinkingIcon() { + return ( + + {/* Face circle */} + + + + + + + + + + + {/* Fill */} + + + + {/* Eyes */} + + + {/* Thinking mouth */} + + {/* Thought bubbles */} + + + + ); +} diff --git a/src/components/kids/elements/step-by-step.tsx b/src/components/kids/elements/step-by-step.tsx new file mode 100644 index 00000000..47c54ccf --- /dev/null +++ b/src/components/kids/elements/step-by-step.tsx @@ -0,0 +1,212 @@ +"use client"; + +import { useState, useEffect, useId } from "react"; +import { useTranslations } from "next-intl"; +import { cn } from "@/lib/utils"; +import { useLevelSlug } from "@/components/kids/providers/level-context"; +import { getComponentState, saveComponentState } from "@/lib/kids/progress"; + +interface StepByStepProps { + title?: string; + problem: string; + wrongAnswer: string; + steps: string[]; + rightAnswer: string; + magicWords?: string; + successMessage?: string; +} + +interface SavedState { + magicWordsAdded: boolean; + revealedSteps: number; + completed: boolean; +} + +export function StepByStep({ + title, + problem, + wrongAnswer, + steps, + rightAnswer, + magicWords = "Let's think step by step", + successMessage, +}: StepByStepProps) { + const t = useTranslations("kids.stepByStep"); + const levelSlug = useLevelSlug(); + const componentId = useId(); + + const displayTitle = title || t("title"); + + const [magicWordsAdded, setMagicWordsAdded] = useState(false); + const [revealedSteps, setRevealedSteps] = useState(0); + const [completed, setCompleted] = useState(false); + const [isLoaded, setIsLoaded] = useState(false); + + // Load saved state + useEffect(() => { + if (!levelSlug) { + setIsLoaded(true); + return; + } + const saved = getComponentState(levelSlug, componentId); + if (saved && typeof saved.magicWordsAdded === 'boolean') { + setMagicWordsAdded(saved.magicWordsAdded); + setRevealedSteps(saved.revealedSteps || 0); + setCompleted(saved.completed || false); + } + setIsLoaded(true); + }, [levelSlug, componentId]); + + // Save state + useEffect(() => { + if (!levelSlug || !isLoaded) return; + saveComponentState(levelSlug, componentId, { + magicWordsAdded, + revealedSteps, + completed, + }); + }, [levelSlug, componentId, magicWordsAdded, revealedSteps, completed, isLoaded]); + + if (!isLoaded) return null; + + const handleAddMagicWords = () => { + setMagicWordsAdded(true); + }; + + const handleRevealNextStep = () => { + if (revealedSteps < steps.length) { + const newRevealed = revealedSteps + 1; + setRevealedSteps(newRevealed); + if (newRevealed === steps.length) { + setCompleted(true); + } + } + }; + + const handleReset = () => { + setMagicWordsAdded(false); + setRevealedSteps(0); + setCompleted(false); + }; + + return ( +
+ {/* Title */} +

+ 🧠 {displayTitle} +

+ + {/* Problem */} +
+
{t("problem")}
+

{problem}

+
+ + {/* Wrong answer (before magic words) */} + {!magicWordsAdded && ( +
+
+ 😕 + {t("withoutMagic")} +
+

{wrongAnswer}

+
+ )} + + {/* Magic words button */} + {!magicWordsAdded && ( + + )} + + {/* Steps revealed after magic words */} + {magicWordsAdded && ( + <> +
+
+ + {t("magicWordsActive")} +
+

"{magicWords}"

+
+ + {/* Steps */} +
+ {steps.map((step, index) => { + const isRevealed = index < revealedSteps; + return ( +
+
+ + {isRevealed ? "✓" : index + 1} + + + {isRevealed ? step : "???"} + +
+
+ ); + })} +
+ + {/* Reveal next step button */} + {!completed && ( + + )} + + {/* Correct answer revealed */} + {completed && ( +
+
+ 🎉 + {t("withMagic")} +
+

{rightAnswer}

+ {successMessage && ( +

{successMessage}

+ )} +
+ )} + + )} + + {/* Reset button */} + {(magicWordsAdded || completed) && ( + + )} +
+ ); +} diff --git a/src/components/kids/elements/story-scene.tsx b/src/components/kids/elements/story-scene.tsx index 4e527afc..358bccd2 100644 --- a/src/components/kids/elements/story-scene.tsx +++ b/src/components/kids/elements/story-scene.tsx @@ -1,10 +1,8 @@ "use client"; import { useState } from "react"; -import { ChevronLeft, ChevronRight } from "lucide-react"; -import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; -import { PromiCharacter } from "./character-guide"; +import { PixelRobot } from "./pixel-art"; type PromiMood = "happy" | "thinking" | "excited" | "confused" | "celebrating"; @@ -27,66 +25,62 @@ export function StoryScene({ panels, className }: StorySceneProps) { const isLast = currentPanel === panels.length - 1; return ( -
+
{/* Story panel */} -
+
{panel.character === "promi" && (
- +
)}
-

{panel.text}

+

{panel.text}

- {/* Navigation */} + {/* Navigation - pixel style */} {panels.length > 1 && ( -
- + - {/* Progress dots */} + {/* Progress dots - pixel style */}
{panels.map((_, i) => (
- +
)}
@@ -102,21 +96,22 @@ interface SinglePanelProps { export function Panel({ character = "promi", mood = "happy", children, highlight }: SinglePanelProps) { return ( -
-
+
+
{character === "promi" && (
- +
)}
-
{children}
+
{children}
diff --git a/src/components/kids/elements/word-predictor.tsx b/src/components/kids/elements/word-predictor.tsx new file mode 100644 index 00000000..fce787ac --- /dev/null +++ b/src/components/kids/elements/word-predictor.tsx @@ -0,0 +1,204 @@ +"use client"; + +import { useState, useEffect, useId } from "react"; +import { useTranslations } from "next-intl"; +import { cn } from "@/lib/utils"; +import { useLevelSlug } from "@/components/kids/providers/level-context"; +import { getComponentState, saveComponentState } from "@/lib/kids/progress"; + +interface WordPredictorProps { + title?: string; + instruction?: string; + sentence: string; + options: string[]; + correctAnswer: string; + explanation: string; + aiThinking?: string; + successMessage?: string; +} + +interface SavedState { + selectedAnswer: string | null; + submitted: boolean; +} + +export function WordPredictor({ + title, + instruction, + sentence, + options, + correctAnswer, + explanation, + aiThinking, + successMessage, +}: WordPredictorProps) { + const t = useTranslations("kids.wordPredictor"); + const levelSlug = useLevelSlug(); + const componentId = useId(); + + const displayTitle = title || t("title"); + const displayInstruction = instruction || t("instruction"); + + const [selectedAnswer, setSelectedAnswer] = useState(null); + const [submitted, setSubmitted] = useState(false); + const [isLoaded, setIsLoaded] = useState(false); + + // Load saved state + useEffect(() => { + if (!levelSlug) { + setIsLoaded(true); + return; + } + const saved = getComponentState(levelSlug, componentId); + if (saved && typeof saved.submitted === "boolean") { + setSelectedAnswer(saved.selectedAnswer); + setSubmitted(saved.submitted); + } + setIsLoaded(true); + }, [levelSlug, componentId]); + + // Save state + useEffect(() => { + if (!levelSlug || !isLoaded) return; + saveComponentState(levelSlug, componentId, { + selectedAnswer, + submitted, + }); + }, [levelSlug, componentId, selectedAnswer, submitted, isLoaded]); + + if (!isLoaded) return null; + + const isCorrect = selectedAnswer === correctAnswer; + + const handleSelect = (option: string) => { + if (submitted) return; + setSelectedAnswer(option); + }; + + const handleSubmit = () => { + if (!selectedAnswer) return; + setSubmitted(true); + }; + + const handleReset = () => { + setSelectedAnswer(null); + setSubmitted(false); + }; + + // Render sentence with blank + const renderSentence = () => { + const parts = sentence.split("___"); + return ( + + {parts[0]} + + {selectedAnswer || "???"} + + {parts[1]} + + ); + }; + + return ( +
+ {/* Title */} +

+ 🧠 {displayTitle} +

+

{displayInstruction}

+ + {/* AI Brain visualization */} +
+
+ 🤖 + {t("aiThinks")} +
+

+ {renderSentence()} +

+
+ + {/* Thinking bubble */} + {!submitted && ( +
+ 💭 {aiThinking || t("thinkingDefault")} +
+ )} + + {/* Options */} +
+ {options.map((option, index) => { + const isSelected = selectedAnswer === option; + const showCorrect = submitted && option === correctAnswer; + const showWrong = submitted && isSelected && !isCorrect; + + return ( + + ); + })} +
+ + {/* Submit button */} + {!submitted && ( + + )} + + {/* Result */} + {submitted && ( +
+

+ {isCorrect ? `🎉 ${successMessage || t("correct")}` : `🤔 ${t("tryAgain")}`} +

+

{explanation}

+
+ )} + + {/* Reset button */} + {submitted && ( + + )} +
+ ); +} diff --git a/src/components/kids/layout/background-music.tsx b/src/components/kids/layout/background-music.tsx new file mode 100644 index 00000000..04eaed14 --- /dev/null +++ b/src/components/kids/layout/background-music.tsx @@ -0,0 +1,347 @@ +"use client"; + +import { useState, useRef, useCallback } from "react"; + +// Pixel art speaker icons +function PixelSpeakerOn() { + return ( + + + + + + + + + ); +} + +function PixelSpeakerOff() { + return ( + + + + + + + + + + ); +} + +// 8-bit chiptune music generator using Web Audio API +class ChiptunePlayer { + private audioContext: AudioContext | null = null; + private masterGain: GainNode | null = null; + private isPlaying = false; + private intervalId: number | null = null; + private step = 0; + + // Fun bouncy 8-bit melody - playful and catchy! + private melody = [ + // Part 1: Bouncy intro + 523.25, 0, 659.25, 0, 783.99, 0, 659.25, 0, // C5 - E5 - G5 - E5 (bouncy) + 698.46, 0, 783.99, 0, 880.00, 783.99, 659.25, 0, // F5 - G5 - A5 G5 E5 (climb up!) + // Part 2: Silly descending + 783.99, 698.46, 659.25, 587.33, 523.25, 0, 392.00, 0, // G5 F5 E5 D5 C5 - G4 (slide down) + 440.00, 493.88, 523.25, 0, 659.25, 0, 523.25, 0, // A4 B4 C5 - E5 - C5 (pop back up) + // Part 3: Playful jumps + 392.00, 523.25, 392.00, 523.25, 659.25, 783.99, 659.25, 0, // G4 C5 G4 C5 E5 G5 E5 (jumping!) + 880.00, 0, 783.99, 0, 659.25, 523.25, 587.33, 659.25, // A5 - G5 - E5 C5 D5 E5 + // Part 4: Fun ending + 783.99, 0, 659.25, 0, 523.25, 587.33, 659.25, 783.99, // G5 - E5 - C5 D5 E5 G5 + 880.00, 783.99, 659.25, 523.25, 392.00, 0, 523.25, 0, // A5 G5 E5 C5 G4 - C5 (finish!) + ]; + + // Funky bass line - groovy! + private bass = [ + // Part 1 + 130.81, 0, 130.81, 164.81, 196.00, 0, 164.81, 0, // C3 - C3 E3 G3 - E3 + 174.61, 0, 196.00, 0, 220.00, 196.00, 164.81, 0, // F3 - G3 - A3 G3 E3 + // Part 2 + 196.00, 174.61, 164.81, 146.83, 130.81, 0, 98.00, 0, // G3 F3 E3 D3 C3 - G2 + 110.00, 123.47, 130.81, 0, 164.81, 0, 130.81, 0, // A2 B2 C3 - E3 - C3 + // Part 3 + 98.00, 130.81, 98.00, 130.81, 164.81, 196.00, 164.81, 0, // G2 C3 G2 C3 E3 G3 E3 + 220.00, 0, 196.00, 0, 164.81, 130.81, 146.83, 164.81, // A3 - G3 - E3 C3 D3 E3 + // Part 4 + 196.00, 0, 164.81, 0, 130.81, 146.83, 164.81, 196.00, // G3 - E3 - C3 D3 E3 G3 + 220.00, 196.00, 164.81, 130.81, 98.00, 0, 130.81, 0, // A3 G3 E3 C3 G2 - C3 + ]; + + async start() { + if (this.isPlaying) return; + + try { + this.audioContext = new (window.AudioContext || (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext)(); + + // Resume audio context if suspended (required by browsers) + if (this.audioContext.state === "suspended") { + await this.audioContext.resume(); + } + + this.masterGain = this.audioContext.createGain(); + this.masterGain.gain.value = 0.2; + this.masterGain.connect(this.audioContext.destination); + this.isPlaying = true; + this.step = 0; + + // Play notes at upbeat tempo + this.intervalId = window.setInterval(() => this.playStep(), 150); + } catch (error) { + console.error("Failed to start audio:", error); + } + } + + private playStep() { + if (!this.audioContext || !this.masterGain) return; + + const now = this.audioContext.currentTime; + const noteIndex = this.step % this.melody.length; + + // Play melody (square wave for 8-bit sound) - skip if 0 (rest) + if (this.melody[noteIndex] > 0) { + this.playNote(this.melody[noteIndex], now, 0.12, "square", 0.12); + } + + // Play bass (triangle wave) - louder and deeper, skip if 0 + if (this.bass[noteIndex] > 0) { + this.playNote(this.bass[noteIndex], now, 0.14, "triangle", 0.15); + // Add sub-bass for extra punch + this.playNote(this.bass[noteIndex] / 2, now, 0.14, "sine", 0.08); + } + + // Aggressive dubstep-style percussion + if (this.step % 8 === 0) { + this.playDrum(now, "kick"); + this.playDrum(now + 0.15, "kick"); // Double kick + } else if (this.step % 8 === 4) { + this.playDrum(now, "snare"); + } else if (this.step % 2 === 1) { + this.playDrum(now, "hihat"); + } + + // Wobble bass on every other beat for dubstep feel + if (this.step % 4 === 2) { + this.playWobble(now); + } + + this.step++; + } + + private playNote(freq: number, time: number, duration: number, type: OscillatorType, volume: number) { + if (!this.audioContext || !this.masterGain) return; + + const osc = this.audioContext.createOscillator(); + const gain = this.audioContext.createGain(); + + osc.type = type; + osc.frequency.value = freq; + + gain.gain.setValueAtTime(volume, time); + gain.gain.exponentialRampToValueAtTime(0.001, time + duration); + + osc.connect(gain); + gain.connect(this.masterGain); + + osc.start(time); + osc.stop(time + duration); + } + + private playDrum(time: number, type: "kick" | "hihat" | "snare" = "hihat") { + if (!this.audioContext || !this.masterGain) return; + + if (type === "kick") { + // Heavy dubstep kick - deep and punchy + const osc = this.audioContext.createOscillator(); + const gain = this.audioContext.createGain(); + + osc.type = "sine"; + osc.frequency.setValueAtTime(180, time); + osc.frequency.exponentialRampToValueAtTime(30, time + 0.12); + + gain.gain.setValueAtTime(0.5, time); + gain.gain.exponentialRampToValueAtTime(0.001, time + 0.2); + + osc.connect(gain); + gain.connect(this.masterGain); + + osc.start(time); + osc.stop(time + 0.2); + + // Add click for attack + const click = this.audioContext.createOscillator(); + const clickGain = this.audioContext.createGain(); + click.type = "square"; + click.frequency.value = 800; + clickGain.gain.setValueAtTime(0.15, time); + clickGain.gain.exponentialRampToValueAtTime(0.001, time + 0.02); + click.connect(clickGain); + clickGain.connect(this.masterGain); + click.start(time); + click.stop(time + 0.02); + + } else if (type === "snare") { + // Aggressive dubstep snare - noise + tone + const bufferSize = this.audioContext.sampleRate * 0.15; + const buffer = this.audioContext.createBuffer(1, bufferSize, this.audioContext.sampleRate); + const data = buffer.getChannelData(0); + + for (let i = 0; i < bufferSize; i++) { + data[i] = Math.random() * 2 - 1; + } + + const noise = this.audioContext.createBufferSource(); + noise.buffer = buffer; + + const noiseGain = this.audioContext.createGain(); + noiseGain.gain.setValueAtTime(0.3, time); + noiseGain.gain.exponentialRampToValueAtTime(0.001, time + 0.15); + + const filter = this.audioContext.createBiquadFilter(); + filter.type = "bandpass"; + filter.frequency.value = 3000; + filter.Q.value = 1; + + noise.connect(filter); + filter.connect(noiseGain); + noiseGain.connect(this.masterGain); + + noise.start(time); + noise.stop(time + 0.15); + + // Add tone body + const tone = this.audioContext.createOscillator(); + const toneGain = this.audioContext.createGain(); + tone.type = "triangle"; + tone.frequency.setValueAtTime(200, time); + tone.frequency.exponentialRampToValueAtTime(100, time + 0.05); + toneGain.gain.setValueAtTime(0.2, time); + toneGain.gain.exponentialRampToValueAtTime(0.001, time + 0.08); + tone.connect(toneGain); + toneGain.connect(this.masterGain); + tone.start(time); + tone.stop(time + 0.08); + + } else { + // Hi-hat - crispy noise + const bufferSize = this.audioContext.sampleRate * 0.04; + const buffer = this.audioContext.createBuffer(1, bufferSize, this.audioContext.sampleRate); + const data = buffer.getChannelData(0); + + for (let i = 0; i < bufferSize; i++) { + data[i] = Math.random() * 2 - 1; + } + + const noise = this.audioContext.createBufferSource(); + noise.buffer = buffer; + + const gain = this.audioContext.createGain(); + gain.gain.setValueAtTime(0.08, time); + gain.gain.exponentialRampToValueAtTime(0.001, time + 0.04); + + const filter = this.audioContext.createBiquadFilter(); + filter.type = "highpass"; + filter.frequency.value = 9000; + + noise.connect(filter); + filter.connect(gain); + gain.connect(this.masterGain); + + noise.start(time); + noise.stop(time + 0.04); + } + } + + private playWobble(time: number) { + if (!this.audioContext || !this.masterGain) return; + + // Classic dubstep wobble bass + const osc = this.audioContext.createOscillator(); + const gain = this.audioContext.createGain(); + const lfo = this.audioContext.createOscillator(); + const lfoGain = this.audioContext.createGain(); + + osc.type = "sawtooth"; + osc.frequency.value = 55; // Low A + + // LFO for wobble effect + lfo.type = "sine"; + lfo.frequency.value = 8; // Wobble speed + lfoGain.gain.value = 400; + + lfo.connect(lfoGain); + + // Create filter for wobble + const filter = this.audioContext.createBiquadFilter(); + filter.type = "lowpass"; + filter.frequency.value = 400; + filter.Q.value = 8; + + lfoGain.connect(filter.frequency); + + gain.gain.setValueAtTime(0.2, time); + gain.gain.exponentialRampToValueAtTime(0.001, time + 0.3); + + osc.connect(filter); + filter.connect(gain); + gain.connect(this.masterGain); + + lfo.start(time); + osc.start(time); + lfo.stop(time + 0.3); + osc.stop(time + 0.3); + } + + stop() { + if (this.intervalId) { + clearInterval(this.intervalId); + this.intervalId = null; + } + if (this.audioContext) { + this.audioContext.close(); + this.audioContext = null; + } + this.isPlaying = false; + } + + getIsPlaying() { + return this.isPlaying; + } +} + +export function MusicButton() { + const [isPlaying, setIsPlaying] = useState(false); + const playerRef = useRef(null); + + const toggleMusic = useCallback(async () => { + if (!playerRef.current) { + playerRef.current = new ChiptunePlayer(); + } + + if (isPlaying) { + playerRef.current.stop(); + setIsPlaying(false); + } else { + await playerRef.current.start(); + setIsPlaying(true); + } + }, [isPlaying]); + + return ( + + ); +} + +// Legacy export for backwards compatibility +export function BackgroundMusic() { + return null; +} diff --git a/src/components/kids/layout/kids-header.tsx b/src/components/kids/layout/kids-header.tsx index bbf53ab4..cac46b6c 100644 --- a/src/components/kids/layout/kids-header.tsx +++ b/src/components/kids/layout/kids-header.tsx @@ -2,17 +2,24 @@ import Link from "next/link"; import { useTranslations } from "next-intl"; -import { Home, Map, Star } from "lucide-react"; -import { Button } from "@/components/ui/button"; import { useEffect, useState } from "react"; import { getTotalStars, getCompletedLevelsCount } from "@/lib/kids/progress"; -import { getTotalLevels } from "@/lib/kids/levels"; +import { getTotalLevels, getLevelBySlug } from "@/lib/kids/levels"; +import { PixelStar, PixelRobot } from "@/components/kids/elements/pixel-art"; +import { MusicButton } from "./background-music"; +import { SettingsButton } from "./settings-modal"; +import { useLevelSlug } from "@/components/kids/providers/level-context"; export function KidsHeader() { const t = useTranslations("kids"); const [stars, setStars] = useState(0); const [completed, setCompleted] = useState(0); const total = getTotalLevels(); + + // Get current level from context (will be empty if not in a level) + const levelSlug = useLevelSlug(); + const currentLevel = levelSlug ? getLevelBySlug(levelSlug) : null; + const levelNumber = currentLevel ? `${currentLevel.world}.${currentLevel.levelNumber}` : null; useEffect(() => { setStars(getTotalStars()); @@ -20,54 +27,97 @@ export function KidsHeader() { }, []); return ( -
-
+
+
{/* Logo */} - - 🤖 - + + + {t("header.title")} {/* Stats & Nav */} -
+
+ {/* Current level indicator */} + {levelNumber && ( +
+ + {t("level.levelLabel", { number: levelNumber })} + +
+ )} + {/* Stars counter */} -
- - {stars} +
+ + {stars}
{/* Progress */} -
- {completed}/{total} - {t("header.levels")} +
+ {completed}/{total}
{/* Nav buttons */}
- - -
- - {/* Back to main site */} - + + + + {/* Back to main site */} + + {t("header.mainSite")} + +
); } + +// Pixel art home icon +function PixelHomeIcon() { + return ( + + + + + + + + + ); +} + +// Pixel art pin/location icon +function PixelMapIcon() { + return ( + + {/* Pin head - circle */} + + + + + + {/* Pin point */} + + + {/* Inner highlight */} + + + ); +} diff --git a/src/components/kids/layout/kids-home-content.tsx b/src/components/kids/layout/kids-home-content.tsx new file mode 100644 index 00000000..10b0076b --- /dev/null +++ b/src/components/kids/layout/kids-home-content.tsx @@ -0,0 +1,252 @@ +"use client"; + +import { useState } from "react"; +import Link from "next/link"; +import { useTranslations } from "next-intl"; +import { cn } from "@/lib/utils"; +import { analyticsKids } from "@/lib/analytics"; +import { PixelRobot, PixelStar, PixelTree, PixelCastle } from "@/components/kids/elements/pixel-art"; + +export function KidsHomeContent() { + const t = useTranslations("kids"); + const [step, setStep] = useState(0); + const totalSteps = 3; + + const nextStep = () => setStep((prev) => Math.min(prev + 1, totalSteps - 1)); + const prevStep = () => setStep((prev) => Math.max(prev - 1, 0)); + + return ( +
+ {/* Main content area */} +
+
+ {/* Step 0: Welcome */} + {step === 0 && ( +
+
+ + {t("home.badge")} +
+ +

+ {t("home.title")} +

+ +

+ {t("home.subtitle")} +

+ +
+
+
+ +
+
+

{t("home.promiIntro.greeting")}

+

+ {t("home.promiIntro.message")} +

+
+
+
+
+ )} + + {/* Step 1: Features */} + {step === 1 && ( +
+

+ {t("home.whatYouLearn")} +

+ +
+
+ +
+

{t("home.features.games.title")}

+

{t("home.features.games.description")}

+
+
+
+ +
+

{t("home.features.stories.title")}

+

{t("home.features.stories.description")}

+
+
+
+
+ + + +
+
+

{t("home.features.stars.title")}

+

{t("home.features.stars.description")}

+
+
+
+
+ )} + + {/* Step 2: Ready to start */} + {step === 2 && ( +
+
+ + + +
+ +

+ {t("home.readyTitle")} +

+ +

+ {t("home.readyMessage")} +

+ + analyticsKids.startGame()} + className="inline-block pixel-btn pixel-btn-green text-xl md:text-2xl px-8 py-4" + > + + + {t("home.startButton")} + + + +

+ {t("home.ageNote")} +

+
+ )} +
+
+ + {/* Navigation footer - pixel art style */} +
+
+ {/* Back button */} + + + {/* Step indicators - pixel style */} +
+ {Array.from({ length: totalSteps }).map((_, i) => ( +
+ + {/* Next button */} + {step < totalSteps - 1 ? ( + + ) : ( + + + + {t("home.startButton")} + + + )} +
+
+
+ ); +} + +// Pixel art icons +function PixelPlayIcon() { + return ( + + + + + + + ); +} + +function PixelArrowLeft() { + return ( + + + + + + + ); +} + +function PixelArrowRight() { + return ( + + + + + + + ); +} + +function PixelGamepad() { + return ( + + + + + + + + + + ); +} + +function PixelBook() { + return ( + + + + + + + + + + ); +} diff --git a/src/components/kids/layout/level-content-wrapper.tsx b/src/components/kids/layout/level-content-wrapper.tsx new file mode 100644 index 00000000..a5272d17 --- /dev/null +++ b/src/components/kids/layout/level-content-wrapper.tsx @@ -0,0 +1,217 @@ +"use client"; + +import { useState, Children, isValidElement, ReactNode, ReactElement, useEffect } from "react"; +import { cn } from "@/lib/utils"; +import Link from "next/link"; +import { useTranslations } from "next-intl"; +import { Section } from "@/components/kids/elements"; +import { useSetLevelSlug } from "@/components/kids/providers/level-context"; +import { getLevelBySlug } from "@/lib/kids/levels"; +import { analyticsKids } from "@/lib/analytics"; + +interface LevelContentWrapperProps { + children: ReactNode; + levelSlug: string; + levelNumber: string; +} + +export function LevelContentWrapper({ children, levelSlug, levelNumber }: LevelContentWrapperProps) { + const t = useTranslations("kids"); + const [currentSection, setCurrentSection] = useState(0); + const setLevelSlug = useSetLevelSlug(); + + // Set the level slug in context when component mounts + useEffect(() => { + setLevelSlug(levelSlug); + + // Track level view + const level = getLevelBySlug(levelSlug); + if (level) { + analyticsKids.viewLevel(levelSlug, level.world); + } + + return () => setLevelSlug(""); // Clear when unmounting + }, [levelSlug, setLevelSlug]); + + // Extract Section components from children + const sections: ReactElement[] = []; + let hasExplicitSections = false; + + // First pass: check if there are explicit Section components + Children.forEach(children, (child) => { + if (isValidElement(child) && child.type === Section) { + hasExplicitSections = true; + } + }); + + // Second pass: collect sections + if (hasExplicitSections) { + Children.forEach(children, (child) => { + if (isValidElement(child) && child.type === Section) { + sections.push(child); + } + }); + } else { + Children.forEach(children, (child) => { + if (isValidElement(child)) { + sections.push(
{child}
); + } + }); + } + + // If no sections found, show coming soon + if (sections.length === 0) { + return ( +
+
+

{t("level.comingSoon")}

+ + + {t("level.backToMap")} + +
+
+ ); + } + + const totalSections = sections.length; + const isFirstSection = currentSection === 0; + const isLastSection = currentSection === totalSections - 1; + + const goToNext = () => { + if (!isLastSection) { + setCurrentSection((prev) => prev + 1); + } + }; + + const goToPrev = () => { + if (!isFirstSection) { + setCurrentSection((prev) => prev - 1); + } + }; + + // Reset to first section when level changes + useEffect(() => { + setCurrentSection(0); + }, [levelSlug]); + + return ( +
+ {/* Content area */} +
+
+
+ {sections[currentSection]} +
+
+
+ + {/* Navigation footer - pixel art style */} +
+
+ {/* Back button */} + + + {/* Progress indicators - pixel style */} +
+ {Array.from({ length: totalSections }).map((_, i) => ( +
+ + {/* Next button or Map link */} + {!isLastSection ? ( + + ) : ( + + + + {t("level.map")} + + + )} +
+
+
+ ); +} + +// Pixel art icons +function PixelArrowLeft() { + return ( + + + + + + + ); +} + +function PixelArrowRight() { + return ( + + + + + + + ); +} + +function PixelMapIcon() { + return ( + + {/* Pin head - circle */} + + + + + + {/* Pin point */} + + + {/* Inner highlight */} + + + ); +} diff --git a/src/components/kids/layout/settings-modal.tsx b/src/components/kids/layout/settings-modal.tsx new file mode 100644 index 00000000..aec630f1 --- /dev/null +++ b/src/components/kids/layout/settings-modal.tsx @@ -0,0 +1,210 @@ +"use client"; + +import { useState } from "react"; +import { useTranslations, useLocale } from "next-intl"; +import { cn } from "@/lib/utils"; +import { clearAllProgress, getTotalStars, getCompletedLevelsCount } from "@/lib/kids/progress"; +import { setLocale } from "@/lib/i18n/client"; +import { analyticsKids } from "@/lib/analytics"; +import { Settings, X, Globe, Trash2, Check } from "lucide-react"; + +const SUPPORTED_LOCALES = [ + { code: "en", label: "English", flag: "🇺🇸" }, + { code: "zh", label: "中文", flag: "🇨🇳" }, + { code: "es", label: "Español", flag: "🇪🇸" }, + { code: "pt", label: "Português", flag: "🇧🇷" }, + { code: "fr", label: "Français", flag: "🇫🇷" }, + { code: "de", label: "Deutsch", flag: "🇩🇪" }, + { code: "it", label: "Italiano", flag: "🇮🇹" }, + { code: "ja", label: "日本語", flag: "🇯🇵" }, + { code: "tr", label: "Türkçe", flag: "🇹🇷" }, + { code: "az", label: "Azərbaycan", flag: "🇦🇿" }, + { code: "ko", label: "한국어", flag: "🇰🇷" }, + { code: "ar", label: "العربية", flag: "🇸🇦" }, + { code: "fa", label: "فارسی", flag: "🇮🇷" }, + { code: "ru", label: "Русский", flag: "🇷🇺" }, + { code: "he", label: "עברית", flag: "🇮🇱" }, + { code: "el", label: "Ελληνικά", flag: "🇬🇷" }, +]; + +export function SettingsButton() { + const [isOpen, setIsOpen] = useState(false); + + return ( + <> + + + {isOpen && setIsOpen(false)} />} + + ); +} + +function SettingsModal({ onClose }: { onClose: () => void }) { + const t = useTranslations("kids.settings"); + const currentLocale = useLocale(); + const [showResetConfirm, setShowResetConfirm] = useState(false); + const [resetComplete, setResetComplete] = useState(false); + + const stars = getTotalStars(); + const completed = getCompletedLevelsCount(); + + const handleLanguageChange = (locale: string) => { + analyticsKids.changeLanguage(locale); + setLocale(locale); + }; + + const handleResetProgress = () => { + if (!showResetConfirm) { + setShowResetConfirm(true); + return; + } + + clearAllProgress(); + analyticsKids.resetProgress(); + setResetComplete(true); + setShowResetConfirm(false); + + // Reload to reflect changes + setTimeout(() => { + window.location.reload(); + }, 1000); + }; + + return ( +
+ {/* Backdrop */} +
+ + {/* Modal */} +
+ {/* Close button */} + + + {/* Title */} +

+ + {t("title")} +

+ + {/* Language Section */} +
+

+ + {t("language")} +

+
+ {SUPPORTED_LOCALES.map((locale) => ( + + ))} +
+
+ + {/* Progress Info */} +
+

+ {t("progress")} +

+
+
+ ⭐ {stars} +
{t("stars")}
+
+
+ ✓ {completed} +
{t("completed")}
+
+
+
+ + {/* Reset Progress */} +
+

+ + {t("resetTitle")} +

+ + {resetComplete ? ( +
+ + {t("resetComplete")} +
+ ) : showResetConfirm ? ( +
+

+ {t("resetWarning")} +

+
+ + +
+
+ ) : ( + + )} +
+
+
+ ); +} + +// Pixel art settings/gear icon +function PixelSettingsIcon() { + return ( + + + + + + + + + + + + + ); +} diff --git a/src/components/kids/providers/level-context.tsx b/src/components/kids/providers/level-context.tsx new file mode 100644 index 00000000..a4f6f340 --- /dev/null +++ b/src/components/kids/providers/level-context.tsx @@ -0,0 +1,46 @@ +"use client"; + +import { createContext, useContext, useState, useEffect, ReactNode } from "react"; + +interface LevelContextType { + levelSlug: string; + setLevelSlug: (slug: string) => void; +} + +const LevelContext = createContext({ + levelSlug: "", + setLevelSlug: () => {}, +}); + +export function LevelProvider({ + children, + levelSlug: initialSlug = "" +}: { + children: ReactNode; + levelSlug?: string; +}) { + const [levelSlug, setLevelSlug] = useState(initialSlug); + + // Update if initialSlug changes + useEffect(() => { + if (initialSlug) { + setLevelSlug(initialSlug); + } + }, [initialSlug]); + + return ( + + {children} + + ); +} + +export function useLevelSlug(): string { + const context = useContext(LevelContext); + return context.levelSlug; +} + +export function useSetLevelSlug(): (slug: string) => void { + const context = useContext(LevelContext); + return context.setLevelSlug; +} diff --git a/src/content/kids/ar/1-1-meet-promi.mdx b/src/content/kids/ar/1-1-meet-promi.mdx index bc6014d1..aeb144ac 100644 --- a/src/content/kids/ar/1-1-meet-promi.mdx +++ b/src/content/kids/ar/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
مرحباً! أنا **Promi** 🤖، صديقك الروبوت! سعيد جداً بلقائك! @@ -9,7 +10,9 @@ أنا ذكاء اصطناعي! يمكنني قراءة رسائلك ومحاولة مساعدتك. لكن هناك سر... أحتاج **تعليمات جيدة** لأقوم بأفضل عمل! +
+
## ما هو البرومبت؟ **البرومبت** هو كلمة راقية للرسالة التي ترسلها لذكاء اصطناعي مثلي. @@ -19,7 +22,9 @@ عندما تكتب برومبت جيد، أستطيع فهم ما تريد ومساعدتك بشكل أفضل! هيا نتدرب! +
+
## لنجرب! +
+
## اختبار سريع! +
+
## نجحت! 🎉 عمل رائع! تعلمت ما هو الذكاء الاصطناعي وما هو البرومبت. أنت تصبح خبيراً في البرومبت! + +
+ diff --git a/src/content/kids/ar/1-2-first-words.mdx b/src/content/kids/ar/1-2-first-words.mdx index 43820cc8..3589594c 100644 --- a/src/content/kids/ar/1-2-first-words.mdx +++ b/src/content/kids/ar/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
مرحباً بعودتك يا صديقي! مستعد لكتابة أول برومبت حقيقي؟ هيا بنا! 🚀 +
+
## سحر الكلمات عندما تتحدث مع الذكاء الاصطناعي، كل كلمة مهمة! دعنا نرى كيف إضافة المزيد من الكلمات تجعل البرومبت أفضل. @@ -9,7 +12,9 @@ انظر! إذا قال لي شخص فقط "قطة"، لا أعرف ماذا يريدون. هل يريدون صورة؟ قصة؟ حقائق عن القطط؟ أنا مرتبك! 😵‍💫 +
+
## بناء برومبت أفضل البرومبت الجيد له **ثلاثة أجزاء**: @@ -21,7 +26,9 @@ هيا نبني برومبت معاً! +
+
## اسحب القطع! +
+
## املأ الفراغات! الآن حاول صنع برومبتك بسحب الكلمات السحرية: + +
+
## دورك للاختيار! +
+
## عمل رائع! 🌟 كتبت أول برومبت لك! تعلمت أن البرومبت الجيد يحتاج: ما تريد، موضوع، وتفاصيل. أنت تتحسن! + +
+ diff --git a/src/content/kids/ar/1-3-being-clear.mdx b/src/content/kids/ar/1-3-being-clear.mdx index c6f57836..6ea4c4ee 100644 --- a/src/content/kids/ar/1-3-being-clear.mdx +++ b/src/content/kids/ar/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
مرحباً يا نجم! 🌟 اليوم سنتعلم أهم مهارة: أن تكون **واضحاً**! +
+
## لماذا الوضوح مهم تخيل أن تطلب من أمك "طعام" مقابل طلب "ساندويتش زبدة فول سوداني بدون قشرة." أيهما يعطيك بالضبط ما تريد؟ @@ -9,11 +12,14 @@ معي نفس الشيء! عندما تكون واضحاً، أعرف بالضبط كيف أساعد. عندما تكون غامضاً، علي أن أخمن... وقد أخمن خطأ! +
+
## واضح مقابل غير واضح هيا نتدرب على اكتشاف الفرق! + + +
+
## تحدي الوضوح هيا نبني أوضح برومبت على الإطلاق! + +
+
## أضف تفاصيل واضحة +
+
## القواعد الذهبية للوضوح @@ -74,6 +88,7 @@ 2. **كيف** يجب أن يكون؟ (قصير، مضحك، بسيط) 3. **لمن** هو؟ (أنا، صديقي، صفي) + +
+
## العالم 1 اكتمل! 🎊 @@ -94,8 +111,11 @@ أنت جاهز لمغامرات جديدة! + +
+ diff --git a/src/content/kids/az/1-1-meet-promi.mdx b/src/content/kids/az/1-1-meet-promi.mdx index 8cf1e564..4e389e1d 100644 --- a/src/content/kids/az/1-1-meet-promi.mdx +++ b/src/content/kids/az/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
Salam! Mən **Promi** 🤖, sənin robot dostun! Səninlə tanış olmağıma çox şadam! @@ -9,7 +10,9 @@ Salam! Mən **Promi** 🤖, sənin robot dostun! Səninlə tanış olmağıma ç Mən AI-yam! Sənin mesajlarını oxuya və kömək etməyə çalışa bilərəm. Amma budur sirr... Ən yaxşı işi görmək üçün **yaxşı təlimatlara** ehtiyacım var! +
+
## Prompt Nədir? **Prompt** sadəcə mənim kimi AI-ya göndərdiyin mesaj deməkdir. @@ -19,7 +22,9 @@ Bunu dostuna yol göstərmək kimi düşün. "Ora get!" desən, dostun hara getm Yaxşı prompt yazdığında, nə istədiyini başa düşə və sənə daha yaxşı kömək edə bilərəm! Gəl məşq edək! +
+
## Gəl Cəhd Edək! +
+
## Sürətli Test! +
+
## Bacardın! 🎉 Əla iş! AI-ın nə olduğunu və promptun nə olduğunu öyrəndin. Artıq prompt mütəxəssisi olursan! + +
+ diff --git a/src/content/kids/az/1-2-first-words.mdx b/src/content/kids/az/1-2-first-words.mdx index 6cf2e6ff..5e3dd44b 100644 --- a/src/content/kids/az/1-2-first-words.mdx +++ b/src/content/kids/az/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
Xoş gəldin geri, dost! İlk əsl promptlarını yazmağa hazırsan? Gedək! 🚀 +
+
## Sözlərin Sehri AI ilə danışanda hər söz önəmlidir! Gəl görək daha çox söz əlavə etmək promptları necə yaxşılaşdırır. @@ -9,7 +12,9 @@ AI ilə danışanda hər söz önəmlidir! Gəl görək daha çox söz əlavə e Bax! Kimsə mənə sadəcə "pişik" desə, nə istədiklərini bilmirəm. Şəkil istəyirlər? Hekayə? Pişiklər haqqında faktlar? Çaşmışam! 😵‍💫 +
+
## Daha Yaxşı Promptlar Qurmaq Yaxşı promptun **üç hissəsi** var: @@ -21,7 +26,9 @@ Yaxşı promptun **üç hissəsi** var: Gəl birlikdə prompt quraq! +
+
## Parçaları Sürüklə! +
+
## Boşluqları Doldur! İndi sehrli sözləri sürükləyərək öz promptunu etməyə çalış: + +
+
## Seçmə Növbəsi Səndədir! +
+
## Əla İş! 🌟 İlk promptlarını yazdın! Yaxşı promptlara lazım olanı öyrəndin: nə istəyirsən, mövzu və detaillar. Həqiqətən yaxşılaşırsan! + +
+ diff --git a/src/content/kids/az/1-3-being-clear.mdx b/src/content/kids/az/1-3-being-clear.mdx index 67052377..b5de2d60 100644 --- a/src/content/kids/az/1-3-being-clear.mdx +++ b/src/content/kids/az/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
Salam superstar! 🌟 Bu gün ən vacib bacarığı öyrənəcəyik: **AYDIN** olmaq! +
+
## Niyə Aydın Olmaq Vacibdir Anandan "yemək" istəməklə "qabıqsız fıstıq yağı sendviçi" istəməyin fərqini təsəvvür et. Hansı sənə dəqiq istədiyini verir? @@ -9,11 +12,14 @@ Anandan "yemək" istəməklə "qabıqsız fıstıq yağı sendviçi" istəməyin Mənimlə eynidir! Aydın olanda, dəqiq necə kömək edəcəyimi bilirəm. Qeyri-müəyyən olanda, təxmin etməliyəm... və səhv edə bilərəm! +
+
## Aydın vs. Aydın Deyil Gəl fərqi tapmağı məşq edək! + + +
+
## Aydınlıq Çağırışı Gəl ən aydın promptu quraq! + +
+
## Aydın Detaillar Əlavə Et +
+
## Aydınlığın Qızıl Qaydaları @@ -74,6 +88,7 @@ Prompt yazanda bu üç sualı xatırla: 2. **NECƏ** olmalıdır? (qısa, gülməli, sadə) 3. **KİM** üçündür? (mən, dostum, sinifim) + +
+
## Dünya 1 Tamamlandı! 🎊 @@ -94,8 +111,11 @@ VAY! Bütün Dünya 1-i bitirdin! Öyrəndiklərin: Yeni macəralara hazırsan! + +
+ diff --git a/src/content/kids/de/1-1-meet-promi.mdx b/src/content/kids/de/1-1-meet-promi.mdx index a5699ffc..a2b97245 100644 --- a/src/content/kids/de/1-1-meet-promi.mdx +++ b/src/content/kids/de/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
Hallo! Ich bin **Promi** 🤖, dein Roboter-Freund! Ich freue mich so, dich kennenzulernen! @@ -9,7 +10,9 @@ Weißt du, was **KI** bedeutet? KI steht für **Künstliche Intelligenz**. Das i Ich bin eine KI! Ich kann deine Nachrichten lesen und versuchen dir zu helfen. Aber hier ist das Geheimnis... Ich brauche **gute Anweisungen** um meine beste Arbeit zu machen! +
+
## Was ist ein Prompt? Ein **Prompt** ist einfach ein schickes Wort für die Nachricht, die du an eine KI wie mich sendest. @@ -19,7 +22,9 @@ Stell dir vor, du gibst einem Freund Wegbeschreibungen. Wenn du sagst "Geh dorth Wenn du einen guten Prompt schreibst, kann ich verstehen, was du willst und dir besser helfen! Lass uns üben! +
+
## Probieren wir es! +
+
## Schnelles Quiz! +
+
## Du hast es geschafft! 🎉 Tolle Arbeit! Du hast gelernt, was KI ist und was ein Prompt ist. Du wirst schon ein Prompt-Experte! + +
+ diff --git a/src/content/kids/de/1-2-first-words.mdx b/src/content/kids/de/1-2-first-words.mdx index b8ef35d5..df21405e 100644 --- a/src/content/kids/de/1-2-first-words.mdx +++ b/src/content/kids/de/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
Willkommen zurück, Freund! Bereit, deine ersten echten Prompts zu schreiben? Los geht's! 🚀 +
+
## Die Magie der Worte Wenn du mit KI sprichst, zählt jedes Wort! Lass uns sehen, wie mehr Worte Prompts besser machen. @@ -9,7 +12,9 @@ Wenn du mit KI sprichst, zählt jedes Wort! Lass uns sehen, wie mehr Worte Promp Schau mal! Wenn jemand nur "Katze" zu mir sagt, weiß ich nicht, was sie wollen. Wollen sie ein Bild? Eine Geschichte? Fakten über Katzen? Ich bin verwirrt! 😵‍💫 +
+
## Bessere Prompts Bauen Ein guter Prompt hat **drei Teile**: @@ -21,7 +26,9 @@ Ein guter Prompt hat **drei Teile**: Lass uns zusammen einen Prompt bauen! +
+
## Ziehe die Teile! +
+
## Fülle die Lücken! Versuche jetzt, deinen eigenen Prompt zu machen, indem du die Zauberwörter ziehst: + +
+
## Du bist dran! +
+
## Tolle Arbeit! 🌟 Du hast deine ersten Prompts geschrieben! Du hast gelernt, dass gute Prompts brauchen: was du willst, ein Thema und Details. Du wirst wirklich gut darin! + +
+ diff --git a/src/content/kids/de/1-3-being-clear.mdx b/src/content/kids/de/1-3-being-clear.mdx index 91da3ac9..02b98d4f 100644 --- a/src/content/kids/de/1-3-being-clear.mdx +++ b/src/content/kids/de/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
Hey Superstar! 🌟 Heute lernen wir die wichtigste Fähigkeit: **KLAR** sein! +
+
## Warum Klar Sein Wichtig Ist Stell dir vor, du bittest deine Mama um "Essen" vs. um "ein Erdnussbutter-Sandwich ohne Kruste." Was gibt dir genau das, was du willst? @@ -9,11 +12,14 @@ Stell dir vor, du bittest deine Mama um "Essen" vs. um "ein Erdnussbutter-Sandwi Bei mir ist es genauso! Wenn du klar bist, weiß ich genau, wie ich helfen kann. Wenn du vage bist, muss ich raten... und ich könnte falsch raten! +
+
## Klar vs. Unklar Lass uns üben, den Unterschied zu erkennen! + + +
+
## Die Klarheits-Herausforderung Lass uns den klarsten Prompt aller Zeiten bauen! + +
+
## Füge Klare Details Hinzu +
+
## Die Goldenen Regeln der Klarheit @@ -74,6 +88,7 @@ Erinnere dich an diese drei Fragen, wenn du einen Prompt schreibst: 2. **WIE** soll es sein? (kurz, lustig, einfach) 3. **FÜR WEN** ist es? (mich, meinen Freund, meine Klasse) + +
+
## Welt 1 Abgeschlossen! 🎊 @@ -94,8 +111,11 @@ WOW! Du hast die ganze Welt 1 beendet! Du hast gelernt: Du bist bereit für neue Abenteuer! + +
+ diff --git a/src/content/kids/el/1-1-meet-promi.mdx b/src/content/kids/el/1-1-meet-promi.mdx index 062bf720..8eaebf3a 100644 --- a/src/content/kids/el/1-1-meet-promi.mdx +++ b/src/content/kids/el/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
Γεια! Είμαι ο **Promi** 🤖, ο ρομπότ φίλος σου! Χαίρομαι πολύ που σε γνωρίζω! @@ -9,7 +10,9 @@ Είμαι AI! Μπορώ να διαβάζω τα μηνύματά σου και να προσπαθώ να βοηθήσω. Αλλά να το μυστικό... Χρειάζομαι **καλές οδηγίες** για να κάνω τη καλύτερη δουλειά! +
+
## Τι είναι ένα Prompt; Ένα **prompt** είναι απλά μια κομψή λέξη για το μήνυμα που στέλνεις σε ένα AI σαν εμένα. @@ -19,7 +22,9 @@ Όταν γράφεις καλό prompt, μπορώ να καταλάβω τι θέλεις και να σε βοηθήσω καλύτερα! Ας εξασκηθούμε! +
+
## Ας Δοκιμάσουμε! +
+
## Γρήγορο Κουίζ! +
+
## Τα Κατάφερες! 🎉 Καταπληκτική δουλειά! Έμαθες τι είναι το AI και τι είναι prompt. Γίνεσαι ήδη ειδικός στα prompts! + +
+ diff --git a/src/content/kids/el/1-2-first-words.mdx b/src/content/kids/el/1-2-first-words.mdx index 0a361e2b..5fe3dd0b 100644 --- a/src/content/kids/el/1-2-first-words.mdx +++ b/src/content/kids/el/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
Καλώς ήρθες πάλι, φίλε! Έτοιμος να γράψεις τα πρώτα σου αληθινά prompts; Πάμε! 🚀 +
+
## Η Μαγεία των Λέξεων Όταν μιλάς με το AI, κάθε λέξη μετράει! Ας δούμε πώς η προσθήκη λέξεων κάνει τα prompts καλύτερα. @@ -9,7 +12,9 @@ Κοίτα! Αν κάποιος μου πει μόνο "γάτα", δεν ξέρω τι θέλουν. Θέλουν εικόνα; Ιστορία; Γεγονότα για γάτες; Είμαι μπερδεμένος! 😵‍💫 +
+
## Χτίζοντας Καλύτερα Prompts Ένα καλό prompt έχει **τρία μέρη**: @@ -21,7 +26,9 @@ Ας χτίσουμε ένα prompt μαζί! +
+
## Σύρε τα Κομμάτια! +
+
## Συμπλήρωσε τα Κενά! Τώρα δοκίμασε να φτιάξεις το δικό σου prompt σύροντας τις μαγικές λέξεις: + +
+
## Η Σειρά Σου να Διαλέξεις! +
+
## Εξαιρετική Δουλειά! 🌟 Έγραψες τα πρώτα σου prompts! Έμαθες ότι τα καλά prompts χρειάζονται: τι θέλεις, θέμα και λεπτομέρειες. Γίνεσαι πολύ καλός! + +
+ diff --git a/src/content/kids/el/1-3-being-clear.mdx b/src/content/kids/el/1-3-being-clear.mdx index a3855f88..ac6bf183 100644 --- a/src/content/kids/el/1-3-being-clear.mdx +++ b/src/content/kids/el/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
Γεια σούπερ αστέρι! 🌟 Σήμερα θα μάθουμε την πιο σημαντική ικανότητα: να είσαι **ΣΑΦΗΣ**! +
+
## Γιατί το να Είσαι Σαφής Είναι Σημαντικό Φαντάσου να ζητάς από τη μαμά σου "φαγητό" έναντι "σάντουιτς με φιστικοβούτυρο χωρίς κόρα." Ποιο σου δίνει ακριβώς αυτό που θέλεις; @@ -9,11 +12,14 @@ Το ίδιο είναι και μαζί μου! Όταν είσαι σαφής, ξέρω ακριβώς πώς να βοηθήσω. Όταν είσαι αόριστος, πρέπει να μαντέψω... και μπορεί να κάνω λάθος! +
+
## Σαφές vs. Ασαφές Ας εξασκηθούμε να βρίσκουμε τη διαφορά! + + +
+
## Η Πρόκληση της Σαφήνειας Ας χτίσουμε το πιο σαφές prompt! + +
+
## Πρόσθεσε Σαφείς Λεπτομέρειες +
+
## Οι Χρυσοί Κανόνες της Σαφήνειας @@ -74,6 +88,7 @@ 2. **ΠΩΣ** πρέπει να είναι; (μικρό, αστείο, απλό) 3. **ΓΙΑ ΠΟΙΟΝ** είναι; (εμένα, τον φίλο μου, την τάξη μου) + +
+
## Κόσμος 1 Ολοκληρώθηκε! 🎊 @@ -94,8 +111,11 @@ Είσαι έτοιμος για νέες περιπέτειες! + +
+ diff --git a/src/content/kids/en/1-1-meet-promi.mdx b/src/content/kids/en/1-1-meet-promi.mdx index 64ccfcd0..d38a66b2 100644 --- a/src/content/kids/en/1-1-meet-promi.mdx +++ b/src/content/kids/en/1-1-meet-promi.mdx @@ -1,25 +1,67 @@ +
Hi there! I'm **Promi** 🤖, your robot friend! I'm so happy to meet you! +
+
Do you know what **AI** means? AI stands for **Artificial Intelligence**. That's a fancy way of saying "a computer that can think and talk!" +
+
I'm an AI! I can read your messages and try to help you. But here's the secret... I need **good instructions** to do my best work! +
+
+## How Do I Think? 🧠 + +Want to know my secret? I don't actually "think" like you do. I read words and guess what word should come next! + + + +
+ +
+ +
+ +
## What is a Prompt? A **prompt** is just a fancy word for the message you send to an AI like me. Think of it like giving directions to a friend. If you say "Go there!" your friend won't know where to go. But if you say "Go to the red house on Maple Street," they'll know exactly where! +
+
When you write a good prompt, I can understand what you want and help you better! Let's practice! +
+
## Let's Try It! +
+
## Quick Quiz! +
+
## You Did It! 🎉 @@ -51,3 +97,4 @@ Amazing job! You learned what AI is and what a prompt is. You're already becomin stars={3} message="You learned what AI and prompts are!" /> +
diff --git a/src/content/kids/en/1-2-first-words.mdx b/src/content/kids/en/1-2-first-words.mdx index aac9d32c..3b1d2008 100644 --- a/src/content/kids/en/1-2-first-words.mdx +++ b/src/content/kids/en/1-2-first-words.mdx @@ -1,15 +1,31 @@ +
Welcome back, friend! Ready to write your first real prompts? Let's go! 🚀 +
+
## The Magic of Words When you talk to AI, every word matters! Let's see how adding more words makes prompts better. + + Watch this! If someone just says "cat" to me, I don't know what they want. Do they want a picture? A story? Facts about cats? I'm confused! 😵‍💫 +
+
## Building Better Prompts A good prompt has **three parts**: @@ -21,7 +37,9 @@ A good prompt has **three parts**: Let's build a prompt together! +
+
## Drag the Pieces! +
+
## Fill in the Blanks! -Now try making your own prompt by filling in the magic words: +Now try making your own prompt by dragging the magic words: +
+
## Your Turn to Choose! +
+
## Great Job! 🌟 @@ -73,3 +97,4 @@ You wrote your first prompts! You learned that good prompts need: what you want, stars={3} message="You learned how to write your first prompts!" /> +
diff --git a/src/content/kids/en/1-3-being-clear.mdx b/src/content/kids/en/1-3-being-clear.mdx index 85964305..a485d2ff 100644 --- a/src/content/kids/en/1-3-being-clear.mdx +++ b/src/content/kids/en/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
Hey superstar! 🌟 Today we're going to learn the most important skill: being **CLEAR**! +
+
## Why Being Clear Matters Imagine asking your mom for "food" vs asking for "a peanut butter sandwich with no crust." Which one gets you exactly what you want? @@ -9,11 +12,11 @@ Imagine asking your mom for "food" vs asking for "a peanut butter sandwich with It's the same with me! When you're clear, I know exactly how to help. When you're vague, I have to guess... and I might guess wrong! +
+
## Clear vs. Unclear -Let's practice spotting the difference! - +
+
+
+
## The Clarity Challenge -Let's build the clearest prompt ever! - +
+
## Fill in Clear Details +
+
## The Golden Rules of Clarity @@ -73,7 +82,9 @@ Remember these three questions when writing a prompt: 1. **WHAT** do I want? (story, help, information) 2. **HOW** should it be? (short, funny, simple) 3. **WHO** is it for? (me, my friend, my class) +
+
+
+
## World 1 Complete! 🎊 @@ -99,3 +112,4 @@ You're ready for new adventures! stars={3} message="You mastered the art of being clear! World 1 complete!" /> +
diff --git a/src/content/kids/en/2-1-missing-details.mdx b/src/content/kids/en/2-1-missing-details.mdx new file mode 100644 index 00000000..34cc9358 --- /dev/null +++ b/src/content/kids/en/2-1-missing-details.mdx @@ -0,0 +1,81 @@ +
+ +Welcome to **Clarity Castle**! 🏰 I'm so glad you made it here! In this world, we'll learn the magic of **details**! + +
+ +
+ +Have you ever asked someone for something, but they didn't understand what you meant? That happens to AI too! + +
+ +
+## The Problem with Vague Prompts + +Look at these two prompts: + +❌ **Vague:** "Draw a picture" + +✅ **Specific:** "Draw a picture of a happy puppy playing in a sunny park" + +Which one gives me more information to work with? +
+ +
+ +The second one tells me **what** to draw (puppy), **what it's doing** (playing), and **where** (sunny park). That's the power of details! + +
+ +
+## Let's Practice! + + +
+ +
+## Why Details Matter + + +
+ +
+## Fill in the Details! + + +
+ +
+## You're Learning! 🎉 + + +Awesome work! You discovered that **details make prompts better**. Vague prompts = confused AI. Detailed prompts = amazing results! + + + +
diff --git a/src/content/kids/en/2-2-who-and-what.mdx b/src/content/kids/en/2-2-who-and-what.mdx new file mode 100644 index 00000000..671436e0 --- /dev/null +++ b/src/content/kids/en/2-2-who-and-what.mdx @@ -0,0 +1,97 @@ +
+ +Welcome back to Clarity Castle! Today we're learning about **WHO** and **WHAT** - two super important details! + +
+ +
+## The WHO Question + +When you ask AI for help, think: **Who is involved?** + +- A person? (boy, girl, grandma, superhero) +- An animal? (cat, dragon, whale) +- A character? (robot, wizard, alien) +
+ +
+ +If you say "Write a story," I don't know who it's about! But "Write a story about a brave knight" tells me exactly who the main character is! + +
+ +
+## Let's Practice WHO! + + +
+ +
+## The WHAT Question + +Now think: **What is happening? What do you want?** + +- What action? (running, singing, building) +- What object? (a cake, a spaceship, a poem) +- What type? (funny, scary, colorful) +
+ +
+## Let's Practice WHAT! + + +
+ +
+## Build Your Own Prompt! + +Put WHO and WHAT together: + + +
+ +
+## Create Your Own! + + +
+ +
+## Amazing Progress! 🎉 + + +You're getting so good at this! Now you know to always include **WHO** is in your prompt and **WHAT** you want. Keep it up! + + + +
diff --git a/src/content/kids/en/2-3-when-and-where.mdx b/src/content/kids/en/2-3-when-and-where.mdx new file mode 100644 index 00000000..ef02f033 --- /dev/null +++ b/src/content/kids/en/2-3-when-and-where.mdx @@ -0,0 +1,96 @@ +
+ +Great to see you again! Today's lesson is about **WHEN** and **WHERE** - these details make your prompts come alive! + +
+ +
+## The WHEN Question + +**When** does your story happen? + +- Time of day: morning, night, sunset +- Season: summer, winter, spring +- Era: long ago, future, present day +- Special time: birthday, holiday, first day of school +
+ +
+ +"A story about a cat" is okay, but "A story about a cat on a spooky Halloween night" is SO much more interesting! + +
+ +
+## Let's Practice WHEN! + + +
+ +
+## The WHERE Question + +**Where** does the action take place? + +- Location: beach, forest, city, space +- Building: school, castle, treehouse +- Fantasy place: underwater kingdom, cloud city +- Specific spot: under a bridge, on top of a mountain +
+ +
+## Let's Practice WHERE! + + +
+ +
+## Combine WHEN and WHERE! + + +
+ +
+## Build a Complete Scene! + + +
+ +
+## You're a Scene Setter! 🎉 + + +Fantastic work! You now know how to add **WHEN** (time) and **WHERE** (place) to your prompts. This makes your requests so much more interesting! + + + +
diff --git a/src/content/kids/en/2-4-detail-detective.mdx b/src/content/kids/en/2-4-detail-detective.mdx new file mode 100644 index 00000000..906d6ccf --- /dev/null +++ b/src/content/kids/en/2-4-detail-detective.mdx @@ -0,0 +1,104 @@ +
+ +Welcome to the final level of Clarity Castle! 🏰 You've learned about WHO, WHAT, WHEN, and WHERE. Now let's put it ALL together! + +
+ +
+## The Detail Detective Checklist + +Before you send a prompt, ask yourself: + +✅ **WHO** - Who is involved? +✅ **WHAT** - What do I want? What's happening? +✅ **WHEN** - When does it happen? +✅ **WHERE** - Where does it take place? +
+ +
+## Sort the Prompt Parts! + + +
+ +
+ +You don't need ALL four every time, but the more details you add, the better I can help you! + +
+ +
+## Detective Challenge #1 + + +
+ +
+## Detective Challenge #2 + + +
+ +
+## Build the Ultimate Prompt! + + +
+ +
+## Create Your Masterpiece! + + +
+ +
+## Congratulations, Detective! 🎉 + + +You did it! You've completed Clarity Castle and become a **Detail Detective**! You now know the secret: WHO + WHAT + WHEN + WHERE = Amazing Prompts! + + + +
diff --git a/src/content/kids/en/3-1-setting-the-scene.mdx b/src/content/kids/en/3-1-setting-the-scene.mdx new file mode 100644 index 00000000..a0c16be9 --- /dev/null +++ b/src/content/kids/en/3-1-setting-the-scene.mdx @@ -0,0 +1,71 @@ +
+ +Welcome to the **Context Caves**! 🕳️ Here we'll discover the magic of **background information**! + +
+ +
+ +Have you ever told someone a joke, but they didn't laugh because they didn't understand the background? Context is like giving someone the backstory! + +
+ +
+## What is Context? + +**Context** is the extra information that helps AI understand your request better. + +Think of it like telling a story - if you just say "and then he won!" nobody knows who won, what they won, or why it matters! +
+ +
+## See the Difference + + +
+ +
+## Setting the Scene + + +
+ +
+## Practice Setting Context! + + +
+ +
+## Excellent Start! 🎉 + + +You're learning to set the scene! Remember: giving me context helps me understand your situation and give you better answers! + + + +
diff --git a/src/content/kids/en/3-2-show-dont-tell.mdx b/src/content/kids/en/3-2-show-dont-tell.mdx new file mode 100644 index 00000000..37f10ff0 --- /dev/null +++ b/src/content/kids/en/3-2-show-dont-tell.mdx @@ -0,0 +1,104 @@ +
+ +Welcome back! Today's lesson is super important: **Show, Don't Tell**! Using examples is one of the best ways to help AI understand! + +
+ +
+## The Power of Examples + +Instead of just describing what you want, **show me an example**! + +It's like when you're teaching someone a game - it's easier to show them how to play than just tell them the rules! +
+ +
+## Learn the Pattern! + + +
+ +
+ +If you say "make it sound cool," I might not know what "cool" means to you. But if you show me an example, I'll understand perfectly! + +
+ +
+## See the Difference + + +
+ +
+## Show Your Style + + +
+ +
+## Give Examples! + + +
+ +
+## Create Your Own Example-Prompt! + + +
+ +
+## Examples Are Powerful! 🎉 + + +Amazing work! You learned that **showing examples** is one of the best ways to help AI understand exactly what you want! + + + +
diff --git a/src/content/kids/en/3-3-format-finder.mdx b/src/content/kids/en/3-3-format-finder.mdx new file mode 100644 index 00000000..54cd7b9e --- /dev/null +++ b/src/content/kids/en/3-3-format-finder.mdx @@ -0,0 +1,87 @@ +
+ +Today we learn about **formats**! 📝 Did you know you can ask AI to respond in different ways? + +
+ +
+## What's a Format? + +A **format** is HOW you want the answer presented: + +- 📋 **List** - numbered or bullet points +- 📖 **Story** - a narrative with beginning, middle, end +- 🎵 **Poem** - with rhymes and rhythm +- ❓ **Q&A** - question and answer style +- 📊 **Table** - organized in rows and columns +
+ +
+ +By telling me the format, you help me organize my answer in the way that's most helpful for you! + +
+ +
+## Format Makes a Difference! + + +
+ +
+## Choose Your Format! + + +
+ +
+## Format Practice! + + +
+ +
+## Pick Your Format! + + +
+ +
+## Format Master! 🎉 + + +Wonderful! You learned that asking for a specific **format** helps you get answers organized exactly how you need them! + + + +
diff --git a/src/content/kids/en/3-4-context-champion.mdx b/src/content/kids/en/3-4-context-champion.mdx new file mode 100644 index 00000000..3c4f165b --- /dev/null +++ b/src/content/kids/en/3-4-context-champion.mdx @@ -0,0 +1,87 @@ +
+ +Welcome to the final level of Context Caves! 🕳️ Time to become a **Context Champion** by combining everything you've learned! + +
+ +
+## The Context Champion Checklist + +Great context includes: + +✅ **Background** - Who you are, what situation you're in +✅ **Examples** - Show what you want +✅ **Format** - How you want the answer organized +
+ +
+ +Put all three together and you'll get amazing results every time! + +
+ +
+## Champion Challenge #1 + + +
+ +
+## Champion Challenge #2 + + +
+ +
+## Build a Champion Prompt! + + +
+ +
+## Create Your Champion Prompt! + + +
+ +
+## Congratulations, Champion! 🎉 + + +You did it! You've completed Context Caves and become a **Context Champion**! You now know how to combine background, examples, and format for amazing prompts! + + + +
diff --git a/src/content/kids/en/4-1-pretend-time.mdx b/src/content/kids/en/4-1-pretend-time.mdx new file mode 100644 index 00000000..788ccd3f --- /dev/null +++ b/src/content/kids/en/4-1-pretend-time.mdx @@ -0,0 +1,86 @@ +
+ +Welcome to **Creation Canyon**! 🎨 This is where creativity comes alive! Today we learn about **role-play prompts**! + +
+ +
+## What is Role-Play? + +**Role-play** means asking the AI to pretend to be someone or something! + +You can say things like: +- "Act as a pirate..." +- "Pretend you're a teacher..." +- "You are a friendly chef..." +
+ +
+ +When you ask me to play a role, I can give answers in that character's voice and style! It's like we're playing pretend together! + +
+ +
+## See Role-Play in Action! + + +
+ +
+## Choose Your Character! + + +
+ +
+## Create a Role-Play Prompt! + + +
+ +
+## Build Your Own Role-Play! + + +
+ +
+## Role-Play Master! 🎉 + + +Fantastic! You learned that **role-play prompts** make conversations creative and fun! Just ask me to "act as" or "pretend to be" someone! + + + +
diff --git a/src/content/kids/en/4-2-story-starters.mdx b/src/content/kids/en/4-2-story-starters.mdx new file mode 100644 index 00000000..28f3d5a8 --- /dev/null +++ b/src/content/kids/en/4-2-story-starters.mdx @@ -0,0 +1,87 @@ +
+ +Welcome back to Creation Canyon! Today we're going to create amazing **stories** together! 📚 + +
+ +
+## AI as Your Co-Author + +You don't have to write stories alone! AI can help you: + +- Start a story with an exciting opening +- Continue a story you've begun +- Add new characters or plot twists +- Give you ideas when you're stuck +
+ +
+ +The best stories come from your imagination AND my help working together! + +
+ +
+## Story Starters That Work! + + +
+ +
+## Continue the Adventure! + + +
+ +
+## Start Your Story! + + +
+ +
+## Create Your Story Prompt! + + +
+ +
+## Story Creator! 🎉 + + +Amazing! You learned how to use AI as your **co-author**! Together, we can create the most incredible stories! + + + +
diff --git a/src/content/kids/en/4-3-character-creator.mdx b/src/content/kids/en/4-3-character-creator.mdx new file mode 100644 index 00000000..a19e1c1d --- /dev/null +++ b/src/content/kids/en/4-3-character-creator.mdx @@ -0,0 +1,88 @@ +
+ +Today we learn to give AI a **personality**! 🎭 This makes conversations SO much more fun! + +
+ +
+## Give AI a Personality! + +You can tell AI what personality to have: + +- **Friendly and cheerful** - always positive! +- **Silly and goofy** - makes lots of jokes +- **Wise and calm** - gives thoughtful answers +- **Excited and energetic** - uses lots of exclamation points! +
+ +
+ +When you tell me what personality to have, I can match the mood you're looking for! + +
+ +
+## Personality Makes a Difference! + + +
+ +
+## Match the Mood! + + +
+ +
+## Create a Character! + + +
+ +
+## Design Your AI Personality! + + +
+ +
+## Personality Master! 🎉 + + +Wonderful! You learned that giving AI a **personality** makes conversations more fun and engaging! Try different personalities for different needs! + + + +
diff --git a/src/content/kids/en/4-4-world-builder.mdx b/src/content/kids/en/4-4-world-builder.mdx new file mode 100644 index 00000000..73abece7 --- /dev/null +++ b/src/content/kids/en/4-4-world-builder.mdx @@ -0,0 +1,85 @@ +
+ +Welcome to the final level of Creation Canyon! 🎨 Let's become **World Builders** and create amazing imaginative scenarios! + +
+ +
+## Building Imaginary Worlds + +You can ask AI to help you create entire worlds: + +- Fantasy kingdoms with magic +- Futuristic cities with robots +- Underwater civilizations +- Planets in distant galaxies +
+ +
+ +The only limit is your imagination! Tell me about your world and I'll help bring it to life! + +
+ +
+## World Building in Action! + + +
+ +
+## Expand Your World! + + +
+ +
+## Build Your World! + + +
+ +
+## Create Your Ultimate World! + + +
+ +
+## Congratulations, World Builder! 🎉 + + +You did it! You've completed Creation Canyon and become a **World Builder**! Your imagination combined with AI can create endless amazing worlds! + + + +
diff --git a/src/content/kids/en/5-1-perfect-prompt.mdx b/src/content/kids/en/5-1-perfect-prompt.mdx new file mode 100644 index 00000000..64880065 --- /dev/null +++ b/src/content/kids/en/5-1-perfect-prompt.mdx @@ -0,0 +1,107 @@ +
+ +Welcome to **Master Mountain**! ⛰️ You've come so far! Now it's time to combine EVERYTHING you've learned into perfect prompts! + +
+ +
+## The Master Checklist + +A perfect prompt can include: + +✅ **Clarity** - Be specific, not vague +✅ **Details** - WHO, WHAT, WHEN, WHERE +✅ **Context** - Background info, examples, format +✅ **Creativity** - Role-play, personality, imagination +
+ +
+## Magic Words: "Think Step by Step" 🧠 + + +
+ +
+ +You don't need ALL of these every time, but knowing when to use each one makes you a Prompt Master! + +
+ +
+## Master Challenge #1 + + +
+ +
+## Master Challenge #2 + + +
+ +
+## Build a Master Prompt! + + +
+ +
+## Create Your Master Prompt! + + +
+ +
+## Master Skills Unlocked! 🎉 + + +Incredible! You learned to combine all your skills into **perfect prompts**! You're well on your way to becoming a Prompt Master! + + + +
diff --git a/src/content/kids/en/5-2-fix-it-up.mdx b/src/content/kids/en/5-2-fix-it-up.mdx new file mode 100644 index 00000000..073cb92b --- /dev/null +++ b/src/content/kids/en/5-2-fix-it-up.mdx @@ -0,0 +1,108 @@ +
+ +Welcome back! Today we learn a super important skill: **finding and fixing weak prompts**! 🔧 + +
+ +
+## Spot the Problems! + +Weak prompts often have: + +❌ Too vague - "Write something" +❌ Missing details - "Tell me about a person" +❌ No format - Just asking without structure +❌ Unclear style - Not saying how you want it +
+ +
+## Be the Prompt Doctor! 🏥 + + +
+ +
+ +Learning to spot weak prompts helps you write better ones! It's like being a prompt detective! + +
+ +
+## Find the Fix! + + +
+ +
+## Improve This Prompt! + + +
+ +
+## Fix the Prompt! + + +
+ +
+## Upgrade Challenge! + +Take this weak prompt and make it strong: + +**Weak:** "Give me ideas" + + +
+ +
+## Prompt Fixer! 🎉 + + +Excellent! You learned to spot weak prompts and **fix them** by adding details, format, and style! This skill will help you forever! + + + +
diff --git a/src/content/kids/en/5-3-prompt-remix.mdx b/src/content/kids/en/5-3-prompt-remix.mdx new file mode 100644 index 00000000..7696e4ee --- /dev/null +++ b/src/content/kids/en/5-3-prompt-remix.mdx @@ -0,0 +1,106 @@ +
+ +Today we learn **Prompt Remix**! 🎵 This means changing prompts to get different results! + +
+ +
+## Same Topic, Different Results! + +You can ask about the same thing in different ways to get different answers: + +- **For fun**: "Tell me about dolphins in a silly way" +- **For school**: "Give me 5 educational facts about dolphins" +- **For creativity**: "Write a poem from a dolphin's point of view" +
+ +
+## Try the Prompt Lab! 🔬 + + +
+ +
+ +Remixing prompts means you can explore the same topic in many exciting ways! + +
+ +
+## See the Remix! + + +
+ +
+## Remix for Different Goals! + + +
+ +
+## Try Different Remixes! + + +
+ +
+## Create Your Remix! + +Take the basic topic "robots" and remix it: + + +
+ +
+## Remix Master! 🎉 + + +Fantastic! You learned to **remix prompts** to get different results from the same topic! This makes your creativity endless! + + + +
diff --git a/src/content/kids/en/5-4-graduation-day.mdx b/src/content/kids/en/5-4-graduation-day.mdx new file mode 100644 index 00000000..43a59e8c --- /dev/null +++ b/src/content/kids/en/5-4-graduation-day.mdx @@ -0,0 +1,102 @@ +
+ +🎉 **CONGRATULATIONS!** 🎉 You've made it to the FINAL LEVEL! This is **Graduation Day**! + +
+ +
+## Look How Far You've Come! + +You've mastered: + +⭐ **World 1** - What AI is and why clarity matters +⭐ **World 2** - WHO, WHAT, WHEN, WHERE details +⭐ **World 3** - Context, examples, and formats +⭐ **World 4** - Role-play, stories, and creativity +⭐ **World 5** - Combining everything perfectly! +
+ +
+ +I'm SO proud of you! You've become a true Prompt Master! Let's celebrate with some final challenges! + +
+ +
+## Final Challenge #1 + + +
+ +
+## Final Challenge #2 + + +
+ +
+## The Ultimate Prompt Challenge! + + +
+ +
+## Create Your Graduation Masterpiece! + + +
+ +
+## 🎓 YOU DID IT! 🎓 + + +**CONGRATULATIONS, PROMPT MASTER!** 🏆 + +You've completed ALL levels! You now know how to talk to AI in the best ways possible. You can: +- Be clear and specific +- Add amazing details +- Give helpful context +- Be creative and imaginative +- And so much more! + +Remember: The better your prompts, the better AI can help you. Go out there and create amazing things! + +**Thank you for learning with me! 🤖❤️** + + + +
diff --git a/src/content/kids/es/1-1-meet-promi.mdx b/src/content/kids/es/1-1-meet-promi.mdx index ad723863..d21d3a86 100644 --- a/src/content/kids/es/1-1-meet-promi.mdx +++ b/src/content/kids/es/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
¡Hola! Soy **Promi** 🤖, ¡tu amigo robot! ¡Estoy muy feliz de conocerte! @@ -9,7 +10,9 @@ ¡Soy una IA! Puedo leer tus mensajes e intentar ayudarte. Pero aquí está el secreto... ¡Necesito **buenas instrucciones** para hacer mi mejor trabajo! +
+
## ¿Qué es un Prompt? Un **prompt** es simplemente una palabra elegante para el mensaje que envías a una IA como yo. @@ -19,7 +22,9 @@ Piénsalo como dar direcciones a un amigo. Si dices "¡Ve allí!" tu amigo no sa ¡Cuando escribes un buen prompt, puedo entender lo que quieres y ayudarte mejor! ¡Practiquemos! +
+
## ¡Intentémoslo! +
+
## ¡Quiz Rápido! +
+
## ¡Lo Lograste! 🎉 ¡Increíble trabajo! Aprendiste qué es la IA y qué es un prompt. ¡Ya te estás convirtiendo en un experto en prompts! + +
+ diff --git a/src/content/kids/es/1-2-first-words.mdx b/src/content/kids/es/1-2-first-words.mdx index f04cc9b3..195755f8 100644 --- a/src/content/kids/es/1-2-first-words.mdx +++ b/src/content/kids/es/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
¡Bienvenido de nuevo, amigo! ¿Listo para escribir tus primeros prompts reales? ¡Vamos! 🚀 +
+
## La Magia de las Palabras Cuando hablas con la IA, ¡cada palabra importa! Veamos cómo agregar más palabras hace mejores los prompts. @@ -9,7 +12,9 @@ Cuando hablas con la IA, ¡cada palabra importa! Veamos cómo agregar más palab ¡Mira esto! Si alguien solo me dice "gato", no sé qué quieren. ¿Quieren una imagen? ¿Una historia? ¿Datos sobre gatos? ¡Estoy confundido! 😵‍💫 +
+
## Construyendo Mejores Prompts Un buen prompt tiene **tres partes**: @@ -21,7 +26,9 @@ Un buen prompt tiene **tres partes**: ¡Construyamos un prompt juntos! +
+
## ¡Arrastra las Piezas! +
+
## ¡Llena los Espacios! Ahora intenta hacer tu propio prompt arrastrando las palabras mágicas: + +
+
## ¡Tu Turno de Elegir! +
+
## ¡Gran Trabajo! 🌟 ¡Escribiste tus primeros prompts! Aprendiste que los buenos prompts necesitan: lo que quieres, un tema y detalles. ¡Te estás volviendo muy bueno en esto! + +
+ diff --git a/src/content/kids/es/1-3-being-clear.mdx b/src/content/kids/es/1-3-being-clear.mdx index b2ccbb07..364a5975 100644 --- a/src/content/kids/es/1-3-being-clear.mdx +++ b/src/content/kids/es/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
¡Hola superestrella! 🌟 Hoy vamos a aprender la habilidad más importante: ¡ser **CLARO**! +
+
## Por Qué Ser Claro Importa Imagina pedirle a tu mamá "comida" vs pedirle "un sándwich de mantequilla de maní sin corteza." ¿Cuál te da exactamente lo que quieres? @@ -9,11 +12,14 @@ Imagina pedirle a tu mamá "comida" vs pedirle "un sándwich de mantequilla de m ¡Es lo mismo conmigo! Cuando eres claro, sé exactamente cómo ayudar. Cuando eres vago, tengo que adivinar... ¡y podría adivinar mal! +
+
## Claro vs. No Claro ¡Practiquemos detectando la diferencia! + + +
+
## El Desafío de Claridad ¡Construyamos el prompt más claro de todos! + +
+
## Agrega Detalles Claros +
+
## Las Reglas de Oro de la Claridad @@ -74,6 +88,7 @@ Recuerda estas tres preguntas cuando escribas un prompt: 2. **¿CÓMO** debe ser? (corto, gracioso, simple) 3. **¿PARA QUIÉN** es? (yo, mi amigo, mi clase) + +
+
## ¡Mundo 1 Completo! 🎊 @@ -94,8 +111,11 @@ Recuerda estas tres preguntas cuando escribas un prompt: ¡Estás listo para nuevas aventuras! + +
+ diff --git a/src/content/kids/fa/1-1-meet-promi.mdx b/src/content/kids/fa/1-1-meet-promi.mdx index de86c5d9..83d83e46 100644 --- a/src/content/kids/fa/1-1-meet-promi.mdx +++ b/src/content/kids/fa/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
سلام! من **Promi** 🤖 هستم، دوست رباتت! خیلی خوشحالم که باهات آشنا شدم! @@ -9,7 +10,9 @@ من یه هوش مصنوعی‌ام! می‌تونم پیام‌هات رو بخونم و سعی کنم کمکت کنم. ولی اینجا یه راز هست... برای بهترین کار به **دستورالعمل‌های خوب** نیاز دارم! +
+
## پرامپت چیه؟ **پرامپت** فقط یه کلمه شیک برای پیامی‌ه که به یه هوش مصنوعی مثل من می‌فرستی. @@ -19,7 +22,9 @@ وقتی پرامپت خوب می‌نویسی، می‌تونم بفهمم چی می‌خوای و بهتر کمکت کنم! بیا تمرین کنیم! +
+
## بیا امتحان کنیم! +
+
## آزمون سریع! +
+
## موفق شدی! 🎉 کار عالی! یاد گرفتی هوش مصنوعی چیه و پرامپت چیه. داری متخصص پرامپت می‌شی! + +
+ diff --git a/src/content/kids/fa/1-2-first-words.mdx b/src/content/kids/fa/1-2-first-words.mdx index 6dc9c095..43d38815 100644 --- a/src/content/kids/fa/1-2-first-words.mdx +++ b/src/content/kids/fa/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
خوش اومدی دوباره، دوست! آماده‌ای اولین پرامپت‌های واقعیت رو بنویسی؟ بریم! 🚀 +
+
## جادوی کلمات وقتی با هوش مصنوعی حرف می‌زنی، هر کلمه مهمه! بیا ببینیم چطور اضافه کردن کلمات بیشتر پرامپت‌ها رو بهتر می‌کنه. @@ -9,7 +12,9 @@ ببین! اگه کسی فقط بگه "گربه"، نمی‌دونم چی می‌خوان. عکس می‌خوان؟ داستان؟ حقایق درباره گربه‌ها؟ گیج شدم! 😵‍💫 +
+
## ساختن پرامپت‌های بهتر یه پرامپت خوب **سه بخش** داره: @@ -21,7 +26,9 @@ بیا با هم یه پرامپت بسازیم! +
+
## تکه‌ها رو بکش! +
+
## جای خالی رو پر کن! حالا سعی کن پرامپت خودت رو با کشیدن کلمات جادویی بسازی: + +
+
## نوبت تو برای انتخاب! +
+
## کار عالی! 🌟 اولین پرامپت‌هات رو نوشتی! یاد گرفتی پرامپت‌های خوب به چی نیاز دارن: چی می‌خوای، موضوع و جزئیات. داری خیلی خوب می‌شی! + +
+ diff --git a/src/content/kids/fa/1-3-being-clear.mdx b/src/content/kids/fa/1-3-being-clear.mdx index f9762c06..5249b7cc 100644 --- a/src/content/kids/fa/1-3-being-clear.mdx +++ b/src/content/kids/fa/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
سلام سوپراستار! 🌟 امروز می‌خوایم مهم‌ترین مهارت رو یاد بگیریم: **واضح** بودن! +
+
## چرا واضح بودن مهمه فکر کن از مامانت "غذا" بخوای یا "ساندویچ کره بادام‌زمینی بدون لبه." کدوم دقیقاً چیزی که می‌خوای رو بهت می‌ده؟ @@ -9,11 +12,14 @@ با منم همینطوره! وقتی واضحی، دقیقاً می‌دونم چطور کمک کنم. وقتی مبهمی، باید حدس بزنم... و ممکنه اشتباه کنم! +
+
## واضح در مقابل نامفهوم بیا تمرین کنیم فرق رو پیدا کنیم! + + +
+
## چالش وضوح بیا واضح‌ترین پرامپت رو بسازیم! + +
+
## جزئیات واضح اضافه کن +
+
## قوانین طلایی وضوح @@ -74,6 +88,7 @@ 2. **چطور** باشه؟ (کوتاه، خنده‌دار، ساده) 3. **برای کی**؟ (من، دوستم، کلاسم) + +
+
## دنیای ۱ تموم شد! 🎊 @@ -94,8 +111,11 @@ آماده ماجراجویی‌های جدیدی! + +
+ diff --git a/src/content/kids/fr/1-1-meet-promi.mdx b/src/content/kids/fr/1-1-meet-promi.mdx index 43971e67..339c1f1b 100644 --- a/src/content/kids/fr/1-1-meet-promi.mdx +++ b/src/content/kids/fr/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
Salut ! Je suis **Promi** 🤖, ton ami robot ! Je suis tellement content de te rencontrer ! @@ -9,7 +10,9 @@ Tu sais ce que veut dire **IA** ? IA signifie **Intelligence Artificielle**. C'e Je suis une IA ! Je peux lire tes messages et essayer de t'aider. Mais voici le secret... J'ai besoin de **bonnes instructions** pour faire mon meilleur travail ! +
+
## C'est quoi un Prompt ? Un **prompt** est juste un mot chic pour le message que tu envoies à une IA comme moi. @@ -19,7 +22,9 @@ Pense à ça comme donner des directions à un ami. Si tu dis "Va là-bas !" ton Quand tu écris un bon prompt, je peux comprendre ce que tu veux et mieux t'aider ! Pratiquons ! +
+
## Essayons ! +
+
## Quiz Rapide ! +
+
## Tu as réussi ! 🎉 Super travail ! Tu as appris ce qu'est l'IA et ce qu'est un prompt. Tu deviens déjà un expert en prompts ! + +
+ diff --git a/src/content/kids/fr/1-2-first-words.mdx b/src/content/kids/fr/1-2-first-words.mdx index b6ad8755..b292f467 100644 --- a/src/content/kids/fr/1-2-first-words.mdx +++ b/src/content/kids/fr/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
Bon retour, ami ! Prêt à écrire tes premiers vrais prompts ? C'est parti ! 🚀 +
+
## La Magie des Mots Quand tu parles à l'IA, chaque mot compte ! Voyons comment ajouter plus de mots rend les prompts meilleurs. @@ -9,7 +12,9 @@ Quand tu parles à l'IA, chaque mot compte ! Voyons comment ajouter plus de mots Regarde ! Si quelqu'un me dit juste "chat", je ne sais pas ce qu'ils veulent. Ils veulent une image ? Une histoire ? Des faits sur les chats ? Je suis confus ! 😵‍💫 +
+
## Construire de Meilleurs Prompts Un bon prompt a **trois parties** : @@ -21,7 +26,9 @@ Un bon prompt a **trois parties** : Construisons un prompt ensemble ! +
+
## Glisse les Pièces ! +
+
## Remplis les Blancs ! Maintenant essaie de faire ton propre prompt en glissant les mots magiques : + +
+
## À Toi de Choisir ! +
+
## Super Travail ! 🌟 Tu as écrit tes premiers prompts ! Tu as appris que les bons prompts ont besoin de : ce que tu veux, un sujet, et des détails. Tu deviens vraiment bon ! + +
+ diff --git a/src/content/kids/fr/1-3-being-clear.mdx b/src/content/kids/fr/1-3-being-clear.mdx index 7baabfcc..0184a33b 100644 --- a/src/content/kids/fr/1-3-being-clear.mdx +++ b/src/content/kids/fr/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
Salut superstar ! 🌟 Aujourd'hui on va apprendre la compétence la plus importante : être **CLAIR** ! +
+
## Pourquoi Être Clair est Important Imagine demander à ta maman "de la nourriture" vs demander "un sandwich au beurre de cacahuète sans croûte." Lequel te donne exactement ce que tu veux ? @@ -9,11 +12,14 @@ Imagine demander à ta maman "de la nourriture" vs demander "un sandwich au beur C'est pareil avec moi ! Quand tu es clair, je sais exactement comment t'aider. Quand tu es vague, je dois deviner... et je pourrais me tromper ! +
+
## Clair vs. Pas Clair Pratiquons à repérer la différence ! + + +
+
## Le Défi de la Clarté Construisons le prompt le plus clair jamais fait ! + +
+
## Ajoute des Détails Clairs +
+
## Les Règles d'Or de la Clarté @@ -74,6 +88,7 @@ Rappelle-toi ces trois questions quand tu écris un prompt : 2. **COMMENT** ça doit être ? (court, drôle, simple) 3. **POUR QUI** c'est ? (moi, mon ami, ma classe) + +
+
## Monde 1 Terminé ! 🎊 @@ -94,8 +111,11 @@ WOW ! Tu as terminé tout le Monde 1 ! Tu as appris : Tu es prêt pour de nouvelles aventures ! + +
+ diff --git a/src/content/kids/he/1-1-meet-promi.mdx b/src/content/kids/he/1-1-meet-promi.mdx index 8871609b..de1eabf1 100644 --- a/src/content/kids/he/1-1-meet-promi.mdx +++ b/src/content/kids/he/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
שלום! אני **Promi** 🤖, החבר הרובוט שלך! שמח מאוד להכיר אותך! @@ -9,7 +10,9 @@ אני AI! אני יכול לקרוא את ההודעות שלך ולנסות לעזור. אבל הנה הסוד... אני צריך **הוראות טובות** כדי לעשות את העבודה הכי טובה! +
+
## מה זה פרומפט? **פרומפט** זו פשוט מילה מפוארת להודעה שאתה שולח ל-AI כמוני. @@ -19,7 +22,9 @@ כשאתה כותב פרומפט טוב, אני יכול להבין מה אתה רוצה ולעזור לך יותר טוב! בוא נתרגל! +
+
## בוא ננסה! +
+
## חידון מהיר! +
+
## הצלחת! 🎉 עבודה מדהימה! למדת מה זה AI ומה זה פרומפט. אתה כבר הופך למומחה פרומפטים! + +
+ diff --git a/src/content/kids/he/1-2-first-words.mdx b/src/content/kids/he/1-2-first-words.mdx index 76a14b93..256c9dca 100644 --- a/src/content/kids/he/1-2-first-words.mdx +++ b/src/content/kids/he/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
ברוך הבא בחזרה, חבר! מוכן לכתוב את הפרומפטים האמיתיים הראשונים שלך? יאללה! 🚀 +
+
## הקסם של מילים כשאתה מדבר עם AI, כל מילה חשובה! בוא נראה איך הוספת יותר מילים עושה פרומפטים יותר טובים. @@ -9,7 +12,9 @@ תראה! אם מישהו רק אומר לי "חתול", אני לא יודע מה הם רוצים. הם רוצים תמונה? סיפור? עובדות על חתולים? אני מבולבל! 😵‍💫 +
+
## בונים פרומפטים יותר טובים לפרומפט טוב יש **שלושה חלקים**: @@ -21,7 +26,9 @@ בוא נבנה פרומפט ביחד! +
+
## גרור את החלקים! +
+
## מלא את החסר! עכשיו נסה לעשות פרומפט משלך על ידי גרירת מילות הקסם: + +
+
## תורך לבחור! +
+
## עבודה נהדרת! 🌟 כתבת את הפרומפטים הראשונים שלך! למדת שפרומפטים טובים צריכים: מה אתה רוצה, נושא, ופרטים. אתה ממש משתפר! + +
+ diff --git a/src/content/kids/he/1-3-being-clear.mdx b/src/content/kids/he/1-3-being-clear.mdx index 1015af95..c20a8292 100644 --- a/src/content/kids/he/1-3-being-clear.mdx +++ b/src/content/kids/he/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
היי סופרסטאר! 🌟 היום נלמד את הכישור החשוב ביותר: להיות **ברור**! +
+
## למה להיות ברור זה חשוב דמיין לבקש מאמא "אוכל" לעומת לבקש "כריך חמאת בוטנים בלי קרום." מה נותן לך בדיוק מה שאתה רוצה? @@ -9,11 +12,14 @@ גם איתי ככה! כשאתה ברור, אני יודע בדיוק איך לעזור. כשאתה מעורפל, אני צריך לנחש... ואני עלול לטעות! +
+
## ברור לעומת לא ברור בוא נתרגל לזהות את ההבדל! + + +
+
## אתגר הבהירות בוא נבנה את הפרומפט הכי ברור אי פעם! + +
+
## הוסף פרטים ברורים +
+
## כללי הזהב של הבהירות @@ -74,6 +88,7 @@ 2. **איך** זה צריך להיות? (קצר, מצחיק, פשוט) 3. **למי** זה? (לי, לחבר שלי, לכיתה שלי) + +
+
## עולם 1 הושלם! 🎊 @@ -94,8 +111,11 @@ אתה מוכן להרפתקאות חדשות! + +
+ diff --git a/src/content/kids/it/1-1-meet-promi.mdx b/src/content/kids/it/1-1-meet-promi.mdx index ce0f917b..0f8ce409 100644 --- a/src/content/kids/it/1-1-meet-promi.mdx +++ b/src/content/kids/it/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
Ciao! Sono **Promi** 🤖, il tuo amico robot! Sono così felice di conoscerti! @@ -9,7 +10,9 @@ Sai cosa significa **IA**? IA sta per **Intelligenza Artificiale**. È un modo e Sono un'IA! Posso leggere i tuoi messaggi e cercare di aiutarti. Ma ecco il segreto... Ho bisogno di **buone istruzioni** per fare il mio lavoro al meglio! +
+
## Cos'è un Prompt? Un **prompt** è semplicemente una parola elegante per il messaggio che invii a un'IA come me. @@ -19,7 +22,9 @@ Pensalo come dare indicazioni a un amico. Se dici "Vai lì!" il tuo amico non sa Quando scrivi un buon prompt, posso capire cosa vuoi e aiutarti meglio! Pratichiamo! +
+
## Proviamo! +
+
## Quiz Veloce! +
+
## Ce l'hai fatta! 🎉 Ottimo lavoro! Hai imparato cos'è l'IA e cos'è un prompt. Stai già diventando un esperto di prompt! + +
+ diff --git a/src/content/kids/it/1-2-first-words.mdx b/src/content/kids/it/1-2-first-words.mdx index be2953c1..3264f511 100644 --- a/src/content/kids/it/1-2-first-words.mdx +++ b/src/content/kids/it/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
Bentornato, amico! Pronto a scrivere i tuoi primi veri prompt? Andiamo! 🚀 +
+
## La Magia delle Parole Quando parli con l'IA, ogni parola conta! Vediamo come aggiungere più parole rende i prompt migliori. @@ -9,7 +12,9 @@ Quando parli con l'IA, ogni parola conta! Vediamo come aggiungere più parole re Guarda! Se qualcuno mi dice solo "gatto", non so cosa vogliono. Vogliono un'immagine? Una storia? Fatti sui gatti? Sono confuso! 😵‍💫 +
+
## Costruire Prompt Migliori Un buon prompt ha **tre parti**: @@ -21,7 +26,9 @@ Un buon prompt ha **tre parti**: Costruiamo un prompt insieme! +
+
## Trascina i Pezzi! +
+
## Riempi gli Spazi! Ora prova a fare il tuo prompt trascinando le parole magiche: + +
+
## Tocca a Te Scegliere! +
+
## Ottimo Lavoro! 🌟 Hai scritto i tuoi primi prompt! Hai imparato che i buoni prompt hanno bisogno di: cosa vuoi, un argomento e dettagli. Stai diventando davvero bravo! + +
+ diff --git a/src/content/kids/it/1-3-being-clear.mdx b/src/content/kids/it/1-3-being-clear.mdx index 4abe5177..4057e1a7 100644 --- a/src/content/kids/it/1-3-being-clear.mdx +++ b/src/content/kids/it/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
Ciao superstar! 🌟 Oggi impareremo l'abilità più importante: essere **CHIARI**! +
+
## Perché Essere Chiari è Importante Immagina chiedere a tua mamma "cibo" vs chiedere "un panino al burro d'arachidi senza crosta." Quale ti dà esattamente quello che vuoi? @@ -9,11 +12,14 @@ Immagina chiedere a tua mamma "cibo" vs chiedere "un panino al burro d'arachidi È lo stesso con me! Quando sei chiaro, so esattamente come aiutare. Quando sei vago, devo indovinare... e potrei sbagliare! +
+
## Chiaro vs. Non Chiaro Pratichiamo a trovare la differenza! + + +
+
## La Sfida della Chiarezza Costruiamo il prompt più chiaro di sempre! + +
+
## Aggiungi Dettagli Chiari +
+
## Le Regole d'Oro della Chiarezza @@ -74,6 +88,7 @@ Ricorda queste tre domande quando scrivi un prompt: 2. **COME** deve essere? (corto, divertente, semplice) 3. **PER CHI** è? (me, il mio amico, la mia classe) + +
+
## Mondo 1 Completato! 🎊 @@ -94,8 +111,11 @@ WOW! Hai finito tutto il Mondo 1! Hai imparato: Sei pronto per nuove avventure! + +
+ diff --git a/src/content/kids/ja/1-1-meet-promi.mdx b/src/content/kids/ja/1-1-meet-promi.mdx index fe2b74cf..a0ef8e7d 100644 --- a/src/content/kids/ja/1-1-meet-promi.mdx +++ b/src/content/kids/ja/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
こんにちは!私は **Promi** 🤖、あなたのロボット友達だよ!会えてとっても嬉しい! @@ -9,7 +10,9 @@ 私はAIなの!あなたのメッセージを読んで助けようとするよ。でもね、秘密があるの...私が一番いい仕事をするには**いい指示**が必要なんだ! +
+
## プロンプトって何? **プロンプト**は、私みたいなAIに送るメッセージのことだよ。 @@ -19,7 +22,9 @@ いいプロンプトを書くと、あなたが何を望んでいるかわかって、もっと上手に助けられるよ!練習しよう! +
+
## やってみよう! +
+
## クイックテスト! +
+
## やったね!🎉 すごい!AIが何かとプロンプトが何かを学んだよ。もうプロンプトの専門家になりつつあるね! + +
+ diff --git a/src/content/kids/ja/1-2-first-words.mdx b/src/content/kids/ja/1-2-first-words.mdx index 85421080..76eda83a 100644 --- a/src/content/kids/ja/1-2-first-words.mdx +++ b/src/content/kids/ja/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
おかえり、友達!本当のプロンプトを書く準備はできた?行こう!🚀 +
+
## 言葉の魔法 AIと話すとき、すべての言葉が大事!言葉を増やすとプロンプトがどう良くなるか見てみよう。 @@ -9,7 +12,9 @@ AIと話すとき、すべての言葉が大事!言葉を増やすとプロン 見て!誰かが「猫」としか言わないと、何が欲しいかわからないよ。絵?物語?猫についての事実?困っちゃう!😵‍💫 +
+
## もっといいプロンプトを作ろう いいプロンプトには**3つの部分**があるよ: @@ -21,7 +26,9 @@ AIと話すとき、すべての言葉が大事!言葉を増やすとプロン 一緒にプロンプトを作ろう! +
+
## ピースをドラッグしよう! +
+
## 空欄を埋めよう! 魔法の言葉をドラッグして自分のプロンプトを作ってみよう: + +
+
## あなたの番! +
+
## よくやったね!🌟 最初のプロンプトを書いたよ!いいプロンプトには欲しいもの、テーマ、詳細が必要だって学んだね。本当に上手になってる! + +
+ diff --git a/src/content/kids/ja/1-3-being-clear.mdx b/src/content/kids/ja/1-3-being-clear.mdx index 8ff2d101..ae3facbf 100644 --- a/src/content/kids/ja/1-3-being-clear.mdx +++ b/src/content/kids/ja/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
やあスーパースター!🌟 今日は一番大事なスキルを学ぶよ:**はっきり伝える**こと! +
+
## なぜはっきり伝えることが大事? お母さんに「食べ物」って頼むのと「耳のないピーナッツバターサンドイッチ」って頼むのを想像して。どっちが欲しいものを正確にくれる? @@ -9,11 +12,14 @@ 私も同じ!はっきり言ってくれると、どう助けるか正確にわかるよ。曖昧だと推測しなきゃいけない...間違えるかも! +
+
## はっきり vs. 曖昧 違いを見つける練習をしよう! + + +
+
## はっきりチャレンジ 今までで一番はっきりしたプロンプトを作ろう! + +
+
## はっきりした詳細を追加 +
+
## はっきりの黄金ルール @@ -74,6 +88,7 @@ 2. **どう**あるべき?(短い、おもしろい、シンプル) 3. **誰**のため?(私、友達、クラス) + +
+
## ワールド1完了!🎊 @@ -94,8 +111,11 @@ 新しい冒険の準備ができたよ! + +
+ diff --git a/src/content/kids/ko/1-1-meet-promi.mdx b/src/content/kids/ko/1-1-meet-promi.mdx index 45d36e40..8d36317b 100644 --- a/src/content/kids/ko/1-1-meet-promi.mdx +++ b/src/content/kids/ko/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
안녕! 나는 **Promi** 🤖, 네 로봇 친구야! 만나서 정말 반가워! @@ -9,7 +10,9 @@ 나는 AI야! 네 메시지를 읽고 도와주려고 해. 하지만 여기 비밀이 있어... 최고의 일을 하려면 **좋은 지시**가 필요해! +
+
## 프롬프트가 뭐야? **프롬프트**는 나 같은 AI에게 보내는 메시지를 말하는 멋진 단어야. @@ -19,7 +22,9 @@ 좋은 프롬프트를 쓰면 네가 뭘 원하는지 이해하고 더 잘 도와줄 수 있어! 연습해보자! +
+
## 해보자! +
+
## 퀴즈! +
+
## 해냈어! 🎉 멋져! AI가 뭔지, 프롬프트가 뭔지 배웠어. 벌써 프롬프트 전문가가 되어가고 있어! + +
+ diff --git a/src/content/kids/ko/1-2-first-words.mdx b/src/content/kids/ko/1-2-first-words.mdx index 5055ba6c..381cab53 100644 --- a/src/content/kids/ko/1-2-first-words.mdx +++ b/src/content/kids/ko/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
다시 왔구나, 친구! 첫 번째 진짜 프롬프트를 쓸 준비 됐어? 가보자! 🚀 +
+
## 단어의 마법 AI와 대화할 때 모든 단어가 중요해! 더 많은 단어를 추가하면 프롬프트가 어떻게 좋아지는지 봐보자. @@ -9,7 +12,9 @@ AI와 대화할 때 모든 단어가 중요해! 더 많은 단어를 추가하 이것 봐! 누군가 나에게 "고양이"라고만 하면 뭘 원하는지 몰라. 그림? 이야기? 고양이에 대한 사실? 혼란스러워! 😵‍💫 +
+
## 더 좋은 프롬프트 만들기 좋은 프롬프트는 **세 가지 부분**이 있어: @@ -21,7 +26,9 @@ AI와 대화할 때 모든 단어가 중요해! 더 많은 단어를 추가하 같이 프롬프트를 만들어보자! +
+
## 조각을 드래그해! +
+
## 빈칸을 채워! 이제 마법의 단어를 드래그해서 네 프롬프트를 만들어봐: + +
+
## 네 차례야! +
+
## 잘했어! 🌟 첫 번째 프롬프트를 썼어! 좋은 프롬프트에는 원하는 것, 주제, 세부사항이 필요하다는 걸 배웠어. 정말 잘하고 있어! + +
+ diff --git a/src/content/kids/ko/1-3-being-clear.mdx b/src/content/kids/ko/1-3-being-clear.mdx index 54bb836a..538a8faf 100644 --- a/src/content/kids/ko/1-3-being-clear.mdx +++ b/src/content/kids/ko/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
안녕 슈퍼스타! 🌟 오늘은 가장 중요한 기술을 배울 거야: **명확하게** 말하기! +
+
## 왜 명확하게 말하는 게 중요할까 엄마에게 "음식"을 달라고 하는 것과 "가장자리 없는 땅콩버터 샌드위치"를 달라고 하는 것을 상상해봐. 어떤 게 원하는 걸 정확히 주지? @@ -9,11 +12,14 @@ 나도 마찬가지야! 명확하게 말하면 어떻게 도와야 할지 정확히 알아. 모호하면 추측해야 하고... 틀릴 수도 있어! +
+
## 명확 vs. 불명확 차이를 찾는 연습을 해보자! + + +
+
## 명확성 도전 지금까지 가장 명확한 프롬프트를 만들어보자! + +
+
## 명확한 세부사항 추가 +
+
## 명확성의 황금 규칙 @@ -74,6 +88,7 @@ 2. **어떻게** 되어야 해? (짧게, 재미있게, 간단하게) 3. **누구를** 위한 거야? (나, 친구, 우리 반) + +
+
## 월드 1 완료! 🎊 @@ -94,8 +111,11 @@ 새로운 모험을 위한 준비가 됐어! + +
+ diff --git a/src/content/kids/pt/1-1-meet-promi.mdx b/src/content/kids/pt/1-1-meet-promi.mdx index 4dd44a75..c18781b3 100644 --- a/src/content/kids/pt/1-1-meet-promi.mdx +++ b/src/content/kids/pt/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
Olá! Eu sou o **Promi** 🤖, seu amigo robô! Estou muito feliz em conhecer você! @@ -9,7 +10,9 @@ Você sabe o que **IA** significa? IA significa **Inteligência Artificial**. É Eu sou uma IA! Posso ler suas mensagens e tentar ajudar. Mas aqui está o segredo... Preciso de **boas instruções** para fazer meu melhor trabalho! +
+
## O que é um Prompt? Um **prompt** é apenas uma palavra chique para a mensagem que você envia para uma IA como eu. @@ -19,7 +22,9 @@ Pense nisso como dar direções para um amigo. Se você diz "Vá lá!" seu amigo Quando você escreve um bom prompt, eu posso entender o que você quer e te ajudar melhor! Vamos praticar! +
+
## Vamos Tentar! +
+
## Quiz Rápido! +
+
## Você Conseguiu! 🎉 Incrível trabalho! Você aprendeu o que é IA e o que é um prompt. Você já está se tornando um expert em prompts! + +
+ diff --git a/src/content/kids/pt/1-2-first-words.mdx b/src/content/kids/pt/1-2-first-words.mdx index 6d809c7b..aff00d2b 100644 --- a/src/content/kids/pt/1-2-first-words.mdx +++ b/src/content/kids/pt/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
Bem-vindo de volta, amigo! Pronto para escrever seus primeiros prompts de verdade? Vamos lá! 🚀 +
+
## A Magia das Palavras Quando você fala com IA, cada palavra importa! Vamos ver como adicionar mais palavras torna os prompts melhores. @@ -9,7 +12,9 @@ Quando você fala com IA, cada palavra importa! Vamos ver como adicionar mais pa Olha isso! Se alguém só me diz "gato", não sei o que querem. Querem uma imagem? Uma história? Fatos sobre gatos? Estou confuso! 😵‍💫 +
+
## Construindo Prompts Melhores Um bom prompt tem **três partes**: @@ -21,7 +26,9 @@ Um bom prompt tem **três partes**: Vamos construir um prompt juntos! +
+
## Arraste as Peças! +
+
## Preencha os Espaços! Agora tente fazer seu próprio prompt arrastando as palavras mágicas: + +
+
## Sua Vez de Escolher! +
+
## Ótimo Trabalho! 🌟 Você escreveu seus primeiros prompts! Aprendeu que bons prompts precisam de: o que você quer, um assunto e detalhes. Você está ficando muito bom nisso! + +
+ diff --git a/src/content/kids/pt/1-3-being-clear.mdx b/src/content/kids/pt/1-3-being-clear.mdx index 5892fa3e..1c442f3b 100644 --- a/src/content/kids/pt/1-3-being-clear.mdx +++ b/src/content/kids/pt/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
Ei superestrela! 🌟 Hoje vamos aprender a habilidade mais importante: ser **CLARO**! +
+
## Por Que Ser Claro Importa Imagine pedir para sua mãe "comida" vs pedir "um sanduíche de pasta de amendoim sem casca." Qual te dá exatamente o que você quer? @@ -9,11 +12,14 @@ Imagine pedir para sua mãe "comida" vs pedir "um sanduíche de pasta de amendoi É igual comigo! Quando você é claro, sei exatamente como ajudar. Quando é vago, tenho que adivinhar... e posso adivinhar errado! +
+
## Claro vs. Não Claro Vamos praticar identificar a diferença! + + +
+
## O Desafio da Clareza Vamos construir o prompt mais claro de todos! + +
+
## Adicione Detalhes Claros +
+
## As Regras de Ouro da Clareza @@ -74,6 +88,7 @@ Lembre dessas três perguntas quando escrever um prompt: 2. **COMO** deve ser? (curto, engraçado, simples) 3. **PARA QUEM** é? (eu, meu amigo, minha turma) + +
+
## Mundo 1 Completo! 🎊 @@ -94,8 +111,11 @@ UAU! Você terminou todo o Mundo 1! Você aprendeu: Você está pronto para novas aventuras! + +
+ diff --git a/src/content/kids/ru/1-1-meet-promi.mdx b/src/content/kids/ru/1-1-meet-promi.mdx index 3f4ea74d..56c9256a 100644 --- a/src/content/kids/ru/1-1-meet-promi.mdx +++ b/src/content/kids/ru/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
Привет! Я **Promi** 🤖, твой друг-робот! Я так рад познакомиться с тобой! @@ -9,7 +10,9 @@ Я ИИ! Я могу читать твои сообщения и пытаться помочь. Но вот секрет... Мне нужны **хорошие инструкции**, чтобы делать свою работу лучше всего! +
+
## Что такое промпт? **Промпт** - это просто модное слово для сообщения, которое ты отправляешь ИИ вроде меня. @@ -19,7 +22,9 @@ Когда ты пишешь хороший промпт, я могу понять, что ты хочешь, и лучше помочь тебе! Давай практиковаться! +
+
## Попробуем! +
+
## Быстрый тест! +
+
## Получилось! 🎉 Отличная работа! Ты узнал, что такое ИИ и что такое промпт. Ты уже становишься экспертом по промптам! + +
+ diff --git a/src/content/kids/ru/1-2-first-words.mdx b/src/content/kids/ru/1-2-first-words.mdx index 9c02932b..4bdcf0a2 100644 --- a/src/content/kids/ru/1-2-first-words.mdx +++ b/src/content/kids/ru/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
С возвращением, друг! Готов писать свои первые настоящие промпты? Поехали! 🚀 +
+
## Магия слов Когда ты разговариваешь с ИИ, каждое слово важно! Давай посмотрим, как добавление слов делает промпты лучше. @@ -9,7 +12,9 @@ Смотри! Если кто-то скажет мне только "кот", я не знаю, что они хотят. Картинку? Историю? Факты о котах? Я запутался! 😵‍💫 +
+
## Строим лучшие промпты Хороший промпт имеет **три части**: @@ -21,7 +26,9 @@ Давай построим промпт вместе! +
+
## Перетащи кусочки! +
+
## Заполни пробелы! Теперь попробуй сделать свой промпт, перетаскивая волшебные слова: + +
+
## Твоя очередь выбирать! +
+
## Отличная работа! 🌟 Ты написал свои первые промпты! Ты узнал, что хорошим промптам нужно: что ты хочешь, тема и детали. У тебя отлично получается! + +
+ diff --git a/src/content/kids/ru/1-3-being-clear.mdx b/src/content/kids/ru/1-3-being-clear.mdx index c36c1f5c..aeee9f10 100644 --- a/src/content/kids/ru/1-3-being-clear.mdx +++ b/src/content/kids/ru/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
Привет, суперзвезда! 🌟 Сегодня мы изучим самый важный навык: быть **ЧЁТКИМ**! +
+
## Почему быть чётким важно Представь, что просишь маму "еду" против "бутерброд с арахисовым маслом без корочки." Что даст тебе именно то, что ты хочешь? @@ -9,11 +12,14 @@ Со мной так же! Когда ты чёткий, я точно знаю, как помочь. Когда ты размытый, мне приходится угадывать... и я могу угадать неправильно! +
+
## Чётко vs. Нечётко Давай практиковаться находить разницу! + + +
+
## Вызов чёткости Давай построим самый чёткий промпт! + +
+
## Добавь чёткие детали +
+
## Золотые правила чёткости @@ -74,6 +88,7 @@ 2. **КАКИМ** должно быть? (коротким, смешным, простым) 3. **ДЛЯ КОГО** это? (меня, моего друга, моего класса) + +
+
## Мир 1 пройден! 🎊 @@ -94,8 +111,11 @@ Ты готов к новым приключениям! + +
+ diff --git a/src/content/kids/tr/1-1-meet-promi.mdx b/src/content/kids/tr/1-1-meet-promi.mdx index 46db9fae..15372125 100644 --- a/src/content/kids/tr/1-1-meet-promi.mdx +++ b/src/content/kids/tr/1-1-meet-promi.mdx @@ -1,25 +1,67 @@ +
Merhaba! Ben **Promi** 🤖, robot arkadaşın! Seninle tanıştığıma çok mutluyum! +
+
**Yapay Zeka** ne demek biliyor musun? Yapay Zeka, "düşünebilen ve konuşabilen bir bilgisayar" demek! +
+
-Ben bir yapay zekayım! Mesajlarını okuyup sana yardım etmeye çalışıyorum. Ama işte sır... En iyi işi yapmam için **iyi talimatlara** ihtiyacım var! +Ben bir yapay zekayım! Mesajlarını okuyup sana yardım etmeye çalışıyorum. Ama işte işin sırrı: En iyi işi yapmam için **iyi talimatlara** ihtiyacım var! +
+
+## Nasıl Düşünürüm? 🧠 + +Sırrımı öğrenmek ister misin? Aslında senin gibi "düşünmüyorum". Kelimeleri okuyup sıradaki kelimenin ne olması gerektiğini tahmin ediyorum! + + + +
+ +
+ +
+ +
## Prompt Nedir? **Prompt**, benim gibi bir yapay zekaya gönderdiğin mesaj demek. -Bunu bir arkadaşına yol tarifi vermek gibi düşün. "Oraya git!" dersen arkadaşın nereye gideceğini bilmez. Ama "Akasya Sokağı'ndaki kırmızı eve git" dersen tam olarak nereye gideceğini bilir! +Bunu bir arkadaşına yol tarifi vermek gibi düşün. "Oraya git!" dersen arkadaşın nereye gideceğini bilmez. Ama "Akasya Sokağı'ndaki kırmızı eve git" dersen tam olarak nereye gideceğini bilir! +
+
İyi bir prompt yazdığında, ne istediğini anlayabilir ve sana daha iyi yardım edebilirim! Hadi pratik yapalım! +
+
## Hadi Deneyelim! +
+
## Hızlı Test! +
+
## Başardın! 🎉 @@ -51,3 +97,4 @@ Harika iş! Yapay zekanın ne olduğunu ve promptun ne olduğunu öğrendin. Şi stars={3} message="Yapay zeka ve promptların ne olduğunu öğrendin!" /> +
diff --git a/src/content/kids/tr/1-2-first-words.mdx b/src/content/kids/tr/1-2-first-words.mdx index f1873631..ac30449e 100644 --- a/src/content/kids/tr/1-2-first-words.mdx +++ b/src/content/kids/tr/1-2-first-words.mdx @@ -1,15 +1,31 @@ +
Tekrar hoş geldin arkadaşım! İlk gerçek promptlarını yazmaya hazır mısın? Hadi başlayalım! 🚀 +
+
## Kelimelerin Büyüsü Yapay zeka ile konuşurken her kelime önemli! Daha fazla kelime eklemenin promptları nasıl daha iyi yaptığını görelim. + + Bunu izle! Birisi bana sadece "kedi" derse, ne istediklerini bilmiyorum. Resim mi istiyorlar? Hikaye mi? Kediler hakkında bilgi mi? Kafam karıştı! 😵‍💫 +
+
## Daha İyi Promptlar Oluşturma İyi bir promptun **üç parçası** var: @@ -21,37 +37,44 @@ Bunu izle! Birisi bana sadece "kedi" derse, ne istediklerini bilmiyorum. Resim m Hadi birlikte bir prompt oluşturalım! +
+
## Parçaları Sürükle! +
+
## Boşlukları Doldur! Şimdi sihirli kelimeleri sürükleyerek kendi promptunu yap: +
+
## Senin Seçimin! +
+
## Harika İş! 🌟 @@ -73,3 +98,4 @@ Hadi birlikte bir prompt oluşturalım! stars={3} message="İlk promptlarını yazmayı öğrendin!" /> +
diff --git a/src/content/kids/tr/1-3-being-clear.mdx b/src/content/kids/tr/1-3-being-clear.mdx index e4433965..bd825067 100644 --- a/src/content/kids/tr/1-3-being-clear.mdx +++ b/src/content/kids/tr/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
Merhaba süperstar! 🌟 Bugün en önemli beceriyi öğreneceğiz: **NET OLMAK**! +
+
## Neden Net Olmak Önemli Annenden "yiyecek" istemek ile "kabuksuz fıstık ezmeli sandviç" istemek arasındaki farkı düşün. Hangisi tam olarak istediğini sana verir? @@ -9,11 +12,11 @@ Annenden "yiyecek" istemek ile "kabuksuz fıstık ezmeli sandviç" istemek aras Benimle de aynı! Net olduğunda, tam olarak nasıl yardım edeceğimi bilirim. Belirsiz olduğunda tahmin etmem gerekiyor... ve yanlış tahmin edebilirim! +
+
## Net vs. Belirsiz -Hadi farkı bulmayı pratik yapalım! - +
+
+
+
## Netlik Mücadelesi -Hadi şimdiye kadarki en net promptu oluşturalım! - +
+
## Net Detaylar Ekle +
+
## Netliğin Altın Kuralları @@ -73,7 +83,9 @@ Prompt yazarken bu üç soruyu hatırla: 1. **NE** istiyorum? (hikaye, yardım, bilgi) 2. **NASIL** olmalı? (kısa, komik, basit) 3. **KİM** için? (ben, arkadaşım, sınıfım) +
+
+
+
## Dünya 1 Tamamlandı! 🎊 @@ -99,3 +113,4 @@ Yeni maceralara hazırsın! stars={3} message="Net olma sanatında ustalaştın! Dünya 1 tamamlandı!" /> +
diff --git a/src/content/kids/tr/2-1-missing-details.mdx b/src/content/kids/tr/2-1-missing-details.mdx new file mode 100644 index 00000000..a188b045 --- /dev/null +++ b/src/content/kids/tr/2-1-missing-details.mdx @@ -0,0 +1,81 @@ +
+ +**Netlik Kalesi**'ne hoş geldin! 🏰 Buraya ulaştığın için çok mutluyum! Bu dünyada **detayların** büyüsünü öğreneceğiz! + +
+ +
+ +Hiç birinden bir şey istedin de seni anlamadı mı? Bu yapay zeka için de olur! + +
+ +
+## Belirsiz Promptların Sorunu + +Şu iki prompt'a bak: + +❌ **Belirsiz:** "Bir resim çiz" + +✅ **Net:** "Güneşli bir parkta oynayan mutlu bir köpek yavrusu çiz" + +Hangisi bana daha fazla bilgi veriyor? +
+ +
+ +İkincisi bana **neyi** çizeceğimi (köpek), **ne yaptığını** (oynuyor) ve **nerede** (güneşli park) olduğunu söylüyor. İşte detayların gücü bu! + +
+ +
+## Hadi Pratik Yapalım! + + +
+ +
+## Detaylar Neden Önemli + + +
+ +
+## Detayları Doldur! + + +
+ +
+## Öğreniyorsun! 🎉 + + +Harika iş! **Detayların promptları daha iyi yaptığını** keşfettin. Belirsiz prompt = kafası karışmış yapay zeka. Detaylı prompt = harika sonuçlar! + + + +
diff --git a/src/content/kids/tr/2-2-who-and-what.mdx b/src/content/kids/tr/2-2-who-and-what.mdx new file mode 100644 index 00000000..dbc7ab9e --- /dev/null +++ b/src/content/kids/tr/2-2-who-and-what.mdx @@ -0,0 +1,97 @@ +
+ +Netlik Kalesi'ne tekrar hoş geldin! Bugün **KİM** ve **NE** hakkında öğreneceğiz - iki süper önemli detay! + +
+ +
+## KİM Sorusu + +Yapay zekadan yardım istediğinde düşün: **Kim var?** + +- Bir kişi mi? (çocuk, anneanme, süper kahraman) +- Bir hayvan mı? (kedi, ejderha, balina) +- Bir karakter mi? (robot, büyücü, uzaylı) +
+ +
+ +"Bir hikaye yaz" dersen, kimin hakkında olduğunu bilmiyorum! Ama "Cesur bir şövalye hakkında hikaye yaz" dersen tam olarak ana karakterin kim olduğunu söylüyor! + +
+ +
+## KİM Pratik Yapalım! + + +
+ +
+## NE Sorusu + +Şimdi düşün: **Ne oluyor? Ne istiyorsun?** + +- Ne eylem? (koşmak, şarkı söylemek, inşa etmek) +- Ne nesne? (bir pasta, bir uzay gemisi, bir şiir) +- Ne tür? (komik, korkunç, renkli) +
+ +
+## NE Pratik Yapalım! + + +
+ +
+## Kendi Promptunu Oluştur! + +KİM ve NE'yi birleştir: + + +
+ +
+## Kendinkini Oluştur! + + +
+ +
+## Harika İlerleme! 🎉 + + +Çok iyileşiyorsun! Artık promptuna her zaman **KİM** olduğunu ve **NE** istediğini eklemeyi biliyorsun. Böyle devam et! + + + +
diff --git a/src/content/kids/tr/2-3-when-and-where.mdx b/src/content/kids/tr/2-3-when-and-where.mdx new file mode 100644 index 00000000..e3f31e66 --- /dev/null +++ b/src/content/kids/tr/2-3-when-and-where.mdx @@ -0,0 +1,96 @@ +
+ +Seni tekrar görmek harika! Bugünkü ders **NE ZAMAN** ve **NEREDE** hakkında - bu detaylar promptlarını canlandırıyor! + +
+ +
+## NE ZAMAN Sorusu + +**Ne zaman** hikayenoluyor? + +- Günün zamanı: sabah, gece, gün batımı +- Mevsim: yaz, kış, ilkbahar +- Dönem: çok uzun zaman önce, gelecek, şimdiki zaman +- Özel zaman: doğum günü, tatil, okulun ilk günü +
+ +
+ +"Bir kedi hakkında hikaye" tamam, ama "Ürkütücü bir Cadılar Bayramı gecesinde bir kedi hakkında hikaye" ÇOK daha ilginç! + +
+ +
+## NE ZAMAN Pratik Yapalım! + + +
+ +
+## NEREDE Sorusu + +**Nerede** eylem gerçekleşiyor? + +- Konum: plaj, orman, şehir, uzay +- Bina: okul, kale, ağaç ev +- Fantezi mekan: sualtı krallığı, bulut şehri +- Belirli nokta: köprünün altında, dağın tepesinde +
+ +
+## NEREDE Pratik Yapalım! + + +
+ +
+## NE ZAMAN ve NEREDE'yi Birleştir! + + +
+ +
+## Tam Bir Sahne Oluştur! + + +
+ +
+## Sen Bir Sahne Kurucususun! 🎉 + + +Fantastik iş! Artık promptlarına **NE ZAMAN** (zaman) ve **NEREDE** (yer) eklemeyi biliyorsun. Bu, isteklerini çok daha ilginç yapıyor! + + + +
diff --git a/src/content/kids/tr/2-4-detail-detective.mdx b/src/content/kids/tr/2-4-detail-detective.mdx new file mode 100644 index 00000000..82cf1c03 --- /dev/null +++ b/src/content/kids/tr/2-4-detail-detective.mdx @@ -0,0 +1,104 @@ +
+ +Netlik Kalesi'nin son seviyesine hoş geldin! 🏰 KİM, NE, NE ZAMAN ve NEREDE hakkında öğrendin. Şimdi hepsini bir araya getirelim! + +
+ +
+## Detay Dedektifi Kontrol Listesi + +Bir prompt göndermeden önce kendine sor: + +✅ **KİM** - Kim var? +✅ **NE** - Ne istiyorum? Ne oluyor? +✅ **NE ZAMAN** - Ne zaman oluyor? +✅ **NEREDE** - Nerede gerçekleşiyor? +
+ +
+## Prompt Parçalarını Sırala! + + +
+ +
+ +Her seferinde dördüne de ihtiyacın yok, ama ne kadar çok detay eklersen, sana o kadar iyi yardımcı olabilirim! + +
+ +
+## Dedektif Görevi #1 + + +
+ +
+## Dedektif Görevi #2 + + +
+ +
+## En İyi Promptu Oluştur! + + +
+ +
+## Başyapıtını Yarat! + + +
+ +
+## Tebrikler Dedektif! 🎉 + + +Başardın! Netlik Kalesi'ni tamamladın ve bir **Detay Dedektifi** oldun! Artık sırrı biliyorsun: KİM + NE + NE ZAMAN + NEREDE = Harika Promptlar! + + + +
diff --git a/src/content/kids/tr/3-1-setting-the-scene.mdx b/src/content/kids/tr/3-1-setting-the-scene.mdx new file mode 100644 index 00000000..59904435 --- /dev/null +++ b/src/content/kids/tr/3-1-setting-the-scene.mdx @@ -0,0 +1,71 @@ +
+ +**Bağlam Mağaraları**'na hoş geldin! 🕳️ Burada **arka plan bilgisinin** büyüsünü keşfedeceğiz! + +
+ +
+ +Hiç birine bir fıkra anlattın da gülmediler çünkü arka planı anlamadılar mı? Bağlam, birine hikayenin arka planını vermek gibi! + +
+ +
+## Bağlam Nedir? + +**Bağlam**, yapay zekanın isteğini daha iyi anlamasına yardımcı olan ekstra bilgidir. + +Bir hikaye anlatmak gibi düşün - sadece "sonra kazandı!" dersen, kimse kimin kazandığını, ne kazandığını veya neden önemli olduğunu bilmez! +
+ +
+## Farkı Gör + + +
+ +
+## Sahneyi Kurma + + +
+ +
+## Bağlam Kurma Pratiği! + + +
+ +
+## Mükemmel Başlangıç! 🎉 + + +Sahneyi kurmayı öğreniyorsun! Unutma: bana bağlam vermek durumunu anlamamı ve sana daha iyi cevaplar vermemi sağlıyor! + + + +
diff --git a/src/content/kids/tr/3-2-show-dont-tell.mdx b/src/content/kids/tr/3-2-show-dont-tell.mdx new file mode 100644 index 00000000..32774739 --- /dev/null +++ b/src/content/kids/tr/3-2-show-dont-tell.mdx @@ -0,0 +1,104 @@ +
+ +Tekrar hoş geldin! Bugünkü ders süper önemli: **Göster, Anlatma**! Örnekler kullanmak yapay zekanın anlamasını sağlamanın en iyi yollarından biri! + +
+ +
+## Örneklerin Gücü + +Ne istediğini sadece açıklamak yerine, **bana bir örnek göster**! + +Birine oyun öğretirken olduğu gibi - sadece kuralları söylemek yerine nasıl oynandığını göstermek daha kolay! +
+ +
+## Deseni Öğren! + + +
+ +
+ +"Havalı yap" dersen, senin için "havalı"nın ne anlama geldiğini bilemem. Ama bir örnek gösterirsen, mükemmel anlayacağım! + +
+ +
+## Farkı Gör + + +
+ +
+## Tarzını Göster + + +
+ +
+## Örnekler Ver! + + +
+ +
+## Kendi Örnek-Promptunu Oluştur! + + +
+ +
+## Örnekler Güçlü! 🎉 + + +Harika iş! **Örnekler göstermenin** yapay zekanın tam olarak ne istediğini anlamasını sağlamanın en iyi yollarından biri olduğunu öğrendin! + + + +
diff --git a/src/content/kids/tr/3-3-format-finder.mdx b/src/content/kids/tr/3-3-format-finder.mdx new file mode 100644 index 00000000..305af2e2 --- /dev/null +++ b/src/content/kids/tr/3-3-format-finder.mdx @@ -0,0 +1,87 @@ +
+ +Bugün **formatları** öğreniyoruz! 📝 Yapay zekadan farklı şekillerde yanıt isteyebileceğini biliyor muydun? + +
+ +
+## Format Nedir? + +**Format**, cevabın NASIL sunulmasını istediğindir: + +- 📋 **Liste** - numaralı veya madde işaretli +- 📖 **Hikaye** - başı, ortası, sonu olan bir anlatı +- 🎵 **Şiir** - kafiyeli ve ritmli +- ❓ **Soru-Cevap** - soru ve cevap tarzı +- 📊 **Tablo** - satır ve sütunlarda organize +
+ +
+ +Bana formatı söyleyerek, cevabımı senin için en yararlı şekilde düzenlememe yardım ediyorsun! + +
+ +
+## Format Fark Yaratır! + + +
+ +
+## Formatını Seç! + + +
+ +
+## Format Pratiği! + + +
+ +
+## Formatını Seç! + + +
+ +
+## Format Ustası! 🎉 + + +Harika! Belirli bir **format** istemenin cevapları tam olarak ihtiyacın gibi organize etmeni sağladığını öğrendin! + + + +
diff --git a/src/content/kids/tr/3-4-context-champion.mdx b/src/content/kids/tr/3-4-context-champion.mdx new file mode 100644 index 00000000..84547964 --- /dev/null +++ b/src/content/kids/tr/3-4-context-champion.mdx @@ -0,0 +1,87 @@ +
+ +Bağlam Mağaraları'nın son seviyesine hoş geldin! 🕳️ Öğrendiğin her şeyi birleştirerek **Bağlam Şampiyonu** olma zamanı! + +
+ +
+## Bağlam Şampiyonu Kontrol Listesi + +Harika bağlam şunları içerir: + +✅ **Arka Plan** - Kim olduğun, ne durumda olduğun +✅ **Örnekler** - Ne istediğini göster +✅ **Format** - Cevabın nasıl düzenlenmesini istiyorsun +
+ +
+ +Üçünü de bir araya getir ve her seferinde harika sonuçlar alacaksın! + +
+ +
+## Şampiyon Görevi #1 + + +
+ +
+## Şampiyon Görevi #2 + + +
+ +
+## Şampiyon Prompt Oluştur! + + +
+ +
+## Şampiyon Promptunu Oluştur! + + +
+ +
+## Tebrikler Şampiyon! 🎉 + + +Başardın! Bağlam Mağaraları'nı tamamladın ve **Bağlam Şampiyonu** oldun! Artık harika promptlar için arka plan, örnekler ve formatı nasıl birleştireceğini biliyorsun! + + + +
diff --git a/src/content/kids/tr/4-1-pretend-time.mdx b/src/content/kids/tr/4-1-pretend-time.mdx new file mode 100644 index 00000000..240892bb --- /dev/null +++ b/src/content/kids/tr/4-1-pretend-time.mdx @@ -0,0 +1,86 @@ +
+ +**Yaratıcılık Kanyonu**'na hoş geldin! 🎨 Yaratıcılığın canlandığı yer burası! Bugün **rol yapma promptlarını** öğreniyoruz! + +
+ +
+## Rol Yapma Nedir? + +**Rol yapma**, yapay zekadan biri veya bir şey gibi davranmasını istemek demek! + +Şöyle şeyler söyleyebilirsin: +- "Korsan gibi davran..." +- "Öğretmen olduğunu hayal et..." +- "Sen arkadaş canlısı bir aşçısın..." +
+ +
+ +Bir rol oynamamamı istediğinde, o karakterin sesi ve tarzıyla cevaplar verebilirim! Birlikte hayal kuruyormuşuz gibi! + +
+ +
+## Rol Yapmayı Gör! + + +
+ +
+## Karakterini Seç! + + +
+ +
+## Rol Yapma Promptu Oluştur! + + +
+ +
+## Kendi Rol Yapmını Oluştur! + + +
+ +
+## Rol Yapma Ustası! 🎉 + + +Fantastik! **Rol yapma promptlarının** konuşmaları yaratıcı ve eğlenceli yaptığını öğrendin! Sadece benden "gibi davran" veya "olduğunu hayal et" diye iste! + + + +
diff --git a/src/content/kids/tr/4-2-story-starters.mdx b/src/content/kids/tr/4-2-story-starters.mdx new file mode 100644 index 00000000..ade36922 --- /dev/null +++ b/src/content/kids/tr/4-2-story-starters.mdx @@ -0,0 +1,87 @@ +
+ +Yaratıcılık Kanyonu'na tekrar hoş geldin! Bugün birlikte harika **hikayeler** oluşturacağız! 📚 + +
+ +
+## Ortak Yazar Olarak Yapay Zeka + +Hikayeleri yalnız yazmak zorunda değilsin! Yapay zeka sana yardım edebilir: + +- Heyecanlı bir açılışla hikaye başlatmak +- Başladığın hikayeyi devam ettirmek +- Yeni karakterler veya olay örgüsü dönüşleri eklemek +- Takıldığında fikir vermek +
+ +
+ +En iyi hikayeler senin hayal gücün VE benim yardımımın birlikte çalışmasından çıkıyor! + +
+ +
+## İşe Yarayan Hikaye Başlatıcılar! + + +
+ +
+## Maceraya Devam Et! + + +
+ +
+## Hikayeni Başlat! + + +
+ +
+## Hikaye Promptunu Oluştur! + + +
+ +
+## Hikaye Yaratıcısı! 🎉 + + +Harika! Yapay zekayı **ortak yazar** olarak nasıl kullanacağını öğrendin! Birlikte en inanılmaz hikayeleri yaratabiliriz! + + + +
diff --git a/src/content/kids/tr/4-3-character-creator.mdx b/src/content/kids/tr/4-3-character-creator.mdx new file mode 100644 index 00000000..83422937 --- /dev/null +++ b/src/content/kids/tr/4-3-character-creator.mdx @@ -0,0 +1,88 @@ +
+ +Bugün yapay zekaya **kişilik** vermeyi öğreniyoruz! 🎭 Bu konuşmaları ÇOK daha eğlenceli yapıyor! + +
+ +
+## Yapay Zekaya Kişilik Ver! + +Yapay zekaya ne kişiliğe sahip olacağını söyleyebilirsin: + +- **Arkadaş canlısı ve neşeli** - her zaman pozitif! +- **Saçma ve aptalca** - çok fıkra yapar +- **Bilge ve sakin** - düşünceli cevaplar verir +- **Heyecanlı ve enerjik** - çok ünlem işareti kullanır! +
+ +
+ +Bana ne kişiliğe sahip olacağımı söylediğinde, aradığın havaya uyabilirim! + +
+ +
+## Kişilik Fark Yaratır! + + +
+ +
+## Havayı Eşleştir! + + +
+ +
+## Bir Karakter Oluştur! + + +
+ +
+## Yapay Zeka Kişiliğini Tasarla! + + +
+ +
+## Kişilik Ustası! 🎉 + + +Harika! Yapay zekaya **kişilik** vermenin konuşmaları daha eğlenceli ve ilgi çekici yaptığını öğrendin! Farklı ihtiyaçlar için farklı kişilikler dene! + + + +
diff --git a/src/content/kids/tr/4-4-world-builder.mdx b/src/content/kids/tr/4-4-world-builder.mdx new file mode 100644 index 00000000..34755c47 --- /dev/null +++ b/src/content/kids/tr/4-4-world-builder.mdx @@ -0,0 +1,85 @@ +
+ +Yaratıcılık Kanyonu'nun son seviyesine hoş geldin! 🎨 **Dünya Oluşturucular** olalım ve harika hayali senaryolar yaratalım! + +
+ +
+## Hayali Dünyalar Kurmak + +Yapay zekadan tüm dünyalar yaratmasına yardım etmesini isteyebilirsin: + +- Büyülü fantezi krallıkları +- Robotlu fütüristik şehirler +- Sualtı medeniyetleri +- Uzak galaksilerdeki gezegenler +
+ +
+ +Tek sınır senin hayal gücün! Bana dünyandan bahset ve canlandırmana yardım edeyim! + +
+ +
+## Dünya İnşası İş Başında! + + +
+ +
+## Dünyanı Genişlet! + + +
+ +
+## Dünya İnşa Et! + + +
+ +
+## En İyi Dünyani Yarat! + + +
+ +
+## Tebrikler, Dünya Oluşturucu! 🎉 + + +Başardın! Yaratıcılık Kanyonu'nu tamamladın ve bir **Dünya Oluşturucu** oldun! Hayal gücün ve yapay zeka birlikte sonsuz harika dünyalar yaratabilir! + + + +
diff --git a/src/content/kids/tr/5-1-perfect-prompt.mdx b/src/content/kids/tr/5-1-perfect-prompt.mdx new file mode 100644 index 00000000..aaf22be1 --- /dev/null +++ b/src/content/kids/tr/5-1-perfect-prompt.mdx @@ -0,0 +1,107 @@ +
+ +**Usta Dağı**'na hoş geldin! ⛰️ Çok yol kat ettin! Şimdi öğrendiğin HER ŞEYİ mükemmel promptlar haline getirme zamanı! + +
+ +
+## Usta Kontrol Listesi + +Mükemmel bir prompt şunları içerebilir: + +✅ **Netlik** - Net ol, belirsiz değil +✅ **Detaylar** - KİM, NE, NE ZAMAN, NEREDE +✅ **Bağlam** - Arka plan bilgisi, örnekler, format +✅ **Yaratıcılık** - Rol yapma, kişilik, hayal gücü +
+ +
+## Sihirli Kelimeler: "Adım Adım Düşün" 🧠 + + +
+ +
+ +Her seferinde bunların HEPSİNE ihtiyacın yok, ama her birini ne zaman kullanacağını bilmek seni Prompt Ustası yapar! + +
+ +
+## Usta Görevi #1 + + +
+ +
+## Usta Görevi #2 + + +
+ +
+## Usta Prompt Oluştur! + + +
+ +
+## Usta Promptunu Oluştur! + + +
+ +
+## Usta Becerileri Açıldı! 🎉 + + +İnanılmaz! Tüm becerilerini **mükemmel promptlara** birleştirmeyi öğrendin! Prompt Ustası olmaya doğru ilerliyorsun! + + + +
diff --git a/src/content/kids/tr/5-2-fix-it-up.mdx b/src/content/kids/tr/5-2-fix-it-up.mdx new file mode 100644 index 00000000..787c0f64 --- /dev/null +++ b/src/content/kids/tr/5-2-fix-it-up.mdx @@ -0,0 +1,108 @@ +
+ +Tekrar hoş geldin! Bugün süper önemli bir beceri öğreniyoruz: **zayıf promptları bulma ve düzeltme**! 🔧 + +
+ +
+## Sorunları Tespit Et! + +Zayıf promptlarda genellikle şunlar vardır: + +❌ Çok belirsiz - "Bir şey yaz" +❌ Eksik detaylar - "Bana bir kişi hakkında anlat" +❌ Format yok - Yapı olmadan istemek +❌ Belirsiz tarz - Nasıl istediğini söylememek +
+ +
+## Prompt Doktoru Ol! 🏥 + + +
+ +
+ +Zayıf promptları tespit etmeyi öğrenmek daha iyilerini yazmana yardımcı olur! Prompt dedektifi olmak gibi! + +
+ +
+## Düzeltmeyi Bul! + + +
+ +
+## Bu Promptu Geliştir! + + +
+ +
+## Promptu Düzelt! + + +
+ +
+## Yükseltme Görevi! + +Bu zayıf promptu al ve güçlü yap: + +**Zayıf:** "Bana fikirler ver" + + +
+ +
+## Prompt Tamircisi! 🎉 + + +Mükemmel! Zayıf promptları tespit etmeyi ve detay, format ve tarz ekleyerek **düzeltmeyi** öğrendin! Bu beceri sana sonsuza kadar yardımcı olacak! + + + +
diff --git a/src/content/kids/tr/5-3-prompt-remix.mdx b/src/content/kids/tr/5-3-prompt-remix.mdx new file mode 100644 index 00000000..618bced1 --- /dev/null +++ b/src/content/kids/tr/5-3-prompt-remix.mdx @@ -0,0 +1,106 @@ +
+ +Bugün **Prompt Remix** öğreniyoruz! 🎵 Bu, farklı sonuçlar almak için promptları değiştirmek demek! + +
+ +
+## Aynı Konu, Farklı Sonuçlar! + +Aynı şeyi farklı şekillerde sorarak farklı cevaplar alabilirsin: + +- **Eğlence için**: "Bana yunusları komik bir şekilde anlat" +- **Okul için**: "Bana yunuslar hakkında 5 eğitici bilgi ver" +- **Yaratıcılık için**: "Yunusun bakış açısından bir şiir yaz" +
+ +
+## Prompt Laboratuvarını Dene! 🔬 + + +
+ +
+ +Promptları remixlemek aynı konuyu birçok heyecanlı şekilde keşfedebileceğin anlamına gelir! + +
+ +
+## Remixi Gör! + + +
+ +
+## Farklı Hedefler İçin Remix! + + +
+ +
+## Farklı Remixler Dene! + + +
+ +
+## Remixini Oluştur! + +Temel konuyu "robotlar" al ve remixle: + + +
+ +
+## Remix Ustası! 🎉 + + +Fantastik! Aynı konudan farklı sonuçlar almak için **promptları remixlemeyi** öğrendin! Bu yaratıcılığını sonsuz yapar! + + + +
diff --git a/src/content/kids/tr/5-4-graduation-day.mdx b/src/content/kids/tr/5-4-graduation-day.mdx new file mode 100644 index 00000000..6e9a154c --- /dev/null +++ b/src/content/kids/tr/5-4-graduation-day.mdx @@ -0,0 +1,102 @@ +
+ +🎉 **TEBRİKLER!** 🎉 SON SEVİYEYE ulaştın! Bu **Mezuniyet Günü**! + +
+ +
+## Ne Kadar Yol Kat Ettin Bak! + +Şunlarda ustalaştın: + +⭐ **Dünya 1** - Yapay zekanın ne olduğu ve netliğin neden önemli olduğu +⭐ **Dünya 2** - KİM, NE, NE ZAMAN, NEREDE detayları +⭐ **Dünya 3** - Bağlam, örnekler ve formatlar +⭐ **Dünya 4** - Rol yapma, hikayeler ve yaratıcılık +⭐ **Dünya 5** - Her şeyi mükemmel birleştirmek! +
+ +
+ +Seninle ÇOK gurur duyuyorum! Gerçek bir Prompt Ustası oldun! Son mücadelelerle kutlayalım! + +
+ +
+## Son Görev #1 + + +
+ +
+## Son Görev #2 + + +
+ +
+## En Zor Prompt Görevi! + + +
+ +
+## Mezuniyet Başyapıtını Oluştur! + + +
+ +
+## 🎓 BAŞARDIN! 🎓 + + +**TEBRİKLER, PROMPT USTASI!** 🏆 + +TÜM seviyeleri tamamladın! Artık yapay zeka ile mümkün olan en iyi şekillerde nasıl konuşulacağını biliyorsun. Şunları yapabilirsin: +- Net ve spesifik olmak +- Harika detaylar eklemek +- Yardımcı bağlam vermek +- Yaratıcı ve hayal gücü dolu olmak +- Ve çok daha fazlası! + +Unutma: Promptların ne kadar iyiyse, yapay zeka sana o kadar iyi yardım edebilir. Git ve harika şeyler yarat! + +**Benimle öğrendiğin için teşekkürler! 🤖❤️** + + + +
diff --git a/src/content/kids/zh/1-1-meet-promi.mdx b/src/content/kids/zh/1-1-meet-promi.mdx index 5fa7aae8..77bbf85b 100644 --- a/src/content/kids/zh/1-1-meet-promi.mdx +++ b/src/content/kids/zh/1-1-meet-promi.mdx @@ -1,3 +1,4 @@ +
你好!我是 **Promi** 🤖,你的机器人朋友!很高兴认识你! @@ -9,7 +10,9 @@ 我就是一个AI!我能读取你的消息并尝试帮助你。但这里有个秘密...我需要**好的指令**才能做到最好! +
+
## 什么是提示词? **提示词**就是你发送给像我这样的AI的消息的另一种说法。 @@ -19,7 +22,9 @@ 当你写一个好的提示词时,我就能理解你想要什么,更好地帮助你!让我们来练习吧! +
+
## 试一试! +
+
## 快速测验! +
+
## 你做到了!🎉 太棒了!你学会了什么是AI和什么是提示词。你已经在成为提示词专家了! + +
+ diff --git a/src/content/kids/zh/1-2-first-words.mdx b/src/content/kids/zh/1-2-first-words.mdx index e71960d0..f8ed56d1 100644 --- a/src/content/kids/zh/1-2-first-words.mdx +++ b/src/content/kids/zh/1-2-first-words.mdx @@ -1,7 +1,10 @@ +
欢迎回来,朋友!准备好写你的第一个真正的提示词了吗?出发!🚀 +
+
## 文字的魔力 当你和AI交流时,每个字都很重要!让我们看看添加更多文字如何让提示词变得更好。 @@ -9,7 +12,9 @@ 看这个!如果有人只对我说"猫",我不知道他们想要什么。他们想要图片?故事?关于猫的知识?我很困惑!😵‍💫 +
+
## 构建更好的提示词 一个好的提示词有**三个部分**: @@ -21,7 +26,9 @@ 让我们一起构建一个提示词! +
+
## 拖动拼图! +
+
## 填空! 现在试着通过拖动魔法词来创建你自己的提示词: + +
+
## 轮到你选择! +
+
## 干得好!🌟 你写了你的第一个提示词!你学到了好的提示词需要:你想要什么、主题和细节。你在这方面真的越来越棒了! + +
+ diff --git a/src/content/kids/zh/1-3-being-clear.mdx b/src/content/kids/zh/1-3-being-clear.mdx index 156009b4..128458c6 100644 --- a/src/content/kids/zh/1-3-being-clear.mdx +++ b/src/content/kids/zh/1-3-being-clear.mdx @@ -1,7 +1,10 @@ +
嗨超级明星!🌟 今天我们要学习最重要的技能:**表达清晰**! +
+
## 为什么清晰很重要 想象一下向妈妈要"食物"和要"去掉边的花生酱三明治"的区别。哪个能让你得到你想要的? @@ -9,11 +12,14 @@ 对我来说也是一样!当你表达清晰时,我确切知道如何帮助你。当你表达模糊时,我必须猜测...而且我可能猜错! +
+
## 清晰 vs. 模糊 让我们练习发现差异! + + +
+
## 清晰挑战 让我们构建有史以来最清晰的提示词! + +
+
## 添加清晰的细节 +
+
## 清晰的黄金法则 @@ -74,6 +88,7 @@ 2. 应该**怎样**?(短的、有趣的、简单的) 3. **给谁**?(我、我的朋友、我的班级) + +
+
## 世界1完成!🎊 @@ -94,8 +111,11 @@ 你准备好迎接新的冒险了! + +
+ diff --git a/src/lib/analytics.ts b/src/lib/analytics.ts index 29fed198..5266c7db 100644 --- a/src/lib/analytics.ts +++ b/src/lib/analytics.ts @@ -724,3 +724,80 @@ export const analyticsAdmin = { }); }, }; + +// ============================================================================ +// Kids Mode Events +// ============================================================================ + +export const analyticsKids = { + startGame: () => { + trackEvent({ + action: "kids_start_game", + category: "kids", + }); + }, + + viewLevel: (levelSlug: string, world: number) => { + trackEvent({ + action: "kids_view_level", + category: "kids", + label: levelSlug, + world, + }); + }, + + completeLevel: (levelSlug: string, world: number, stars: number) => { + trackEvent({ + action: "kids_complete_level", + category: "kids", + label: levelSlug, + world, + value: stars, + }); + }, + + completeWorld: (world: number) => { + trackEvent({ + action: "kids_complete_world", + category: "kids", + value: world, + }); + }, + + interactiveComplete: (componentType: string, levelSlug: string) => { + trackEvent({ + action: "kids_interactive_complete", + category: "kids", + label: `${componentType}:${levelSlug}`, + }); + }, + + openSettings: () => { + trackEvent({ + action: "kids_open_settings", + category: "kids", + }); + }, + + changeLanguage: (locale: string) => { + trackEvent({ + action: "kids_change_language", + category: "kids", + label: locale, + }); + }, + + resetProgress: () => { + trackEvent({ + action: "kids_reset_progress", + category: "kids", + }); + }, + + viewMap: () => { + trackEvent({ + action: "kids_view_map", + category: "kids", + }); + }, +}; diff --git a/src/lib/kids/levels.ts b/src/lib/kids/levels.ts index b4c6e872..c9acb986 100644 --- a/src/lib/kids/levels.ts +++ b/src/lib/kids/levels.ts @@ -60,16 +60,206 @@ export const worlds: World[] = [ }, ], }, - // Future worlds (post-MVP) - // { - // number: 2, - // title: "Clarity Castle", - // titleKey: "kids.worlds.2.title", - // slug: "clarity-castle", - // emoji: "🏰", - // color: "blue", - // levels: [], - // }, + { + number: 2, + title: "Clarity Castle", + titleKey: "kids.worlds.2.title", + slug: "clarity-castle", + emoji: "🏰", + color: "blue", + levels: [ + { + slug: "2-1-missing-details", + title: "The Missing Details", + titleKey: "kids.levels.2_1_missing_details.title", + description: "Discover why details matter - vague vs specific prompts", + descriptionKey: "kids.levels.2_1_missing_details.description", + world: 2, + levelNumber: 1, + concepts: ["specificity", "details"], + }, + { + slug: "2-2-who-and-what", + title: "Who & What", + titleKey: "kids.levels.2_2_who_and_what.title", + description: "Add characters and objects to make prompts come alive", + descriptionKey: "kids.levels.2_2_who_and_what.description", + world: 2, + levelNumber: 2, + concepts: ["characters", "objects"], + }, + { + slug: "2-3-when-and-where", + title: "When & Where", + titleKey: "kids.levels.2_3_when_and_where.title", + description: "Learn to add time and place to your prompts", + descriptionKey: "kids.levels.2_3_when_and_where.description", + world: 2, + levelNumber: 3, + concepts: ["time", "place"], + }, + { + slug: "2-4-detail-detective", + title: "The Detail Detective", + titleKey: "kids.levels.2_4_detail_detective.title", + description: "Become a master of adding all the right details", + descriptionKey: "kids.levels.2_4_detail_detective.description", + world: 2, + levelNumber: 4, + concepts: ["combining", "mastery"], + }, + ], + }, + { + number: 3, + title: "Context Caves", + titleKey: "kids.worlds.3.title", + slug: "context-caves", + emoji: "🕳️", + color: "purple", + levels: [ + { + slug: "3-1-setting-the-scene", + title: "Setting the Scene", + titleKey: "kids.levels.3_1_setting_the_scene.title", + description: "Learn why background info helps AI understand you", + descriptionKey: "kids.levels.3_1_setting_the_scene.description", + world: 3, + levelNumber: 1, + concepts: ["background", "context"], + }, + { + slug: "3-2-show-dont-tell", + title: "Show, Don't Tell", + titleKey: "kids.levels.3_2_show_dont_tell.title", + description: "Use examples to show AI exactly what you want", + descriptionKey: "kids.levels.3_2_show_dont_tell.description", + world: 3, + levelNumber: 2, + concepts: ["examples", "demonstration"], + }, + { + slug: "3-3-format-finder", + title: "The Format Finder", + titleKey: "kids.levels.3_3_format_finder.title", + description: "Ask for lists, stories, poems, and more!", + descriptionKey: "kids.levels.3_3_format_finder.description", + world: 3, + levelNumber: 3, + concepts: ["formats", "structure"], + }, + { + slug: "3-4-context-champion", + title: "Context Champion", + titleKey: "kids.levels.3_4_context_champion.title", + description: "Combine all context techniques like a pro", + descriptionKey: "kids.levels.3_4_context_champion.description", + world: 3, + levelNumber: 4, + concepts: ["combining", "mastery"], + }, + ], + }, + { + number: 4, + title: "Creation Canyon", + titleKey: "kids.worlds.4.title", + slug: "creation-canyon", + emoji: "🎨", + color: "orange", + levels: [ + { + slug: "4-1-pretend-time", + title: "Pretend Time!", + titleKey: "kids.levels.4_1_pretend_time.title", + description: "Learn role-play prompts - 'Act as...'", + descriptionKey: "kids.levels.4_1_pretend_time.description", + world: 4, + levelNumber: 1, + concepts: ["roleplay", "personas"], + }, + { + slug: "4-2-story-starters", + title: "Story Starters", + titleKey: "kids.levels.4_2_story_starters.title", + description: "Create amazing stories with AI as your co-author", + descriptionKey: "kids.levels.4_2_story_starters.description", + world: 4, + levelNumber: 2, + concepts: ["storytelling", "narrative"], + }, + { + slug: "4-3-character-creator", + title: "Character Creator", + titleKey: "kids.levels.4_3_character_creator.title", + description: "Give AI a personality and watch it come alive", + descriptionKey: "kids.levels.4_3_character_creator.description", + world: 4, + levelNumber: 3, + concepts: ["characters", "personality"], + }, + { + slug: "4-4-world-builder", + title: "World Builder", + titleKey: "kids.levels.4_4_world_builder.title", + description: "Create imaginative worlds and scenarios", + descriptionKey: "kids.levels.4_4_world_builder.description", + world: 4, + levelNumber: 4, + concepts: ["worldbuilding", "imagination"], + }, + ], + }, + { + number: 5, + title: "Master Mountain", + titleKey: "kids.worlds.5.title", + slug: "master-mountain", + emoji: "⛰️", + color: "amber", + levels: [ + { + slug: "5-1-perfect-prompt", + title: "The Perfect Prompt", + titleKey: "kids.levels.5_1_perfect_prompt.title", + description: "Combine clarity, details, and context together", + descriptionKey: "kids.levels.5_1_perfect_prompt.description", + world: 5, + levelNumber: 1, + concepts: ["combining", "advanced"], + }, + { + slug: "5-2-fix-it-up", + title: "Fix It Up!", + titleKey: "kids.levels.5_2_fix_it_up.title", + description: "Find and improve weak prompts", + descriptionKey: "kids.levels.5_2_fix_it_up.description", + world: 5, + levelNumber: 2, + concepts: ["debugging", "improvement"], + }, + { + slug: "5-3-prompt-remix", + title: "Prompt Remix", + titleKey: "kids.levels.5_3_prompt_remix.title", + description: "Rewrite prompts for different outcomes", + descriptionKey: "kids.levels.5_3_prompt_remix.description", + world: 5, + levelNumber: 3, + concepts: ["variation", "adaptation"], + }, + { + slug: "5-4-graduation-day", + title: "Graduation Day", + titleKey: "kids.levels.5_4_graduation_day.title", + description: "The final challenge - become a Prompt Master!", + descriptionKey: "kids.levels.5_4_graduation_day.description", + world: 5, + levelNumber: 4, + concepts: ["final", "mastery"], + }, + ], + }, ]; export function getAllLevels(): Level[] { diff --git a/src/lib/kids/progress.ts b/src/lib/kids/progress.ts index 63ca45a2..efa72397 100644 --- a/src/lib/kids/progress.ts +++ b/src/lib/kids/progress.ts @@ -101,3 +101,69 @@ export function getCompletedLevelsCount(): number { export function getTotalStars(): number { return getProgress().totalStars; } + +// Component state persistence for within-level progress +const COMPONENT_STATE_KEY = "kids-component-state"; + +interface ComponentState { + [levelSlug: string]: { + [componentId: string]: unknown; + }; +} + +export function getComponentState(levelSlug: string, componentId: string): T | null { + if (typeof window === "undefined") return null; + + try { + const stored = localStorage.getItem(COMPONENT_STATE_KEY); + if (!stored) return null; + const state = JSON.parse(stored) as ComponentState; + return (state[levelSlug]?.[componentId] as T) || null; + } catch { + return null; + } +} + +export function saveComponentState(levelSlug: string, componentId: string, data: T): void { + if (typeof window === "undefined") return; + + try { + const stored = localStorage.getItem(COMPONENT_STATE_KEY); + const state: ComponentState = stored ? JSON.parse(stored) : {}; + + if (!state[levelSlug]) { + state[levelSlug] = {}; + } + state[levelSlug][componentId] = data; + + localStorage.setItem(COMPONENT_STATE_KEY, JSON.stringify(state)); + } catch { + console.error("Failed to save component state"); + } +} + +export function clearComponentState(levelSlug: string): void { + if (typeof window === "undefined") return; + + try { + const stored = localStorage.getItem(COMPONENT_STATE_KEY); + if (!stored) return; + + const state: ComponentState = JSON.parse(stored); + delete state[levelSlug]; + localStorage.setItem(COMPONENT_STATE_KEY, JSON.stringify(state)); + } catch { + console.error("Failed to clear component state"); + } +} + +export function clearAllProgress(): void { + if (typeof window === "undefined") return; + + try { + localStorage.removeItem(STORAGE_KEY); + localStorage.removeItem(COMPONENT_STATE_KEY); + } catch { + console.error("Failed to clear all progress"); + } +}