Skip to content

Commit da0e8f4

Browse files
feat: enhance opening drill functionality with new drill performance tracking, target move count configuration, and improved UI components
1 parent e6384a6 commit da0e8f4

9 files changed

Lines changed: 1381 additions & 622 deletions

File tree

src/components/Board/BoardController.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ interface Props {
1515
gameTree: GameTree
1616
setCurrentMove?: (move: [string, string] | null) => void
1717
disableFlip?: boolean
18+
disablePrevious?: boolean
1819
}
1920

2021
export const BoardController: React.FC<Props> = ({
@@ -29,6 +30,7 @@ export const BoardController: React.FC<Props> = ({
2930
gameTree,
3031
setCurrentMove,
3132
disableFlip = false,
33+
disablePrevious = false,
3234
}: Props) => {
3335
const { width } = useWindowSize()
3436

@@ -84,7 +86,7 @@ export const BoardController: React.FC<Props> = ({
8486
switch (e.key) {
8587
case 'Left':
8688
case 'ArrowLeft':
87-
if (hasPrevious) getPrevious()
89+
if (hasPrevious && !disablePrevious) getPrevious()
8890
break
8991
case 'Right':
9092
case 'ArrowRight':
@@ -96,7 +98,7 @@ export const BoardController: React.FC<Props> = ({
9698
break
9799
case 'Up':
98100
case 'ArrowUp':
99-
if (hasPrevious) getFirst()
101+
if (hasPrevious && !disablePrevious) getFirst()
100102
break
101103
case 'f':
102104
if (!disableFlip) toggleBoardOrientation()
@@ -116,6 +118,7 @@ export const BoardController: React.FC<Props> = ({
116118
getFirst,
117119
getLast,
118120
toggleBoardOrientation,
121+
disablePrevious,
119122
])
120123

121124
return (
@@ -129,14 +132,14 @@ export const BoardController: React.FC<Props> = ({
129132
</button>
130133
<button
131134
onClick={getFirst}
132-
disabled={!hasPrevious}
135+
disabled={!hasPrevious || disablePrevious}
133136
className="flex h-7 flex-1 items-center justify-center bg-button-secondary transition duration-200 hover:bg-human-3 disabled:bg-button-secondary/40 md:rounded-sm"
134137
>
135138
&#8249;&#8249;&#8249;
136139
</button>
137140
<button
138141
onClick={getPrevious}
139-
disabled={!hasPrevious}
142+
disabled={!hasPrevious || disablePrevious}
140143
className="flex h-7 flex-1 items-center justify-center bg-button-secondary transition duration-200 hover:bg-human-3 disabled:bg-button-secondary/40 md:rounded-sm"
141144
>
142145
&#8249;
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import React from 'react'
2+
import { AnimatePresence, motion } from 'framer-motion'
3+
import { ModalContainer } from '../Misc'
4+
import { DrillPerformanceData } from 'src/types/openings'
5+
6+
interface Props {
7+
performanceData: DrillPerformanceData
8+
onContinueAnalyzing: () => void
9+
onNextDrill: () => void
10+
isLastDrill: boolean
11+
}
12+
13+
export const DrillPerformanceModal: React.FC<Props> = ({
14+
performanceData,
15+
onContinueAnalyzing,
16+
onNextDrill,
17+
isLastDrill,
18+
}) => {
19+
const {
20+
drill,
21+
evaluationChart,
22+
accuracy,
23+
blunderCount,
24+
goodMoveCount,
25+
feedback,
26+
} = performanceData
27+
28+
return (
29+
<ModalContainer dismiss={onContinueAnalyzing}>
30+
<motion.div
31+
initial={{ opacity: 0, scale: 0.95 }}
32+
animate={{ opacity: 1, scale: 1 }}
33+
exit={{ opacity: 0, scale: 0.95 }}
34+
className="relative flex h-[80vh] max-h-[600px] w-[90vw] max-w-[800px] flex-col overflow-hidden rounded-lg bg-background-1 shadow-2xl"
35+
>
36+
{/* Header */}
37+
<div className="flex items-center justify-between border-b border-white/10 p-6">
38+
<div>
39+
<h2 className="text-2xl font-bold text-primary">Drill Complete!</h2>
40+
<p className="text-sm text-secondary">
41+
{drill.selection.opening.name}
42+
{drill.selection.variation &&
43+
` - ${drill.selection.variation.name}`}
44+
</p>
45+
</div>
46+
<button
47+
onClick={onContinueAnalyzing}
48+
className="text-secondary hover:text-primary"
49+
>
50+
<span className="material-symbols-outlined">close</span>
51+
</button>
52+
</div>
53+
54+
{/* Content */}
55+
<div className="flex flex-1 overflow-hidden">
56+
{/* Left Panel - Stats */}
57+
<div className="flex w-1/2 flex-col gap-4 border-r border-white/10 p-6">
58+
<div className="grid grid-cols-2 gap-4">
59+
<div className="rounded bg-background-2 p-4 text-center">
60+
<p className="text-2xl font-bold text-human-4">
61+
{Math.round(accuracy)}%
62+
</p>
63+
<p className="text-sm text-secondary">Accuracy</p>
64+
</div>
65+
<div className="rounded bg-background-2 p-4 text-center">
66+
<p className="text-2xl font-bold text-primary">
67+
{drill.totalMoves}
68+
</p>
69+
<p className="text-sm text-secondary">Moves Played</p>
70+
</div>
71+
<div className="rounded bg-background-2 p-4 text-center">
72+
<p className="text-2xl font-bold text-green-400">
73+
{goodMoveCount}
74+
</p>
75+
<p className="text-sm text-secondary">Good Moves</p>
76+
</div>
77+
<div className="rounded bg-background-2 p-4 text-center">
78+
<p className="text-2xl font-bold text-red-400">
79+
{blunderCount}
80+
</p>
81+
<p className="text-sm text-secondary">Blunders</p>
82+
</div>
83+
</div>
84+
85+
{/* Evaluation Chart Placeholder */}
86+
<div className="flex-1 rounded bg-background-2 p-4">
87+
<h3 className="mb-2 text-sm font-medium">Position Evaluation</h3>
88+
<div className="flex h-full items-center justify-center text-secondary">
89+
{/* Simple text representation for now */}
90+
<div className="text-center">
91+
<p className="text-sm">Final Position:</p>
92+
<p className="text-lg font-bold">
93+
{drill.finalEvaluation > 0 ? '+' : ''}
94+
{(drill.finalEvaluation / 100).toFixed(2)}
95+
</p>
96+
</div>
97+
</div>
98+
</div>
99+
</div>
100+
101+
{/* Right Panel - Feedback */}
102+
<div className="flex w-1/2 flex-col gap-4 p-6">
103+
<h3 className="text-lg font-semibold">Performance Feedback</h3>
104+
<div className="flex-1 space-y-3 overflow-y-auto">
105+
{feedback.map((item, index) => (
106+
<div key={index} className="rounded bg-background-2 p-3">
107+
<p className="text-sm text-primary">{item}</p>
108+
</div>
109+
))}
110+
{feedback.length === 0 && (
111+
<p className="text-center text-secondary">
112+
Great job completing this opening drill!
113+
</p>
114+
)}
115+
</div>
116+
117+
{/* Notable Moves */}
118+
<div className="space-y-2">
119+
{drill.goodMoves.length > 0 && (
120+
<div>
121+
<h4 className="text-sm font-medium text-green-400">
122+
Best Moves: {drill.goodMoves.slice(0, 3).join(', ')}
123+
</h4>
124+
</div>
125+
)}
126+
{drill.blunders.length > 0 && (
127+
<div>
128+
<h4 className="text-sm font-medium text-red-400">
129+
Blunders: {drill.blunders.slice(0, 3).join(', ')}
130+
</h4>
131+
</div>
132+
)}
133+
</div>
134+
</div>
135+
</div>
136+
137+
{/* Action Buttons */}
138+
<div className="flex gap-3 border-t border-white/10 p-6">
139+
<button
140+
onClick={onContinueAnalyzing}
141+
className="flex-1 rounded bg-background-2 py-3 font-medium transition-colors hover:bg-background-3"
142+
>
143+
Continue Analyzing
144+
</button>
145+
<button
146+
onClick={onNextDrill}
147+
className="flex-1 rounded bg-human-4 py-3 font-medium transition-colors hover:bg-human-4/80"
148+
>
149+
{isLastDrill ? 'View Summary' : 'Next Drill'}
150+
</button>
151+
</div>
152+
</motion.div>
153+
</ModalContainer>
154+
)
155+
}

0 commit comments

Comments
 (0)