@@ -8,11 +8,21 @@ import {
88 OpeningVariation ,
99 OpeningSelection ,
1010 DrillConfiguration ,
11+ EcoOpening ,
12+ EcoOpeningVariation ,
13+ EcoDatabase ,
14+ EcoSection ,
15+ PopularOpening ,
1116} from 'src/types'
1217import { ModalContainer } from '../Common/ModalContainer'
1318import { useTour } from 'src/contexts'
1419import { tourConfigs } from 'src/constants/tours'
1520import { WindowSizeContext } from 'src/contexts/WindowSizeContext'
21+ import EcoTreeView from './EcoTreeView'
22+ import {
23+ processEcoDatabase ,
24+ ecoToLegacyOpening ,
25+ } from 'src/lib/openings/ecoProcessor'
1626import {
1727 trackOpeningSelectionModalOpened ,
1828 trackOpeningSearchUsed ,
@@ -26,9 +36,11 @@ import { MAIA_MODELS_WITH_NAMES } from 'src/constants/common'
2636import { selectOpeningDrills } from 'src/api/opening'
2737
2838type MobileTab = 'browse' | 'selected'
39+ type ViewMode = 'simple' | 'eco'
2940
3041interface Props {
3142 openings : Opening [ ]
43+ ecoDatabase ?: EcoDatabase
3244 initialSelections ?: OpeningSelection [ ]
3345 onComplete : ( configuration : DrillConfiguration ) => void
3446 onClose : ( ) => void
@@ -791,6 +803,7 @@ const SelectedPanel: React.FC<{
791803
792804export const OpeningSelectionModal : React . FC < Props > = ( {
793805 openings,
806+ ecoDatabase,
794807 initialSelections = [ ] ,
795808 onComplete,
796809 onClose,
@@ -810,8 +823,24 @@ export const OpeningSelectionModal: React.FC<Props> = ({
810823 const [ drillCount , setDrillCount ] = useState ( 5 )
811824 const [ searchTerm , setSearchTerm ] = useState ( '' )
812825 const [ activeTab , setActiveTab ] = useState < MobileTab > ( 'browse' )
826+ const [ viewMode , setViewMode ] = useState < ViewMode > (
827+ ecoDatabase ? 'eco' : 'simple' ,
828+ )
813829 const [ initialTourCheck , setInitialTourCheck ] = useState ( false )
814830 const [ hasTrackedModalOpen , setHasTrackedModalOpen ] = useState ( false )
831+
832+ // ECO database processing
833+ const ecoData = useMemo ( ( ) => {
834+ if ( ! ecoDatabase ) return null
835+ return processEcoDatabase ( ecoDatabase )
836+ } , [ ecoDatabase ] )
837+
838+ // ECO preview state - initialize with first ECO opening if available
839+ const [ previewEcoOpening , setPreviewEcoOpening ] = useState < EcoOpening | null > (
840+ ecoData ?. sections ?. [ 0 ] ?. openings ?. [ 0 ] || null ,
841+ )
842+ const [ previewEcoVariation , setPreviewEcoVariation ] =
843+ useState < EcoOpeningVariation | null > ( null )
815844 const [ mobilePopupOpening , setMobilePopupOpening ] = useState < Opening | null > (
816845 null ,
817846 )
@@ -863,8 +892,60 @@ export const OpeningSelectionModal: React.FC<Props> = ({
863892 }
864893
865894 const previewFen = useMemo ( ( ) => {
895+ if ( viewMode === 'eco' && previewEcoOpening ) {
896+ return previewEcoVariation
897+ ? previewEcoVariation . fen
898+ : previewEcoOpening . fen
899+ }
866900 return previewVariation ? previewVariation . fen : previewOpening . fen
867- } , [ previewOpening , previewVariation ] )
901+ } , [
902+ previewOpening ,
903+ previewVariation ,
904+ previewEcoOpening ,
905+ previewEcoVariation ,
906+ viewMode ,
907+ ] )
908+
909+ // ECO selection handlers
910+ const handleEcoOpeningClick = (
911+ opening : EcoOpening ,
912+ variation ?: EcoOpeningVariation ,
913+ ) => {
914+ setPreviewEcoOpening ( opening )
915+ setPreviewEcoVariation ( variation || null )
916+ trackOpeningPreviewSelected (
917+ opening . name ,
918+ opening . id ,
919+ ! ! variation ,
920+ variation ?. name ,
921+ )
922+ }
923+
924+ const handleEcoQuickAdd = (
925+ opening : EcoOpening ,
926+ variation ?: EcoOpeningVariation ,
927+ ) => {
928+ const legacyOpening = ecoToLegacyOpening ( opening )
929+ const legacyVariation = variation
930+ ? {
931+ id : variation . id ,
932+ name : variation . name ,
933+ fen : variation . fen ,
934+ pgn : variation . pgn ,
935+ }
936+ : null
937+
938+ addQuickSelection ( legacyOpening , legacyVariation )
939+ }
940+
941+ const isEcoSelected = (
942+ opening : EcoOpening ,
943+ variation ?: EcoOpeningVariation ,
944+ ) => {
945+ return selections . some (
946+ ( s ) => s . opening . id === opening . id && s . variation ?. id === variation ?. id ,
947+ )
948+ }
868949
869950 const filteredOpenings = useMemo ( ( ) => {
870951 if ( ! searchTerm ) return openings
@@ -899,24 +980,40 @@ export const OpeningSelectionModal: React.FC<Props> = ({
899980 }
900981
901982 const addSelection = ( ) => {
902- if ( isDuplicateSelection ( previewOpening , previewVariation ) ) return
983+ // Handle ECO vs traditional opening selection
984+ const currentOpening =
985+ viewMode === 'eco' && previewEcoOpening
986+ ? ecoToLegacyOpening ( previewEcoOpening )
987+ : previewOpening
988+
989+ const currentVariation =
990+ viewMode === 'eco' && previewEcoVariation
991+ ? {
992+ id : previewEcoVariation . id ,
993+ name : previewEcoVariation . name ,
994+ fen : previewEcoVariation . fen ,
995+ pgn : previewEcoVariation . pgn ,
996+ }
997+ : previewVariation
998+
999+ if ( isDuplicateSelection ( currentOpening , currentVariation ) ) return
9031000
9041001 const newSelection : OpeningSelection = {
905- id : `${ previewOpening . id } -${ previewVariation ?. id || 'main' } -${ selectedColor } -${ selectedMaiaVersion . id } -${ targetMoveNumber } ` ,
906- opening : previewOpening ,
907- variation : previewVariation ,
1002+ id : `${ currentOpening . id } -${ currentVariation ?. id || 'main' } -${ selectedColor } -${ selectedMaiaVersion . id } -${ targetMoveNumber } ` ,
1003+ opening : currentOpening ,
1004+ variation : currentVariation ,
9081005 playerColor : selectedColor ,
9091006 maiaVersion : selectedMaiaVersion . id ,
9101007 targetMoveNumber,
9111008 }
9121009
9131010 // Track opening configuration and addition
9141011 trackOpeningConfiguredAndAdded (
915- previewOpening . name ,
1012+ currentOpening . name ,
9161013 selectedColor ,
9171014 selectedMaiaVersion . id ,
9181015 targetMoveNumber ,
919- previewVariation ?. name ,
1016+ currentVariation ?. name ,
9201017 )
9211018
9221019 setSelections ( [ ...selections , newSelection ] )
@@ -1178,6 +1275,32 @@ export const OpeningSelectionModal: React.FC<Props> = ({
11781275 your color and opponent strength.
11791276 </ p >
11801277 </ div >
1278+
1279+ { /* View Toggle */ }
1280+ { ecoDatabase && (
1281+ < div className = "flex items-center gap-2 rounded bg-background-2 p-1" >
1282+ < button
1283+ onClick = { ( ) => setViewMode ( 'simple' ) }
1284+ className = { `rounded px-3 py-1 text-sm font-medium transition-colors ${
1285+ viewMode === 'simple'
1286+ ? 'bg-human-4 text-white'
1287+ : 'text-secondary hover:text-primary'
1288+ } `}
1289+ >
1290+ Simple
1291+ </ button >
1292+ < button
1293+ onClick = { ( ) => setViewMode ( 'eco' ) }
1294+ className = { `rounded px-3 py-1 text-sm font-medium transition-colors ${
1295+ viewMode === 'eco'
1296+ ? 'bg-human-4 text-white'
1297+ : 'text-secondary hover:text-primary'
1298+ } `}
1299+ >
1300+ ECO Tree
1301+ </ button >
1302+ </ div >
1303+ ) }
11811304 </ div >
11821305 </ div >
11831306
@@ -1190,26 +1313,69 @@ export const OpeningSelectionModal: React.FC<Props> = ({
11901313
11911314 { /* Main Content - Responsive Layout */ }
11921315 < div className = "grid w-full flex-1 grid-cols-1 overflow-hidden md:grid-cols-3" >
1193- < BrowsePanel
1194- activeTab = { activeTab }
1195- filteredOpenings = { filteredOpenings }
1196- previewOpening = { previewOpening }
1197- previewVariation = { previewVariation }
1198- setPreviewOpening = { setPreviewOpening }
1199- setPreviewVariation = { setPreviewVariation }
1200- setActiveTab = { setActiveTab }
1201- addQuickSelection = { addQuickSelection }
1202- isDuplicateSelection = { isDuplicateSelection }
1203- searchTerm = { searchTerm }
1204- setSearchTerm = { setSearchTerm }
1205- selections = { selections }
1206- onOpeningClick = { handleMobileOpeningClick }
1207- removeSelection = { removeSelection }
1208- />
1316+ { viewMode === 'eco' && ecoData ? (
1317+ < div
1318+ className = { `flex w-full flex-col overflow-y-scroll ${ activeTab !== 'browse' ? 'hidden md:flex' : 'flex' } md:border-r md:border-white/10` }
1319+ >
1320+ < div className = "hidden h-20 flex-col justify-center gap-1 border-b border-white/10 p-4 md:flex" >
1321+ < h2 className = "text-xl font-bold" > ECO Opening Tree</ h2 >
1322+ < p className = "text-xs text-secondary" >
1323+ Browse openings organized by ECO classification
1324+ </ p >
1325+ </ div >
1326+
1327+ < div className = "flex h-16 flex-col justify-center gap-1 border-b border-white/10 p-4 md:hidden" >
1328+ < h2 className = "text-lg font-bold" > ECO Openings</ h2 >
1329+ < p className = "text-xs text-secondary" >
1330+ Choose from ECO database
1331+ </ p >
1332+ </ div >
1333+
1334+ < EcoTreeView
1335+ sections = { ecoData . sections }
1336+ popularOpenings = { ecoData . popularOpenings }
1337+ onOpeningClick = { handleEcoOpeningClick }
1338+ onQuickAdd = { handleEcoQuickAdd }
1339+ isSelected = { isEcoSelected }
1340+ searchTerm = { searchTerm }
1341+ setSearchTerm = { setSearchTerm }
1342+ />
1343+ </ div >
1344+ ) : (
1345+ < BrowsePanel
1346+ activeTab = { activeTab }
1347+ filteredOpenings = { filteredOpenings }
1348+ previewOpening = { previewOpening }
1349+ previewVariation = { previewVariation }
1350+ setPreviewOpening = { setPreviewOpening }
1351+ setPreviewVariation = { setPreviewVariation }
1352+ setActiveTab = { setActiveTab }
1353+ addQuickSelection = { addQuickSelection }
1354+ isDuplicateSelection = { isDuplicateSelection }
1355+ searchTerm = { searchTerm }
1356+ setSearchTerm = { setSearchTerm }
1357+ selections = { selections }
1358+ onOpeningClick = { handleMobileOpeningClick }
1359+ removeSelection = { removeSelection }
1360+ />
1361+ ) }
12091362 < PreviewPanel
12101363 selections = { selections }
1211- previewOpening = { previewOpening }
1212- previewVariation = { previewVariation }
1364+ previewOpening = {
1365+ viewMode === 'eco' && previewEcoOpening
1366+ ? ecoToLegacyOpening ( previewEcoOpening )
1367+ : previewOpening
1368+ }
1369+ previewVariation = {
1370+ viewMode === 'eco' && previewEcoVariation
1371+ ? {
1372+ id : previewEcoVariation . id ,
1373+ name : previewEcoVariation . name ,
1374+ fen : previewEcoVariation . fen ,
1375+ pgn : previewEcoVariation . pgn ,
1376+ }
1377+ : previewVariation
1378+ }
12131379 previewFen = { previewFen }
12141380 selectedColor = { selectedColor }
12151381 setSelectedColor = { setSelectedColor }
0 commit comments