11import { Chess } from 'chess.ts'
22import { useMemo , Dispatch , SetStateAction } from 'react'
33
4- import { Markdown } from 'src/components'
54import { useTrainingController } from 'src/hooks'
65import { PuzzleGame , Status } from 'src/types/puzzle'
76
@@ -14,6 +13,7 @@ interface Props {
1413 controller : ReturnType < typeof useTrainingController >
1514 lastAttemptedMove : string | null
1615 setLastAttemptedMove : Dispatch < SetStateAction < string | null > >
16+ solutionMoveSan : string | null
1717 embedded ?: boolean
1818}
1919
@@ -26,81 +26,91 @@ export const Feedback: React.FC<Props> = ({
2626 controller : controller ,
2727 lastAttemptedMove,
2828 setLastAttemptedMove,
29+ solutionMoveSan,
2930 embedded = false ,
3031} : Props ) => {
31- const { targetIndex } = game
32-
3332 const turn =
3433 new Chess ( controller . gameTree . getLastMainlineNode ( ) . fen ) . turn ( ) === 'w'
3534 ? 'white'
3635 : 'black'
3736
38- const archivedContent = `
39- ##### PUZZLE COMPLETED
40- You already solved this puzzle. Use the boxes on the left to navigate to another puzzle.
41- `
37+ const content = useMemo ( ( ) => {
38+ if ( status === 'archived' ) {
39+ return {
40+ titlePrefix : null ,
41+ title : 'You already solved this puzzle.' ,
42+ detail : 'Choose another puzzle from the history list.' ,
43+ titleClass : 'text-primary' ,
44+ accentPrefixClass : '' ,
45+ }
46+ }
4247
43- const defaultContent = `
44- ##### YOUR TURN
45- Find the best move for **${ turn } **!
46- `
47- const incorrectContent = `
48- ##### ${ lastAttemptedMove || 'Move' } is incorrect
49- Try again or give up to analyze the board and see the best move.
50- `
48+ if ( status === 'forfeit' ) {
49+ return {
50+ titlePrefix : null ,
51+ title : `${ solutionMoveSan || 'That move' } is the best move.` ,
52+ detail : 'Explore the position or try the next puzzle.' ,
53+ titleClass : 'text-primary' ,
54+ accentPrefixClass : '' ,
55+ }
56+ }
5157
52- const correctContent = `
53- ##### Correct! ${ lastAttemptedMove || 'Move' } is the best move.
54- You can now explore and analyze the position by making moves, or train on another position.
55- `
58+ if ( status === 'correct' ) {
59+ return {
60+ titlePrefix : 'Correct!' ,
61+ title : ` ${ lastAttemptedMove || 'That move' } is the best move.` ,
62+ detail : 'Explore the position or try the next puzzle.' ,
63+ titleClass : 'text-primary' ,
64+ accentPrefixClass : 'text-green-400' ,
65+ }
66+ }
5667
57- const gaveUpContent = `
58- ##### Explore the position
59- Explore the current position by making moves or train on another position.`
68+ if ( status === 'incorrect' ) {
69+ return {
70+ titlePrefix : 'Incorrect.' ,
71+ title : ` ${ lastAttemptedMove || 'That move' } is not the best move.` ,
72+ detail : 'Try again or give up to unlock analysis.' ,
73+ titleClass : 'text-primary' ,
74+ accentPrefixClass : 'text-human-2' ,
75+ }
76+ }
6077
61- const content = useMemo ( ( ) => {
62- if ( status === 'archived' ) {
63- return archivedContent
64- } else if ( status === 'forfeit' ) {
65- return gaveUpContent
66- } else if ( status === 'correct' ) {
67- return correctContent
68- } else if ( status === 'incorrect' ) {
69- return incorrectContent
70- } else {
71- return defaultContent
78+ return {
79+ titlePrefix : null ,
80+ title : `Find the best move for ${ turn } .` ,
81+ detail : 'Give up if you want to reveal the answer and analyze it.' ,
82+ titleClass : 'text-primary' ,
83+ accentPrefixClass : '' ,
7284 }
73- } , [ defaultContent , incorrectContent , correctContent , status , targetIndex ] )
85+ } , [ lastAttemptedMove , solutionMoveSan , status , turn ] )
7486
7587 return (
7688 < div
7789 className = {
7890 embedded
7991 ? 'flex w-screen flex-1 flex-col border-t border-glass-border bg-transparent p-3 md:w-auto md:p-5 lg:justify-between'
80- : 'flex w-screen flex-1 flex- col rounded-md border border-glass-border bg-glass p-3 backdrop-blur-md md:w-auto md:p-5 lg:justify-between '
92+ : 'flex w-screen flex-col rounded-md border border-glass-border bg-glass p-4 shadow-[0_12px_32px_rgb(0_0_0_/_0.14)] backdrop-blur-md md:w-auto'
8193 }
8294 >
83- < div >
84- < Markdown > { content . trim ( ) } </ Markdown >
85- { ( status === 'forfeit' || status === 'correct' ) && (
86- < div className = "mt-4 flex items-start gap-2" >
87- < div className = "flex items-center gap-0.5" >
88- < span className = "material-symbols-outlined !text-xs text-human-3" >
89- arrow_outward
90- </ span >
91- < span className = "text-xs text-human-3" > Most Human Move</ span >
92- </ div >
93- < div className = "flex items-center gap-0.5" >
94- < span className = "material-symbols-outlined !text-xs text-engine-3" >
95- arrow_outward
95+ < div className = "flex flex-col gap-3" >
96+ < div className = "space-y-2" >
97+ < h3
98+ className = { `text-[1.6rem] font-semibold leading-tight ${ content . titleClass } ` }
99+ >
100+ { content . titlePrefix ? (
101+ < span className = { content . accentPrefixClass } >
102+ { content . titlePrefix }
96103 </ span >
97- < span className = "text-xs text-engine-3" > Best Engine Move</ span >
98- </ div >
99- </ div >
100- ) }
104+ ) : null }
105+ { content . title }
106+ </ h3 >
107+ < p className = "max-w-[32ch] text-sm leading-6 text-secondary/75" >
108+ { content . detail }
109+ </ p >
110+ </ div >
101111 </ div >
102112
103- < div className = "mt-2 flex min-w-32 flex-row gap-1.5 lg:mt-0 lg:flex-col" >
113+ < div className = "mt-4 flex min-w-32 flex-row gap-1.5 lg:flex-col" >
104114 { status !== 'archived' && (
105115 < >
106116 { status === 'incorrect' && (
@@ -110,15 +120,15 @@ export const Feedback: React.FC<Props> = ({
110120 setLastAttemptedMove ( null )
111121 controller . reset ( )
112122 } }
113- className = "flex w-full justify-center rounded-sm bg-engine-3 py-1.5 text-sm font-medium text-primary transition duration-300 hover:bg-engine-4 disabled:bg-backdrop disabled:text-secondary"
123+ className = "flex w-full justify-center rounded-md border border-engine-4/40 bg-engine-4/15 py-2 text-sm font-medium text-primary transition duration-300 hover:bg-engine-4/25 disabled:bg-backdrop disabled:text-secondary"
114124 >
115125 Try Again
116126 </ button >
117127 ) }
118128 { status !== 'forfeit' && status !== 'correct' && (
119129 < button
120130 onClick = { setAndGiveUp }
121- className = "flex w-full justify-center rounded-sm bg-human-3 py-1.5 text-sm font-medium text-primary transition duration-300 hover:bg-human-4 disabled:bg-backdrop disabled:text-secondary"
131+ className = "flex w-full justify-center rounded-md bg-human-3 py-2 text-sm font-medium text-primary transition duration-300 hover:bg-human-4 disabled:bg-backdrop disabled:text-secondary"
122132 >
123133 Give Up
124134 </ button >
@@ -128,7 +138,7 @@ export const Feedback: React.FC<Props> = ({
128138 onClick = { async ( ) => {
129139 await getNewGame ( )
130140 } }
131- className = "flex w-full justify-center rounded-sm bg-human-3 py-1.5 text-sm font-medium text-primary transition duration-300 hover:bg-human-4 disabled:bg-backdrop disabled:text-secondary"
141+ className = "flex w-full justify-center rounded-md bg-human-3 py-2 text-sm font-medium text-primary transition duration-300 hover:bg-human-4 disabled:bg-backdrop disabled:text-secondary"
132142 >
133143 Next Puzzle
134144 </ button >
0 commit comments