11import React , { useState , useEffect , useMemo , useCallback } from 'react'
22import { Calculator , AlertCircle , Loader2 , ChevronDown , ChevronUp , FileDown , ArrowUpDown , ArrowUp , ArrowDown , Filter , Info , ArrowRight } from 'lucide-react'
3- import { useQuery , useQueryClient } from '@tanstack/react-query'
3+ import { useQuery , useQueryClient , useIsRestoring } from '@tanstack/react-query'
44import { LoadingOverlay } from '@/components/LoadingOverlay'
55import { LoadingPlaceholder } from '@/components/LoadingPlaceholder'
66import { AnimatedSection } from '@/components/AnimatedSection'
@@ -123,6 +123,7 @@ function calcPrice(quantity: number | undefined, price: string | number | undefi
123123export default function Simulator ( ) {
124124 // const { user } = useAuth() // Unused for now
125125 const queryClient = useQueryClient ( )
126+ const isRestoring = useIsRestoring ( )
126127 const isDemo = useIsDemo ( )
127128
128129 // Fetch user's PDLs
@@ -141,7 +142,7 @@ export default function Simulator() {
141142 } )
142143
143144 // Fetch energy providers and offers
144- const { data : providersData , isLoading : providersLoading } = useQuery ( {
145+ const { data : providersDataRaw , isLoading : providersLoading } = useQuery ( {
145146 queryKey : [ 'energy-providers' ] ,
146147 queryFn : async ( ) => {
147148 const response = await energyApi . getProviders ( )
@@ -150,9 +151,13 @@ export default function Simulator() {
150151 }
151152 return [ ]
152153 } ,
154+ staleTime : 0 ,
153155 } )
154156
155- const { data : offersData , isLoading : offersLoading } = useQuery ( {
157+ // Ensure providersData is always an array
158+ const providersData = Array . isArray ( providersDataRaw ) ? providersDataRaw : [ ]
159+
160+ const { data : offersDataRaw , isLoading : offersLoading } = useQuery ( {
156161 queryKey : [ 'energy-offers' ] ,
157162 queryFn : async ( ) => {
158163 const response = await energyApi . getOffers ( )
@@ -161,8 +166,12 @@ export default function Simulator() {
161166 }
162167 return [ ]
163168 } ,
169+ staleTime : 0 , // Always refetch to ensure fresh data
164170 } )
165171
172+ // Ensure offersData is always an array
173+ const offersData = Array . isArray ( offersDataRaw ) ? offersDataRaw : [ ]
174+
166175 // Selected PDL from global store
167176 const { selectedPdl, setSelectedPdl } = usePdlStore ( )
168177
@@ -187,35 +196,41 @@ export default function Simulator() {
187196 // Read consumptionDetail data via direct cache access + subscription
188197 const [ cachedConsumptionData , setCachedConsumptionData ] = useState < any > ( null )
189198
199+ // Subscribe to cache updates IMMEDIATELY (don't wait for hydration)
200+ // This ensures we capture setQueryData events even while hydrating
190201 useEffect ( ( ) => {
191202 if ( ! selectedPdl ) {
192203 setCachedConsumptionData ( null )
193204 return
194205 }
195206
196- // Read current data from cache (includes persisted data after hydration)
197- const initialData = queryClient . getQueryData ( [ 'consumptionDetail' , selectedPdl ] )
198- if ( initialData ) {
199- logger . log ( '[Simulator] Initial cache data found:' , ! ! initialData )
200- setCachedConsumptionData ( initialData )
201- }
202-
203- // Subscribe to future changes (when setQueryData is called or cache hydrates)
207+ // Subscribe to future changes (when setQueryData is called)
204208 const unsubscribe = queryClient . getQueryCache ( ) . subscribe ( ( event ) => {
209+ // Listen to 'updated' events for this query (setQueryData triggers 'updated')
205210 if (
206211 event ?. type === 'updated' &&
207212 event ?. query ?. queryKey ?. [ 0 ] === 'consumptionDetail' &&
208213 event ?. query ?. queryKey ?. [ 1 ] === selectedPdl
209214 ) {
210215 const updatedData = queryClient . getQueryData ( [ 'consumptionDetail' , selectedPdl ] )
211- logger . log ( '[Simulator] Cache updated:' , ! ! updatedData )
212216 setCachedConsumptionData ( updatedData )
213217 }
214218 } )
215219
216220 return ( ) => unsubscribe ( )
217221 } , [ selectedPdl , queryClient ] )
218222
223+ // Read initial data from cache AFTER hydration completes
224+ useEffect ( ( ) => {
225+ if ( ! selectedPdl || isRestoring ) return
226+
227+ // Hydration complete - read current data from cache
228+ const initialData = queryClient . getQueryData ( [ 'consumptionDetail' , selectedPdl ] )
229+ if ( initialData ) {
230+ setCachedConsumptionData ( initialData )
231+ }
232+ } , [ selectedPdl , queryClient , isRestoring ] )
233+
219234 // Simulation state
220235 const [ isSimulating , setIsSimulating ] = useState ( false )
221236 const [ simulationResult , setSimulationResult ] = useState < any > ( null )
@@ -819,60 +834,25 @@ export default function Simulator() {
819834 // Auto-launch simulation if cache data exists
820835 // IMPORTANT: This hook must be before any early returns to respect React's rules of hooks
821836 useEffect ( ( ) => {
822- logger . log ( '[Auto-launch] useEffect triggered' , {
823- selectedPdl,
824- isSimulating,
825- hasSimulationResult : ! ! simulationResult ,
826- hasAutoLaunched,
827- isDemo,
828- pdlsDataLoaded : ! ! pdlsData ,
829- offersDataLoaded : ! ! offersData ,
830- providersDataLoaded : ! ! providersData ,
831- offersLoading,
832- providersLoading,
833- isConsumptionCacheLoading,
834- hasCachedData : ! ! cachedConsumptionData ,
835- } )
836-
837837 // Don't auto-launch if already launched, simulating, or have results
838- if ( ! selectedPdl || isSimulating || simulationResult || hasAutoLaunched ) {
839- logger . log ( '[Auto-launch] Skipping auto-launch due to conditions' )
840- return
841- }
838+ if ( ! selectedPdl || isSimulating || simulationResult || hasAutoLaunched ) return
842839
843840 // Don't auto-launch while data is still loading (including cache hydration)
844- if ( offersLoading || providersLoading || isConsumptionCacheLoading ) {
845- logger . log ( '[Auto-launch] Skipping auto-launch - still loading data' )
846- return
847- }
841+ if ( offersLoading || providersLoading || isConsumptionCacheLoading ) return
848842
849843 // Don't auto-launch if PDL data, offers, or providers are not loaded yet
850- if ( ! pdlsData || ! Array . isArray ( offersData ) || offersData . length === 0 || ! providersData ) {
851- logger . log ( '[Auto-launch] Skipping auto-launch - data not loaded yet' , {
852- pdlsData : ! ! pdlsData ,
853- offersData : Array . isArray ( offersData ) ? offersData . length : 'not array' ,
854- providersData : ! ! providersData
855- } )
856- return
857- }
844+ if ( ! pdlsData || offersData . length === 0 || providersData . length === 0 ) return
858845
859846 // Use cachedConsumptionData from state (populated via subscription, handles IndexedDB hydration)
860- if ( ! cachedConsumptionData ?. data ?. meter_reading ?. interval_reading ?. length ) {
861- logger . log ( '[Auto-launch] ❌ No cached data found for PDL:' , selectedPdl )
862- return
863- }
847+ if ( ! cachedConsumptionData ?. data ?. meter_reading ?. interval_reading ?. length ) return
864848
865849 const readings = cachedConsumptionData . data . meter_reading . interval_reading
866850 const totalPoints = readings . length
867851
868852 // Check if we have enough data (at least 30 days worth = ~1440 points at 30min intervals)
869853 const minRequiredPoints = 30 * 48 // 30 days * 48 half-hours
870- const hasEnoughData = totalPoints >= minRequiredPoints
871-
872- logger . log ( `[Auto-launch] Cache check: ${ totalPoints } points (need ${ minRequiredPoints } minimum)` )
873854
874- if ( hasEnoughData ) {
875- logger . log ( `✅ Auto-launching simulation with ${ totalPoints } cached points` )
855+ if ( totalPoints >= minRequiredPoints ) {
876856 setHasAutoLaunched ( true )
877857 // Show loading overlay while preparing simulation
878858 setIsInitialLoadingFromCache ( true )
@@ -881,8 +861,6 @@ export default function Simulator() {
881861 setTimeout ( ( ) => {
882862 handleSimulation ( )
883863 } , 100 )
884- } else {
885- logger . log ( `❌ Not enough cached data (${ totalPoints } points), skipping auto-launch` )
886864 }
887865 } , [ selectedPdl , isSimulating , simulationResult , hasAutoLaunched , isDemo , pdlsData , offersData , providersData , offersLoading , providersLoading , isConsumptionCacheLoading , cachedConsumptionData , handleSimulation ] )
888866
0 commit comments