Skip to content

Commit 25ad9de

Browse files
feat: improve drill ending functionality
1 parent 6828b76 commit 25ad9de

3 files changed

Lines changed: 84 additions & 50 deletions

File tree

src/components/Openings/OpeningDrillSidebar.tsx

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ export const OpeningDrillSidebar: React.FC<Props> = ({
5959
<div className="mt-3 flex gap-2">
6060
<button
6161
onClick={onResetCurrentDrill}
62-
className="flex-1 rounded bg-background-2 px-3 py-1 text-xs transition-colors hover:bg-background-3"
62+
className="w-full rounded bg-background-2 py-1 text-xs transition-colors hover:bg-background-3"
6363
>
64-
Reset
64+
Reset Drill
6565
</button>
6666
{onChangeSelections && (
6767
<button
6868
onClick={onChangeSelections}
69-
className="flex-1 rounded bg-background-2 px-3 py-1 text-xs transition-colors hover:bg-background-3"
69+
className="w-full rounded bg-background-2 py-1 text-xs transition-colors hover:bg-background-3"
7070
>
7171
Change
7272
</button>
@@ -81,25 +81,14 @@ export const OpeningDrillSidebar: React.FC<Props> = ({
8181
{/* Drill Progress */}
8282
<div className="border-b border-white/10 p-4">
8383
<h3 className="mb-2 text-sm font-medium text-primary">
84-
Drill Progress
84+
Completed Drills ({completedDrills.length})
8585
</h3>
8686
<div className="space-y-2">
8787
<div className="flex justify-between text-xs">
88-
<span className="text-secondary">Current Drill</span>
88+
<span className="text-secondary">Drill Progress</span>
8989
<span className="font-medium text-human-4">
90-
{currentDrillIndex + 1} of {totalDrills}
91-
</span>
92-
</div>
93-
<div className="flex justify-between text-xs">
94-
<span className="text-secondary">Completed</span>
95-
<span className="font-medium text-green-400">
96-
{completedDrills.length}
97-
</span>
98-
</div>
99-
<div className="flex justify-between text-xs">
100-
<span className="text-secondary">Remaining</span>
101-
<span className="font-medium text-yellow-400">
102-
{totalDrills - completedDrills.length}
90+
{Math.min(completedDrills.length + 1, totalDrills)} of{' '}
91+
{totalDrills}
10392
</span>
10493
</div>
10594
<div className="h-2 w-full rounded bg-background-2">
@@ -108,7 +97,10 @@ export const OpeningDrillSidebar: React.FC<Props> = ({
10897
style={{
10998
width: `${
11099
totalDrills > 0
111-
? (completedDrills.length / totalDrills) * 100
100+
? Math.min(
101+
(completedDrills.length / totalDrills) * 100,
102+
100,
103+
)
112104
: 0
113105
}%`,
114106
}}
@@ -118,10 +110,7 @@ export const OpeningDrillSidebar: React.FC<Props> = ({
118110
</div>
119111

120112
{/* Completed Drills List */}
121-
<div className="flex h-96 flex-col overflow-hidden">
122-
<h3 className="p-3 text-sm font-medium text-primary">
123-
Completed Drills ({completedDrills.length})
124-
</h3>
113+
<div className="flex h-64 flex-col overflow-hidden">
125114
<div className="red-scrollbar flex h-full flex-col overflow-y-auto">
126115
{completedDrills.length === 0 ? (
127116
<div className="flex h-full items-center justify-center">
@@ -144,7 +133,7 @@ export const OpeningDrillSidebar: React.FC<Props> = ({
144133
return (
145134
<div
146135
key={completedDrill.selection.id}
147-
className="bg-background-2 p-2 transition-colors hover:bg-background-3"
136+
className="border-b border-white/5 bg-background-1 px-3 py-2 transition-colors"
148137
>
149138
<div className="flex items-start justify-between">
150139
<div className="min-w-0 flex-1">

src/hooks/useOpeningDrillController/useOpeningDrillController.ts

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

src/pages/openings/index.tsx

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,9 @@ const OpeningsPage: NextPage = () => {
258258
)
259259

260260
const handleChangeSelections = useCallback(() => {
261+
controller.resetDrillSession()
261262
setShowSelectionModal(true)
262-
}, [])
263+
}, [controller])
263264

264265
// No-op function for disabling orientation changes
265266
const noOpSetOrientation = useCallback((_orientation: 'white' | 'black') => {
@@ -486,14 +487,15 @@ const OpeningsPage: NextPage = () => {
486487
/>
487488
</div>
488489
</div>
489-
{controller.remainingDrills.length > 1 && (
490-
<button
491-
onClick={controller.moveToNextDrill}
492-
className="rounded bg-human-4 px-4 py-2 text-sm font-medium transition-colors hover:bg-human-4/80"
493-
>
494-
Next Drill
495-
</button>
496-
)}
490+
{controller.remainingDrills.length > 1 &&
491+
!controller.areAllDrillsCompleted && (
492+
<button
493+
onClick={controller.moveToNextDrill}
494+
className="rounded bg-human-4 px-4 py-2 text-sm font-medium transition-colors hover:bg-human-4/80"
495+
>
496+
Next Drill
497+
</button>
498+
)}
497499
</div>
498500
)}
499501
</div>
@@ -571,14 +573,15 @@ const OpeningsPage: NextPage = () => {
571573
>
572574
Change Openings
573575
</button>
574-
{controller.remainingDrills.length > 1 && (
575-
<button
576-
onClick={controller.moveToNextDrill}
577-
className="rounded bg-human-4 px-4 py-2 text-sm font-medium"
578-
>
579-
Next
580-
</button>
581-
)}
576+
{controller.remainingDrills.length > 1 &&
577+
!controller.areAllDrillsCompleted && (
578+
<button
579+
onClick={controller.moveToNextDrill}
580+
className="rounded bg-human-4 px-4 py-2 text-sm font-medium"
581+
>
582+
Next
583+
</button>
584+
)}
582585
</div>
583586

584587
{/* Mobile progress */}
@@ -644,7 +647,7 @@ const OpeningsPage: NextPage = () => {
644647
performanceData={controller.overallPerformanceData}
645648
onContinueAnalyzing={controller.continueAnalyzingFromFinal}
646649
onSelectNewOpenings={() => {
647-
controller.setShowFinalModal(false)
650+
controller.resetDrillSession()
648651
setShowSelectionModal(true)
649652
}}
650653
/>

0 commit comments

Comments
 (0)