@@ -84,6 +84,7 @@ export const useOpeningDrillController = (
8484 useState < OpeningDrillGame | null > ( null )
8585 const [ analysisEnabled , setAnalysisEnabled ] = useState ( false )
8686 const [ currentDrillIndex , setCurrentDrillIndex ] = useState ( 0 )
87+ const [ allDrillsCompleted , setAllDrillsCompleted ] = useState ( false )
8788
8889 // Performance tracking state
8990 const [ showPerformanceModal , setShowPerformanceModal ] = useState ( false )
@@ -104,17 +105,18 @@ export const useOpeningDrillController = (
104105 useEffect ( ( ) => {
105106 if (
106107 configuration . drillSequence . length > 0 &&
107- remainingDrills . length === 0
108+ remainingDrills . length === 0 &&
109+ ! allDrillsCompleted
108110 ) {
109111 setRemainingDrills ( configuration . drillSequence )
110112 setCurrentDrill ( configuration . drillSequence [ 0 ] )
111113 setCurrentDrillIndex ( 0 )
112114 }
113- } , [ configuration . drillSequence , remainingDrills . length ] )
115+ } , [ configuration . drillSequence , remainingDrills . length , allDrillsCompleted ] )
114116
115117 // Initialize current drill game when drill changes
116118 useEffect ( ( ) => {
117- if ( ! currentDrill ) return
119+ if ( ! currentDrill || allDrillsCompleted ) return
118120
119121 const startingFen =
120122 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
@@ -144,7 +146,7 @@ export const useOpeningDrillController = (
144146 setCurrentDrillGame ( drillGame )
145147 setWaitingForMaiaResponse ( false )
146148 setContinueAnalyzingMode ( false ) // Reset continue analyzing mode for new drill
147- } , [ currentDrill ] )
149+ } , [ currentDrill , allDrillsCompleted ] )
148150
149151 // Use the current drill game's tree, or create a default one
150152 const gameTree = currentDrillGame ?. tree || new GameTree ( new Chess ( ) . fen ( ) )
@@ -194,6 +196,13 @@ export const useOpeningDrillController = (
194196 return controller . currentNode === currentDrillGame . openingEndNode
195197 } , [ currentDrillGame , controller . currentNode ] )
196198
199+ // Check if all drills are completed
200+ const areAllDrillsCompleted = useMemo ( ( ) => {
201+ return (
202+ allDrillsCompleted || completedDrills . length >= configuration . drillCount
203+ )
204+ } , [ allDrillsCompleted , completedDrills . length , configuration . drillCount ] )
205+
197206 // Available moves for the current position - only when it's the player's turn
198207 const moves = useMemo ( ( ) => {
199208 if ( ! controller . currentNode || ! isPlayerTurn )
@@ -290,9 +299,8 @@ export const useOpeningDrillController = (
290299 setCurrentPerformanceData ( performanceData )
291300 setCompletedDrills ( ( prev ) => [ ...prev , performanceData . drill ] )
292301
293- // Move drill from remaining to completed
294- setRemainingDrills ( ( prev ) => prev . slice ( 1 ) )
295-
302+ // Don't remove from remaining drills here - do it in moveToNextDrill
303+ // This ensures proper counting for the performance modal
296304 setShowPerformanceModal ( true )
297305 } , [ currentDrillGame , evaluateDrillPerformance ] )
298306
@@ -302,14 +310,18 @@ export const useOpeningDrillController = (
302310 setCurrentPerformanceData ( null )
303311 setContinueAnalyzingMode ( false ) // Reset continue analyzing mode for next drill
304312
313+ // Remove the completed drill from remaining drills
314+ setRemainingDrills ( ( prev ) => prev . slice ( 1 ) )
315+
305316 const nextIndex = currentDrillIndex + 1
306317
307- // The drill has already been moved from remaining to completed in completeDrill()
318+ // Check if there are more drills to complete
308319 if ( nextIndex < configuration . drillSequence . length ) {
309320 setCurrentDrill ( configuration . drillSequence [ nextIndex ] )
310321 setCurrentDrillIndex ( nextIndex )
311322 } else {
312323 // All drills completed - show final modal
324+ setAllDrillsCompleted ( true )
313325 setShowFinalModal ( true )
314326 }
315327 } , [ currentDrillIndex , configuration . drillSequence ] )
@@ -321,6 +333,29 @@ export const useOpeningDrillController = (
321333 setContinueAnalyzingMode ( true ) // Allow moves beyond target count
322334 } , [ ] )
323335
336+ // Continue analyzing from final modal - just enable analysis mode
337+ const continueAnalyzingFromFinal = useCallback ( ( ) => {
338+ setShowFinalModal ( false )
339+ setAnalysisEnabled ( true ) // Auto-enable analysis
340+ setContinueAnalyzingMode ( true ) // Allow moves beyond target count
341+ } , [ ] )
342+
343+ // Reset drill session for new openings
344+ const resetDrillSession = useCallback ( ( ) => {
345+ setAllDrillsCompleted ( false )
346+ setRemainingDrills ( [ ] )
347+ setCompletedDrills ( [ ] )
348+ setCurrentDrill ( null )
349+ setCurrentDrillGame ( null )
350+ setCurrentDrillIndex ( 0 )
351+ setAnalysisEnabled ( false )
352+ setContinueAnalyzingMode ( false )
353+ setShowPerformanceModal ( false )
354+ setShowFinalModal ( false )
355+ setCurrentPerformanceData ( null )
356+ setWaitingForMaiaResponse ( false )
357+ } , [ ] )
358+
324359 // Calculate overall performance data
325360 const overallPerformanceData = useMemo ( ( ) : OverallPerformanceData => {
326361 if ( completedDrills . length === 0 ) {
@@ -722,6 +757,7 @@ export const useOpeningDrillController = (
722757 completeDrill,
723758 moveToNextDrill,
724759 continueAnalyzing,
760+ continueAnalyzingFromFinal,
725761
726762 // Analysis
727763 analysisEnabled,
@@ -733,5 +769,11 @@ export const useOpeningDrillController = (
733769 currentPerformanceData,
734770 overallPerformanceData,
735771 setShowFinalModal,
772+
773+ // Reset drill session
774+ resetDrillSession,
775+
776+ // Check if all drills are completed
777+ areAllDrillsCompleted,
736778 }
737779}
0 commit comments