@@ -3,13 +3,14 @@ import Sidebar from "@/components/sidebar";
33import DTable from "@/components/table" ;
44import DetailModal from "@/components/modal" ;
55import Cards from "@/components/cards" ;
6- import { useEffect , useState } from "react" ;
6+ import { useEffect , useState , useRef } from "react" ;
77import { Spinner , Toast , ToastContainer } from "react-bootstrap" ;
88import { getCardData , getTableData , getModalData , Config } from "@/components/api" ;
99
1010export default function Home ( ) {
1111 const [ state , setState ] = useState ( {
1212 loading : true ,
13+ tableLoading : false ,
1314 cardData : { } ,
1415 category : 0 ,
1516 tablePage : 0 ,
@@ -31,8 +32,15 @@ export default function Home() {
3132 } ,
3233 } ) ;
3334
34- function getCardAndTableData ( setLoading ) {
35- Promise . allSettled ( [ getTableData ( state . tablePage , state . category , state . committee ) , getCardData ( ) , Config ( ) ] ) . then (
35+ const autoRefreshingRef = useRef ( false ) ;
36+
37+ const stateRef = useRef ( state ) ;
38+ const lastUserActionRef = useRef ( 0 ) ;
39+ const autoRefreshVersionRef = useRef ( 0 ) ;
40+ stateRef . current = state ;
41+
42+ function getCardAndTableData ( setLoading , currentState = state ) {
43+ Promise . allSettled ( [ getTableData ( currentState . tablePage , currentState . category , currentState . committee ) , getCardData ( ) , Config ( ) ] ) . then (
3644 ( values ) => {
3745 let settledValues = [ ] ;
3846 for ( const v of values ) {
@@ -53,21 +61,44 @@ export default function Home() {
5361 settledValues [ 2 ] . precommitVoteTimeoutMS +
5462 settledValues [ 2 ] . commitTimeoutMS ;
5563
56- if ( setLoading ) {
57- return setState ( {
58- ...state ,
59- loading : false ,
60- tableData : settledValues [ 0 ] ,
61- cardData : settledValues [ 1 ] ,
62- consensusDuration : consensusDuration ,
63- } ) ;
64- }
65- return setState ( {
66- ...state ,
64+ setState ( prevState => ( {
65+ ...prevState ,
66+ loading : setLoading ? false : prevState . loading ,
6767 tableData : settledValues [ 0 ] ,
6868 cardData : settledValues [ 1 ] ,
6969 consensusDuration : consensusDuration ,
70- } ) ;
70+ } ) ) ;
71+ } ,
72+ ) ;
73+ }
74+
75+ function getCardDataOnly ( ) {
76+ Promise . allSettled ( [ getCardData ( ) , Config ( ) ] ) . then (
77+ ( values ) => {
78+ let settledValues = [ ] ;
79+ for ( const v of values ) {
80+ if ( v . status === "rejected" ) {
81+ settledValues . push ( { } ) ;
82+ continue ;
83+ }
84+ settledValues . push ( v . value ) ;
85+ }
86+
87+ const consensusDuration =
88+ settledValues [ 1 ] . newHeightTimeoutMS +
89+ settledValues [ 1 ] . electionTimeoutMS +
90+ settledValues [ 1 ] . electionVoteTimeoutMS +
91+ settledValues [ 1 ] . proposeTimeoutMS +
92+ settledValues [ 1 ] . proposeVoteTimeoutMS +
93+ settledValues [ 1 ] . precommitTimeoutMS +
94+ settledValues [ 1 ] . precommitVoteTimeoutMS +
95+ settledValues [ 1 ] . commitTimeoutMS ;
96+
97+ setState ( prevState => ( {
98+ ...prevState ,
99+ cardData : settledValues [ 0 ] ,
100+ consensusDuration : consensusDuration ,
101+ } ) ) ;
71102 } ,
72103 ) ;
73104 }
@@ -90,21 +121,84 @@ export default function Home() {
90121 if ( committee == null ) {
91122 committee = state . committee ;
92123 }
93- setState ( {
94- ...state ,
124+
125+ // Mark user action timestamp and invalidate auto-refresh promises
126+ lastUserActionRef . current = Date . now ( ) ;
127+ autoRefreshVersionRef . current += 1 ;
128+ autoRefreshingRef . current = false ; // Cancel any ongoing auto-refresh
129+
130+ // Set table loading state and update page/category immediately
131+ setState ( prevState => ( {
132+ ...prevState ,
95133 committee : committee ,
96134 category : category ,
97135 tablePage : page ,
98- tableData : await getTableData ( page , category , committee ) ,
99- } ) ;
136+ tableLoading : true ,
137+ } ) ) ;
138+
139+ try {
140+ const tableData = await getTableData ( page , category , committee ) ;
141+ setState ( prevState => ( {
142+ ...prevState ,
143+ tableData : tableData ,
144+ tableLoading : false ,
145+ } ) ) ;
146+ } catch ( error ) {
147+ console . error ( 'Error loading table data:' , error ) ;
148+ setState ( prevState => ( {
149+ ...prevState ,
150+ tableLoading : false ,
151+ } ) ) ;
152+ }
153+ }
154+
155+ async function refreshCurrentTable ( ) {
156+ const currentState = stateRef . current ;
157+ if ( currentState . tableLoading || autoRefreshingRef . current ) return ; // Prevent conflicts
158+
159+ // Capture version and current state to detect if user navigated during this auto-refresh
160+ const refreshVersion = autoRefreshVersionRef . current ;
161+ const { tablePage, category, committee } = currentState ;
162+
163+ // Set invisible auto-refresh flag (doesn't affect UI)
164+ autoRefreshingRef . current = true ;
165+
166+ try {
167+ const tableData = await getTableData ( tablePage , category , committee ) ;
168+
169+ // Only update state if no user navigation happened during this request
170+ if ( autoRefreshVersionRef . current === refreshVersion ) {
171+ setState ( prevState => ( {
172+ ...prevState ,
173+ tableData : tableData ,
174+ } ) ) ;
175+ }
176+ } catch ( error ) {
177+ console . error ( 'Error refreshing table data:' , error ) ;
178+ } finally {
179+ // Always clear auto-refresh flag
180+ autoRefreshingRef . current = false ;
181+ }
100182 }
101183
102184 useEffect ( ( ) => {
103185 const interval = setInterval ( ( ) => {
104- getCardAndTableData ( false ) ;
186+ const currentState = stateRef . current ;
187+ const timeSinceUserAction = Date . now ( ) - lastUserActionRef . current ;
188+
189+ // Auto-refresh cards always
190+ getCardDataOnly ( ) ;
191+
192+ // Auto-refresh table data only if:
193+ // 1. Not currently loading from user interaction
194+ // 2. Not already auto-refreshing
195+ // 3. At least 2 seconds since last user action (prevents interference)
196+ if ( ! currentState . tableLoading && ! autoRefreshingRef . current && timeSinceUserAction > 2000 ) {
197+ refreshCurrentTable ( ) ;
198+ }
105199 } , 4000 ) ;
106200 return ( ) => clearInterval ( interval ) ;
107- } ) ;
201+ } , [ ] ) ;
108202 if ( state . loading || ! state . cardData . blocks ) {
109203 getCardAndTableData ( true ) ;
110204 return (
@@ -120,7 +214,7 @@ export default function Home() {
120214 </ >
121215 ) ;
122216 } else {
123- const props = { state, setState, openModal, selectTable } ;
217+ const props = { state, setState, openModal, selectTable, refreshCurrentTable } ;
124218 const onToastClose = ( ) => setState ( { ...state , showToast : false } ) ;
125219 return (
126220 < >
0 commit comments