From cd151aace4323ededb352927ab181d7aee076971 Mon Sep 17 00:00:00 2001 From: RaymondVerhoef Date: Sun, 24 May 2026 23:45:26 +0200 Subject: [PATCH] feat: implement core micro-learning components and hooks for diverse educational formats --- .../micro_learning/ConceptExplainer.jsx | 16 +++--- .../micro_learning/FlashcardSet.jsx | 16 +++--- .../micro_learning/MicroLearningSelector.jsx | 51 +++++++++---------- .../micro_learning/ReflectionPrompt.jsx | 28 +++++----- .../micro_learning/ScenarioQuiz.jsx | 25 ++++----- src/hooks/useMicroLearningCompletions.js | 16 ++---- src/hooks/useMicroLearnings.js | 2 +- 7 files changed, 71 insertions(+), 83 deletions(-) diff --git a/src/components/micro_learning/ConceptExplainer.jsx b/src/components/micro_learning/ConceptExplainer.jsx index e798bb8..e1503ba 100644 --- a/src/components/micro_learning/ConceptExplainer.jsx +++ b/src/components/micro_learning/ConceptExplainer.jsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef } from 'react'; -import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'; // assuming some UI library, otherwise use standard divs +import Card from '../ui/Card'; export default function ConceptExplainer({ content, onComplete }) { const containerRef = useRef(null); @@ -25,12 +25,12 @@ export default function ConceptExplainer({ content, onComplete }) { }, [onComplete]); return ( - - - Concept Explainer - - +
+

Concept Explainer

+
+
{content?.sections?.map((section, i) => ( @@ -39,7 +39,7 @@ export default function ConceptExplainer({ content, onComplete }) {
))} - +
); } diff --git a/src/components/micro_learning/FlashcardSet.jsx b/src/components/micro_learning/FlashcardSet.jsx index 16a841c..c28fdbc 100644 --- a/src/components/micro_learning/FlashcardSet.jsx +++ b/src/components/micro_learning/FlashcardSet.jsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; -import { Card, CardContent } from '../ui/card'; -import { Button } from '../ui/button'; +import Card from '../ui/Card'; +import Button from '../ui/Button'; export default function FlashcardSet({ content, onComplete }) { const [currentIndex, setCurrentIndex] = useState(0); @@ -12,12 +12,10 @@ export default function FlashcardSet({ content, onComplete }) { const handleFlip = () => { setIsFlipped(!isFlipped); - // Once flipped, mark this card as viewed const newViewed = new Set(viewedCards); newViewed.add(currentIndex); setViewedCards(newViewed); - // If all cards are viewed, trigger completion if (newViewed.size === cards.length && cards.length > 0) { onComplete(); } @@ -41,25 +39,25 @@ export default function FlashcardSet({ content, onComplete }) { return (
-
+
Card {currentIndex + 1} of {cards.length}
- +
{isFlipped ? (

{currentCard.back}

) : ( -
+

{currentCard.front}

)} - +
diff --git a/src/components/micro_learning/MicroLearningSelector.jsx b/src/components/micro_learning/MicroLearningSelector.jsx index ca22bfc..4faf36c 100644 --- a/src/components/micro_learning/MicroLearningSelector.jsx +++ b/src/components/micro_learning/MicroLearningSelector.jsx @@ -1,8 +1,8 @@ import React, { useState, useEffect } from 'react'; import { useMicroLearnings } from '../../hooks/useMicroLearnings'; import MicroLearningContainer from './MicroLearningContainer'; -import { Button } from '../ui/button'; -import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'; +import Button from '../ui/Button'; +import Card from '../ui/Card'; const TYPE_LABELS = { 'concept_explainer': 'Concept Explainer', @@ -40,19 +40,21 @@ export default function MicroLearningSelector({ topicId, sessionWeek, onTopicCom setSelectedML(ml); }; - if (loading) return
Loading learning formats...
; + if (loading) return
Loading learning formats...
; if (availableMLs.length === 0) { - return
No micro learnings available for this topic yet.
; + return
No micro learnings available for this topic yet.
; } - // If one is selected, render it if (selectedML) { return (
- + - - Choose a Learning Format - - -
- {availableMLs.map((ml) => ( - handleSelection(ml)} - > - -

{TYPE_LABELS[ml.type] || ml.type}

-

{TYPE_DESCRIPTIONS[ml.type]}

-
-
- ))} -
-
+
+

Choose a Learning Format

+
+
+ {availableMLs.map((ml) => ( +
handleSelection(ml)} + > +

{TYPE_LABELS[ml.type] || ml.type}

+

{TYPE_DESCRIPTIONS[ml.type]}

+
+ ))} +
); } diff --git a/src/components/micro_learning/ReflectionPrompt.jsx b/src/components/micro_learning/ReflectionPrompt.jsx index 39ecd91..af12411 100644 --- a/src/components/micro_learning/ReflectionPrompt.jsx +++ b/src/components/micro_learning/ReflectionPrompt.jsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; -import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'; -import { Button } from '../ui/button'; +import Card from '../ui/Card'; +import Button from '../ui/Button'; export default function ReflectionPrompt({ content, onComplete }) { const [response, setResponse] = useState(''); @@ -11,15 +11,15 @@ export default function ReflectionPrompt({ content, onComplete }) { if (!response.trim() || submitted) return; setSubmitted(true); - onComplete(); // Trigger completion when a response is submitted + onComplete(); }; return ( - - Reflection Prompt - - +
+

Reflection Prompt

+
+

{content?.prompt}

@@ -27,7 +27,7 @@ export default function ReflectionPrompt({ content, onComplete }) { {!submitted ? (