useCompatibleSRS.ts
1 import { useCallback } from 'react' 2 import { usePGLiteSRS } from './usePGLiteSRS' 3 import type { DueCard } from '../types/srs.types' 4 5 /** 6 * Compatibility hook that wraps PGLite SRS functionality 7 * Provides the same interface as the old IDB implementation 8 */ 9 export function useCompatibleSRS() { 10 const pgLiteSRS = usePGLiteSRS() 11 12 // Wrapper for getDueCards 13 const getDueCards = useCallback(async (limit?: number, songId?: number): Promise<DueCard[]> => { 14 const cards = await pgLiteSRS.getDueCards(limit, songId) 15 // Convert PGLite format to IDB format for compatibility 16 return cards.map(card => ({ 17 id: card.id!, 18 songId: card.song_id, 19 lineIndex: card.referent_id, // Map referent_id back to lineIndex 20 lineText: card.fragment, 21 songTitle: card.song_title, 22 artistName: card.artist_name, 23 difficulty: card.difficulty, 24 stability: card.stability, 25 elapsedDays: card.elapsed_days, 26 scheduledDays: card.scheduled_days, 27 reps: card.reps, 28 lapses: card.lapses, 29 state: card.state, 30 lastReview: card.last_review, 31 dueDate: card.due_date, 32 createdAt: card.created_at, 33 updatedAt: card.updated_at 34 })) 35 }, [pgLiteSRS]) 36 37 // Wrapper for updateCardReview 38 const updateCardReview = useCallback(async ( 39 songId: number, 40 lineIndex: number, 41 wasCorrect: boolean 42 ): Promise<boolean> => { 43 return await pgLiteSRS.updateCardReview(songId, lineIndex, wasCorrect) 44 }, [pgLiteSRS]) 45 46 // Wrapper for saveExerciseSession (saveStudySession in PGLite) 47 const saveExerciseSession = useCallback(async (data: { 48 cardsReviewed: number 49 cardsCorrect: number 50 accuracy?: number 51 }): Promise<string | null> => { 52 return await pgLiteSRS.saveStudySession({ 53 cardsReviewed: data.cardsReviewed, 54 cardsCorrect: data.cardsCorrect, 55 startedAt: Date.now() - 300000, // Default 5 minutes ago 56 completedAt: Date.now() 57 }) 58 }, [pgLiteSRS]) 59 60 // Wrapper for createExerciseCard 61 const createExerciseCard = useCallback(async (params: { 62 exerciseId: string 63 exerciseType: string 64 songId: number 65 referentId: number 66 question: string 67 fragment: string 68 songTitle?: string 69 artistName?: string 70 }): Promise<boolean> => { 71 return await pgLiteSRS.createExerciseCard({ 72 songId: params.songId, 73 referentId: params.referentId, 74 fragment: params.fragment, 75 songTitle: params.songTitle, 76 artistName: params.artistName 77 }) 78 }, [pgLiteSRS]) 79 80 // Wrapper for getUserStats 81 const getUserStats = useCallback(async (songId?: number) => { 82 const stats = await pgLiteSRS.getUserStats(songId) 83 if (!stats) return null 84 85 // Convert to IDB format 86 return { 87 newCards: stats.new_cards, 88 learningCards: stats.learning_cards, 89 dueCards: stats.review_cards, // Use review_cards instead of total_due_cards 90 totalCards: stats.total_cards, 91 averageScore: 0 // Not tracked in PGLite 92 } 93 }, [pgLiteSRS]) 94 95 return { 96 // State 97 isReady: pgLiteSRS.isReady, 98 isInitialized: pgLiteSRS.isReady, 99 isChecking: false, 100 usePGLite: true, // Always using PGLite now 101 102 // Core SRS operations 103 getDueCards, 104 updateCardReview, 105 saveExerciseSession, 106 createExerciseCard, 107 getUserStats, 108 109 // Pass through from PGLite 110 syncStatus: pgLiteSRS.syncStatus, 111 currentChainId: pgLiteSRS.currentChainId, 112 113 // New method to check total cards (useful for migration status) 114 getTotalCardCount: useCallback(async () => { 115 const stats = await pgLiteSRS.getUserStats() 116 return stats?.total_cards || 0 117 }, [pgLiteSRS]) 118 } 119 }