@@ -58,6 +58,30 @@ export const AnalysisGameList: React.FC<AnalysisGameListProps> = ({
5858 const [ localHandGames , setLocalHandGames ] = useState ( analysisHandList )
5959 const [ localBrainGames , setLocalBrainGames ] = useState ( analysisBrainList )
6060
61+ const [ fetchedCache , setFetchedCache ] = useState < {
62+ [ key : string ] : { [ page : number ] : boolean }
63+ } > ( {
64+ play : { } ,
65+ hand : { } ,
66+ brain : { } ,
67+ pgn : { } ,
68+ tournament : { } ,
69+ } )
70+
71+ const [ totalPagesCache , setTotalPagesCache ] = useState < {
72+ [ key : string ] : number
73+ } > ( { } )
74+
75+ const [ currentPagePerTab , setCurrentPagePerTab ] = useState < {
76+ [ key : string ] : number
77+ } > ( {
78+ play : 1 ,
79+ hand : 1 ,
80+ brain : 1 ,
81+ pgn : 1 ,
82+ tournament : 1 ,
83+ } )
84+
6185 const listKeys = useMemo ( ( ) => {
6286 return analysisTournamentList
6387 ? Array . from ( analysisTournamentList . keys ( ) ) . sort (
@@ -95,56 +119,104 @@ export const AnalysisGameList: React.FC<AnalysisGameListProps> = ({
95119
96120 useEffect ( ( ) => {
97121 if ( selected !== 'tournament' && selected !== 'pgn' ) {
98- setLoading ( true )
99- getAnalysisGameList ( selected , currentPage ) . then ( ( data ) => {
100- const parse = (
101- game : {
102- game_id : string
103- maia_name : string
104- result : string
105- player_color : 'white' | 'black'
106- } ,
107- type : string ,
108- ) => {
109- const raw = game . maia_name . replace ( '_kdd_' , ' ' )
110- const maia = raw . charAt ( 0 ) . toUpperCase ( ) + raw . slice ( 1 )
122+ const isAlreadyFetched = fetchedCache [ selected ] ?. [ currentPage ]
123+
124+ if ( ! isAlreadyFetched ) {
125+ setLoading ( true )
126+
127+ setFetchedCache ( ( prev ) => ( {
128+ ...prev ,
129+ [ selected ] : { ...prev [ selected ] , [ currentPage ] : true } ,
130+ } ) )
131+
132+ getAnalysisGameList ( selected , currentPage )
133+ . then ( ( data ) => {
134+ const parse = (
135+ game : {
136+ game_id : string
137+ maia_name : string
138+ result : string
139+ player_color : 'white' | 'black'
140+ } ,
141+ type : string ,
142+ ) => {
143+ const raw = game . maia_name . replace ( '_kdd_' , ' ' )
144+ const maia = raw . charAt ( 0 ) . toUpperCase ( ) + raw . slice ( 1 )
145+
146+ return {
147+ id : game . game_id ,
148+ label :
149+ game . player_color === 'white'
150+ ? `You vs. ${ maia } `
151+ : `${ maia } vs. You` ,
152+ result : game . result ,
153+ type,
154+ }
155+ }
111156
112- return {
113- id : game . game_id ,
114- label :
115- game . player_color === 'white'
116- ? `You vs. ${ maia } `
117- : `${ maia } vs. You` ,
118- result : game . result ,
119- type,
120- }
121- }
157+ const parsedGames = data . games . map ( ( game : GameData ) =>
158+ parse ( game , selected ) ,
159+ )
160+ const calculatedTotalPages = Math . ceil ( data . total / 100 )
122161
123- if ( selected === 'play' ) {
124- setLocalPlayGames (
125- data . games . map ( ( game : GameData ) => parse ( game , 'play' ) ) ,
126- )
127- } else if ( selected === 'hand' ) {
128- setLocalHandGames (
129- data . games . map ( ( game : GameData ) => parse ( game , 'hand' ) ) ,
130- )
131- } else if ( selected === 'brain' ) {
132- setLocalBrainGames (
133- data . games . map ( ( game : GameData ) => parse ( game , 'brain' ) ) ,
134- )
135- }
136- setTotalPages ( Math . ceil ( data . total / 100 ) )
137- setLoading ( false )
138- } )
162+ setTotalPagesCache ( ( prev ) => ( {
163+ ...prev ,
164+ [ selected ] : calculatedTotalPages ,
165+ } ) )
166+
167+ if ( selected === 'play' ) {
168+ setLocalPlayGames ( ( prev ) =>
169+ currentPage === 1 ? parsedGames : [ ...prev , ...parsedGames ] ,
170+ )
171+ } else if ( selected === 'hand' ) {
172+ setLocalHandGames ( ( prev ) =>
173+ currentPage === 1 ? parsedGames : [ ...prev , ...parsedGames ] ,
174+ )
175+ } else if ( selected === 'brain' ) {
176+ setLocalBrainGames ( ( prev ) =>
177+ currentPage === 1 ? parsedGames : [ ...prev , ...parsedGames ] ,
178+ )
179+ }
180+ setLoading ( false )
181+ } )
182+ . catch ( ( ) => {
183+ setFetchedCache ( ( prev ) => {
184+ const newCache = { ...prev }
185+ delete newCache [ selected ] [ currentPage ]
186+ return newCache
187+ } )
188+ setLoading ( false )
189+ } )
190+ }
191+ }
192+ } , [ selected , currentPage , fetchedCache ] )
193+
194+ useEffect ( ( ) => {
195+ if ( totalPagesCache [ selected ] ) {
196+ setTotalPages ( totalPagesCache [ selected ] )
197+ } else if ( selected === 'pgn' || selected === 'tournament' ) {
198+ setTotalPages ( 1 )
139199 }
140- } , [ selected , currentPage ] )
200+
201+ setCurrentPage ( currentPagePerTab [ selected ] )
202+ } , [ selected , totalPagesCache , currentPagePerTab ] )
141203
142204 const handlePageChange = ( newPage : number ) => {
143205 if ( newPage >= 1 && newPage <= totalPages ) {
144206 setCurrentPage ( newPage )
207+ setCurrentPagePerTab ( ( prev ) => ( {
208+ ...prev ,
209+ [ selected ] : newPage ,
210+ } ) )
145211 }
146212 }
147213
214+ const handleTabChange = (
215+ newTab : 'tournament' | 'play' | 'hand' | 'brain' | 'pgn' ,
216+ ) => {
217+ setSelected ( newTab )
218+ }
219+
148220 return analysisTournamentList ? (
149221 < div className = "flex h-full flex-col items-start justify-start overflow-hidden bg-background-1 md:rounded" >
150222 < div className = "flex h-full w-full flex-col" >
@@ -153,31 +225,31 @@ export const AnalysisGameList: React.FC<AnalysisGameListProps> = ({
153225 label = "Play"
154226 name = "play"
155227 selected = { selected }
156- setSelected = { setSelected }
228+ setSelected = { handleTabChange }
157229 />
158230 < Header
159231 label = "Hand"
160232 name = "hand"
161233 selected = { selected }
162- setSelected = { setSelected }
234+ setSelected = { handleTabChange }
163235 />
164236 < Header
165237 label = "Brain"
166238 name = "brain"
167239 selected = { selected }
168- setSelected = { setSelected }
240+ setSelected = { handleTabChange }
169241 />
170242 < Header
171243 label = "Lichess"
172244 name = "pgn"
173245 selected = { selected }
174- setSelected = { setSelected }
246+ setSelected = { handleTabChange }
175247 />
176248 < Header
177249 label = "WC"
178250 name = "tournament"
179251 selected = { selected }
180- setSelected = { setSelected }
252+ setSelected = { handleTabChange }
181253 />
182254 </ div >
183255 < div className = "red-scrollbar flex h-full flex-col overflow-y-scroll" >
0 commit comments