1
- import React , { useState , useEffect } from 'react' ;
1
+ import React , { useState , useEffect , useReducer } from 'react' ;
2
2
import axios from 'axios' ;
3
3
import { FiBattery , FiAlertCircle , FiClock , FiThermometer , FiPercent , FiZap , FiActivity , FiRefreshCw , FiCalendar , FiFilter } from 'react-icons/fi' ;
4
4
import { useSettings } from '../context/SettingsContext' ;
@@ -30,11 +30,45 @@ ChartJS.register(
30
30
31
31
const Dashboard = ( ) => {
32
32
const { getPollIntervalMs, settings } = useSettings ( ) ;
33
- const [ upsSystems , setUpsSystems ] = useState ( [ ] ) ;
34
- const [ loading , setLoading ] = useState ( true ) ;
35
- const [ error , setError ] = useState ( null ) ;
36
- const [ selectedUps , setSelectedUps ] = useState ( null ) ;
33
+ // Define reducer for dashboard state
34
+ const initialState = {
35
+ upsSystems : [ ] ,
36
+ loading : true ,
37
+ error : null ,
38
+ selectedUpsId : null ,
39
+ lastUpdated : new Date ( ) ,
40
+ forceUpdate : 0 // Used to force re-renders
41
+ } ;
42
+
43
+ const dashboardReducer = ( state , action ) => {
44
+ switch ( action . type ) {
45
+ case 'SET_UPS_SYSTEMS' :
46
+ return {
47
+ ...state ,
48
+ upsSystems : action . payload ,
49
+ lastUpdated : new Date ( ) ,
50
+ forceUpdate : state . forceUpdate + 1 // Increment to force re-render
51
+ } ;
52
+ case 'SET_LOADING' :
53
+ return { ...state , loading : action . payload } ;
54
+ case 'SET_ERROR' :
55
+ return { ...state , error : action . payload } ;
56
+ case 'SET_SELECTED_UPS_ID' :
57
+ return { ...state , selectedUpsId : action . payload } ;
58
+ default :
59
+ return state ;
60
+ }
61
+ } ;
62
+
63
+ // Use reducer instead of multiple useState calls
64
+ const [ state , dispatch ] = useReducer ( dashboardReducer , initialState ) ;
65
+ const { upsSystems, loading, error, selectedUpsId, lastUpdated, forceUpdate } = state ;
66
+
67
+ // Get the selected UPS from the current state
68
+ const selectedUps = upsSystems . find ( ups => ups . id === selectedUpsId ) || null ;
69
+
37
70
const [ timeFilter , setTimeFilter ] = useState ( 3 ) ; // Default to 3 days
71
+
38
72
const {
39
73
batteryHistory,
40
74
loading : historyLoading ,
@@ -43,37 +77,45 @@ const Dashboard = () => {
43
77
refreshData : refreshBatteryHistory ,
44
78
currentTimeFilter
45
79
} = useBatteryHistory ( selectedUps ?. id , timeFilter ) ;
46
- const [ lastUpdated , setLastUpdated ] = useState ( new Date ( ) ) ;
47
80
81
+ // Effect for fetching UPS systems data
48
82
useEffect ( ( ) => {
49
83
const fetchUpsSystems = async ( ) => {
50
84
try {
51
- setLoading ( true ) ;
85
+ dispatch ( { type : 'SET_LOADING' , payload : true } ) ;
52
86
const response = await axios . get ( '/api/ups/systems' ) ;
53
- setUpsSystems ( response . data ) ;
54
- setLastUpdated ( new Date ( ) ) ;
87
+ const data = response . data ;
55
88
56
- if ( response . data . length > 0 && ! selectedUps ) {
57
- setSelectedUps ( response . data [ 0 ] ) ;
89
+ // Set initial selection if needed
90
+ if ( data . length > 0 && ! selectedUpsId ) {
91
+ dispatch ( { type : 'SET_SELECTED_UPS_ID' , payload : data [ 0 ] . id } ) ;
58
92
}
93
+
94
+ dispatch ( { type : 'SET_UPS_SYSTEMS' , payload : data } ) ;
95
+
96
+ // Log for debugging
97
+ console . log ( 'UPS systems data fetched:' , data ) ;
59
98
} catch ( err ) {
60
- setError ( 'Failed to fetch UPS systems. Please check your connection to the NUT server.' ) ;
99
+ dispatch ( {
100
+ type : 'SET_ERROR' ,
101
+ payload : 'Failed to fetch UPS systems. Please check your connection to the NUT server.'
102
+ } ) ;
61
103
console . error ( 'Error fetching UPS systems:' , err ) ;
62
104
} finally {
63
- setLoading ( false ) ;
105
+ dispatch ( { type : 'SET_LOADING' , payload : false } ) ;
64
106
}
65
107
} ;
66
108
67
109
fetchUpsSystems ( ) ;
68
110
69
- // Set up polling for real-time updates using the configured poll interval
111
+ // Set up polling for real-time updates
70
112
const interval = setInterval ( fetchUpsSystems , getPollIntervalMs ( ) ) ;
71
113
72
114
return ( ) => clearInterval ( interval ) ;
73
- } , [ getPollIntervalMs , selectedUps ] ) ;
115
+ } , [ getPollIntervalMs , selectedUpsId ] ) ; // Added selectedUpsId back to ensure proper initial selection
74
116
75
117
const handleUpsSelect = ( ups ) => {
76
- setSelectedUps ( ups ) ;
118
+ dispatch ( { type : 'SET_SELECTED_UPS_ID' , payload : ups . id } ) ;
77
119
} ;
78
120
79
121
const getStatusColor = ( status ) => {
@@ -226,7 +268,7 @@ const Dashboard = () => {
226
268
{ /* Selected UPS Details */ }
227
269
< div className = "md:col-span-2" >
228
270
{ selectedUps && (
229
- < div className = "space-y-6" >
271
+ < div className = "space-y-6" key = { ` ${ selectedUps . id } - ${ selectedUps . batteryCharge } - ${ forceUpdate } ` } >
230
272
< div className = "bg-white dark:bg-gray-800 shadow rounded-lg overflow-hidden" >
231
273
< div className = "px-4 py-5 sm:px-6 border-b dark:border-gray-700 flex justify-between items-center" >
232
274
< div >
0 commit comments