summaryrefslogtreecommitdiff
path: root/src/components/Flashcard
diff options
context:
space:
mode:
authorpolwex <polwex@sortug.com>2025-05-29 15:16:41 +0700
committerpolwex <polwex@sortug.com>2025-05-29 15:16:41 +0700
commit8e0965f5274635f609972ef85802675af64df0f4 (patch)
treecc82db5928d49bede5c162cd22ab2a4e36cbdc6b /src/components/Flashcard
parent490388360a0852bcf8ee054e96fa90e166df5792 (diff)
this is mostly me
Diffstat (limited to 'src/components/Flashcard')
-rw-r--r--src/components/Flashcard/StudySession.tsx75
1 files changed, 42 insertions, 33 deletions
diff --git a/src/components/Flashcard/StudySession.tsx b/src/components/Flashcard/StudySession.tsx
index 1f79e09..c58531b 100644
--- a/src/components/Flashcard/StudySession.tsx
+++ b/src/components/Flashcard/StudySession.tsx
@@ -13,37 +13,43 @@ import { cn } from "@/lib/utils";
interface StudySessionProps {
userId: number;
lessonId: number;
- initialData?: DeckResponse;
+ initialData: DeckResponse;
}
-export default function StudySession({ userId, lessonId, initialData }: StudySessionProps) {
- const [deckData, setDeckData] = useState<DeckResponse | null>(initialData || null);
+export default function StudySession({
+ userId,
+ lessonId,
+ initialData,
+}: StudySessionProps) {
+ const [deckData, setDeckData] = useState<DeckResponse | null>(
+ initialData || null,
+ );
const [currentCardIndex, setCurrentCardIndex] = useState(0);
const [reviewedCards, setReviewedCards] = useState<CardResponse[]>([]);
const [isLoading, setIsLoading] = useState(!initialData);
const [isCompleted, setIsCompleted] = useState(false);
const [stats, setStats] = useState<any>(null);
const [error, setError] = useState<string | null>(null);
-
+
// Load the deck data if not provided
useEffect(() => {
if (!initialData) {
loadDeck();
}
-
+
// Load user stats
loadStats();
}, []);
-
+
// Load deck data
const loadDeck = async () => {
setIsLoading(true);
setError(null);
-
+
try {
const result = await startStudySession(userId, lessonId, true);
-
- if ('error' in result) {
+
+ if ("error" in result) {
setError(result.error);
setDeckData(null);
} else {
@@ -56,7 +62,7 @@ export default function StudySession({ userId, lessonId, initialData }: StudySes
setIsLoading(false);
}
};
-
+
// Load user stats
const loadStats = async () => {
try {
@@ -66,12 +72,12 @@ export default function StudySession({ userId, lessonId, initialData }: StudySes
console.error("Error loading stats:", error);
}
};
-
+
// Handle card completion
const handleCardComplete = (updatedCard: CardResponse) => {
// Add to reviewed cards
- setReviewedCards(prev => [...prev, updatedCard]);
-
+ setReviewedCards((prev) => [...prev, updatedCard]);
+
// Move to next card
if (deckData && currentCardIndex < deckData.cards.length - 1) {
setCurrentCardIndex(currentCardIndex + 1);
@@ -79,18 +85,18 @@ export default function StudySession({ userId, lessonId, initialData }: StudySes
// End of deck
setIsCompleted(true);
}
-
+
// Refresh stats
loadStats();
};
-
+
// Skip current card
const handleSkip = () => {
if (deckData && currentCardIndex < deckData.cards.length - 1) {
setCurrentCardIndex(currentCardIndex + 1);
}
};
-
+
// Restart session
const handleRestart = () => {
setCurrentCardIndex(0);
@@ -98,19 +104,20 @@ export default function StudySession({ userId, lessonId, initialData }: StudySes
setIsCompleted(false);
loadDeck();
};
-
+
// Calculate completion percentage
const getCompletionPercentage = () => {
if (!deckData) return 0;
return (reviewedCards.length / deckData.cards.length) * 100;
};
-
+
// Get current card
const getCurrentCard = (): CardResponse | null => {
- if (!deckData || !deckData.cards || deckData.cards.length === 0) return null;
- return deckData.cards[currentCardIndex];
+ if (!deckData || !deckData.cards || deckData.cards.length === 0)
+ return null;
+ return deckData.cards[currentCardIndex]!;
};
-
+
// Render loading state
if (isLoading) {
return (
@@ -128,7 +135,7 @@ export default function StudySession({ userId, lessonId, initialData }: StudySes
</div>
);
}
-
+
// Render error state
if (error) {
return (
@@ -140,16 +147,20 @@ export default function StudySession({ userId, lessonId, initialData }: StudySes
</div>
);
}
-
+
// Render completion state
if (isCompleted || !getCurrentCard()) {
return (
<div className="w-full max-w-3xl mx-auto p-4">
<Card className="p-6">
<div className="text-center">
- <h2 className="text-2xl font-bold mb-4">Study Session Completed!</h2>
+ <h2 className="text-2xl font-bold mb-4">
+ Study Session Completed!
+ </h2>
<div className="mb-6">
- <p className="text-lg">You've reviewed {reviewedCards.length} cards.</p>
+ <p className="text-lg">
+ You've reviewed {reviewedCards.length} cards.
+ </p>
{stats && (
<div className="mt-4 text-sm text-gray-600">
<p>Total cards: {stats.totalCards}</p>
@@ -169,29 +180,27 @@ export default function StudySession({ userId, lessonId, initialData }: StudySes
</div>
);
}
-
+
// Render study session
return (
<div className="w-full max-w-3xl mx-auto p-4">
<div className="mb-6">
<div className="flex justify-between items-center mb-2">
- <h2 className="text-xl font-bold">
- {deckData?.lesson.name}
- </h2>
+ <h2 className="text-xl font-bold">{deckData?.lesson.name}</h2>
<div className="text-sm text-gray-500">
{reviewedCards.length} / {deckData?.cards.length} cards
</div>
</div>
<Progress value={getCompletionPercentage()} className="h-2" />
</div>
-
+
<StudyCard
card={getCurrentCard()!}
userId={userId}
onComplete={handleCardComplete}
onSkip={handleSkip}
/>
-
+
<div className="mt-6 flex justify-between">
<Button variant="ghost" onClick={() => window.history.back()}>
Exit
@@ -200,7 +209,7 @@ export default function StudySession({ userId, lessonId, initialData }: StudySes
Skip
</Button>
</div>
-
+
{stats && (
<div className="mt-8 p-4 bg-gray-50 rounded-lg">
<h3 className="font-medium mb-2">Your Progress</h3>
@@ -226,4 +235,4 @@ export default function StudySession({ userId, lessonId, initialData }: StudySes
)}
</div>
);
-} \ No newline at end of file
+}