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? +

+
+ +