diff --git a/src/components/micro_learning/ConceptExplainer.jsx b/src/components/micro_learning/ConceptExplainer.jsx
index e1503ba..a504fb9 100644
--- a/src/components/micro_learning/ConceptExplainer.jsx
+++ b/src/components/micro_learning/ConceptExplainer.jsx
@@ -1,38 +1,13 @@
-import React, { useEffect, useRef } from 'react';
import Card from '../ui/Card';
+import Button from '../ui/Button';
export default function ConceptExplainer({ content, onComplete }) {
- const containerRef = useRef(null);
-
- // Trigger completion when scrolled to the end
- useEffect(() => {
- const handleScroll = () => {
- if (!containerRef.current) return;
- const { scrollTop, scrollHeight, clientHeight } = containerRef.current;
- if (scrollTop + clientHeight >= scrollHeight - 50) {
- onComplete();
- }
- };
-
- // Check initially in case content is short and doesn't need scrolling
- if (containerRef.current && containerRef.current.scrollHeight <= containerRef.current.clientHeight) {
- onComplete();
- }
-
- const currentRef = containerRef.current;
- currentRef?.addEventListener('scroll', handleScroll);
- return () => currentRef?.removeEventListener('scroll', handleScroll);
- }, [onComplete]);
-
return (
Concept Explainer
-
+
{content?.sections?.map((section, i) => (
{section.title}
@@ -40,6 +15,9 @@ export default function ConceptExplainer({ content, onComplete }) {
))}
+
+
+
);
}
diff --git a/src/components/micro_learning/FlashcardSet.jsx b/src/components/micro_learning/FlashcardSet.jsx
index c28fdbc..8aa9769 100644
--- a/src/components/micro_learning/FlashcardSet.jsx
+++ b/src/components/micro_learning/FlashcardSet.jsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import { useState } from 'react';
import Card from '../ui/Card';
import Button from '../ui/Button';
@@ -11,14 +11,9 @@ export default function FlashcardSet({ content, onComplete }) {
const handleFlip = () => {
setIsFlipped(!isFlipped);
-
const newViewed = new Set(viewedCards);
newViewed.add(currentIndex);
setViewedCards(newViewed);
-
- if (newViewed.size === cards.length && cards.length > 0) {
- onComplete();
- }
};
const handleNext = () => {
@@ -68,6 +63,13 @@ export default function FlashcardSet({ content, onComplete }) {
+
+
+
+ {viewedCards.size}/{cards.length} cards viewed
+
+
+
);
}
diff --git a/src/components/micro_learning/MicroLearningContainer.jsx b/src/components/micro_learning/MicroLearningContainer.jsx
index f19f640..c042a6f 100644
--- a/src/components/micro_learning/MicroLearningContainer.jsx
+++ b/src/components/micro_learning/MicroLearningContainer.jsx
@@ -1,5 +1,4 @@
-import { useState } from 'react';
-import { useNavigate } from 'react-router-dom';
+import { useRef } from 'react';
import ConceptExplainer from './ConceptExplainer';
import ScenarioQuiz from './ScenarioQuiz';
import FlashcardSet from './FlashcardSet';
@@ -7,31 +6,33 @@ import { useMicroLearningCompletions } from '../../hooks/useMicroLearningComplet
export default function MicroLearningContainer({ microLearning, sessionWeek, onCompletedSuccessfully }) {
const { recordCompletion } = useMicroLearningCompletions();
- const [completed, setCompleted] = useState(false);
- const navigate = useNavigate();
+ // Ref-guard against double-fire while the await is in flight — using state
+ // would let a second click slip through before the re-render lands.
+ const recordingRef = useRef(false);
const handleComplete = async () => {
- if (completed) return; // Prevent double recording
+ if (recordingRef.current) return;
+ recordingRef.current = true;
const record = await recordCompletion({
microLearningId: microLearning.id,
topicId: microLearning.topic_id,
type: microLearning.type,
- sessionWeek: sessionWeek
+ sessionWeek: sessionWeek,
});
- if (record) {
- setCompleted(true);
- if (onCompletedSuccessfully) {
- onCompletedSuccessfully(record);
- }
+ if (record && onCompletedSuccessfully) {
+ onCompletedSuccessfully(record);
+ } else if (!record) {
+ // Allow a retry if persistence failed.
+ recordingRef.current = false;
}
};
const renderComponent = () => {
const props = {
content: microLearning.content,
- onComplete: handleComplete
+ onComplete: handleComplete,
};
switch (microLearning.type) {
@@ -46,24 +47,5 @@ export default function MicroLearningContainer({ microLearning, sessionWeek, onC
}
};
- return (
-
- {renderComponent()}
-
- {completed && (
-
-
-
Micro Learning Completed!
-
Your progress has been recorded.
-
-
-
- )}
-
- );
+ return {renderComponent()}
;
}
diff --git a/src/components/micro_learning/ScenarioQuiz.jsx b/src/components/micro_learning/ScenarioQuiz.jsx
index d8e0c94..a187e2b 100644
--- a/src/components/micro_learning/ScenarioQuiz.jsx
+++ b/src/components/micro_learning/ScenarioQuiz.jsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import { useState } from 'react';
import Card from '../ui/Card';
import Button from '../ui/Button';
@@ -10,7 +10,6 @@ export default function ScenarioQuiz({ content, onComplete }) {
if (showExplanations) return;
setSelectedOptionId(idx);
setShowExplanations(true);
- onComplete();
};
return (
@@ -57,6 +56,12 @@ export default function ScenarioQuiz({ content, onComplete }) {
);
})}
+
+ {showExplanations && (
+
+
+
+ )}
);
diff --git a/src/pages/Leren.jsx b/src/pages/Leren.jsx
index d895388..d89ceb8 100644
--- a/src/pages/Leren.jsx
+++ b/src/pages/Leren.jsx
@@ -1,7 +1,7 @@
import { useState, useEffect } from 'react';
-import { BookOpen, CheckCircle, ArrowRight, ChevronLeft, Calendar } from 'lucide-react';
+import { BookOpen, CheckCircle, ArrowRight, ChevronLeft, Calendar, CheckSquare } from 'lucide-react';
import { motion } from 'framer-motion';
-import { Link } from 'react-router-dom';
+import { useNavigate } from 'react-router-dom';
import Card from '../components/ui/Card';
import Button from '../components/ui/Button';
import Tag from '../components/ui/Tag';
@@ -14,6 +14,7 @@ import { useMicroLearningCompletions } from '../hooks/useMicroLearningCompletion
const Leren = () => {
const { state } = useApp();
+ const navigate = useNavigate();
const [assignedTopic, setAssignedTopic] = useState(null);
const [allTopics, setAllTopics] = useState([]);
@@ -96,12 +97,21 @@ const Leren = () => {
Topic reviewed!
-
+
You have successfully completed a micro learning for "{activeTopic.label}".
-
+
+ Ready to put it to the test, or explore another format for this topic?
+
+
+
+