@@ -67,6 +67,7 @@ import {
6767 Dumbbell ,
6868 Beaker ,
6969 BarChart3 ,
70+ Loader2 ,
7071 type LucideIcon ,
7172} from "lucide-react" ;
7273import { cn } from "../../lib/utils" ;
@@ -132,6 +133,47 @@ function getStressTrendColor(value: number | null): string {
132133 return "text-blue-500" ;
133134}
134135
136+ function getCorrelationColor ( value : number | null ) : string {
137+ if ( value === null ) return "text-muted-foreground" ;
138+ if ( value < - 0.3 ) return "text-green-500" ;
139+ if ( value > 0 ) return "text-red-500" ;
140+ return "text-muted-foreground" ;
141+ }
142+
143+ function getHrvSdColor ( value : number | null ) : string {
144+ if ( value === null ) return "" ;
145+ if ( value < 0.1 ) return "text-green-500" ;
146+ if ( value > 0.15 ) return "text-red-500" ;
147+ return "" ;
148+ }
149+
150+ function getTsbColor ( value : number | null ) : string {
151+ if ( value === null ) return "" ;
152+ if ( value > 0 ) return "text-green-500" ;
153+ if ( value < - 10 ) return "text-red-500" ;
154+ return "" ;
155+ }
156+
157+ function getAllostaticScoreColor ( value : number | null ) : string {
158+ if ( value === null ) return "text-yellow-500" ;
159+ if ( value < 20 ) return "text-green-500" ;
160+ if ( value > 40 ) return "text-red-500" ;
161+ return "text-yellow-500" ;
162+ }
163+
164+ function getDysregulationRateColor ( rate : number ) : string {
165+ if ( rate > 0.3 ) return "text-red-500" ;
166+ if ( rate > 0.15 ) return "text-yellow-500" ;
167+ return "text-green-500" ;
168+ }
169+
170+ function getCrossCorrelationColor ( value : number | null ) : string {
171+ if ( value === null ) return "" ;
172+ if ( value > 0.3 ) return "text-green-500" ;
173+ if ( value < - 0.3 ) return "text-red-500" ;
174+ return "" ;
175+ }
176+
135177interface DataQualityBadgeProps {
136178 quality : DataQuality ;
137179}
@@ -346,10 +388,14 @@ export function StatisticsPage() {
346388 trendWindow,
347389 useShiftedZScore,
348390 } = modeConfig ;
349- const { data, isLoading, error } = useHealthData ( MAX_BASELINE_DAYS , true ) ;
391+ const { data, isLoading, isFetching, error } = useHealthData (
392+ MAX_BASELINE_DAYS ,
393+ true ,
394+ ) ;
350395 const {
351396 data : analyticsData ,
352397 isLoading : analyticsLoading ,
398+ isFetching : analyticsFetching ,
353399 error : analyticsError ,
354400 } = useAnalytics ( mode ) ;
355401 const advancedInsights = analyticsData ?. advanced_insights ;
@@ -541,7 +587,12 @@ export function StatisticsPage() {
541587 Personal baseline deviations and trends
542588 </ p >
543589 </ div >
544- < ModeSelector mode = { mode } setMode = { setMode } />
590+ < div className = "flex items-center gap-3" >
591+ { ( isFetching || analyticsFetching ) && (
592+ < Loader2 className = "h-4 w-4 animate-spin text-primary" />
593+ ) }
594+ < ModeSelector mode = { mode } setMode = { setMode } />
595+ </ div >
545596 </ div >
546597
547598 < Card className = "border-2" >
@@ -1248,13 +1299,7 @@ export function StatisticsPage() {
12481299 < span
12491300 className = { cn (
12501301 "font-mono text-sm" ,
1251- correlationMetrics . hrvRhrCorrelation !== null &&
1252- correlationMetrics . hrvRhrCorrelation < - 0.3
1253- ? "text-green-500"
1254- : correlationMetrics . hrvRhrCorrelation !== null &&
1255- correlationMetrics . hrvRhrCorrelation > 0
1256- ? "text-red-500"
1257- : "text-muted-foreground" ,
1302+ getCorrelationColor ( correlationMetrics . hrvRhrCorrelation ) ,
12581303 ) }
12591304 >
12601305 { correlationMetrics . hrvRhrCorrelation !== null
@@ -1729,16 +1774,9 @@ export function StatisticsPage() {
17291774 < span
17301775 className = { cn (
17311776 "font-mono text-sm" ,
1732- advancedInsights . hrv_advanced . ln_rmssd_sd_7d !==
1733- null &&
1734- advancedInsights . hrv_advanced . ln_rmssd_sd_7d < 0.1
1735- ? "text-green-500"
1736- : advancedInsights . hrv_advanced . ln_rmssd_sd_7d !==
1737- null &&
1738- advancedInsights . hrv_advanced . ln_rmssd_sd_7d >
1739- 0.15
1740- ? "text-red-500"
1741- : "" ,
1777+ getHrvSdColor (
1778+ advancedInsights . hrv_advanced . ln_rmssd_sd_7d ,
1779+ ) ,
17421780 ) }
17431781 >
17441782 { advancedInsights . hrv_advanced . ln_rmssd_sd_7d ?. toFixed (
@@ -1920,13 +1958,7 @@ export function StatisticsPage() {
19201958 { advancedInsights . fitness . atl ?. toFixed ( 1 ) ?? "—" } /{ " " }
19211959 < span
19221960 className = { cn (
1923- advancedInsights . fitness . tsb !== null &&
1924- advancedInsights . fitness . tsb > 0
1925- ? "text-green-500"
1926- : advancedInsights . fitness . tsb !== null &&
1927- advancedInsights . fitness . tsb < - 10
1928- ? "text-red-500"
1929- : "" ,
1961+ getTsbColor ( advancedInsights . fitness . tsb ) ,
19301962 ) }
19311963 >
19321964 { advancedInsights . fitness . tsb ?. toFixed ( 1 ) ?? "—" }
@@ -1987,17 +2019,9 @@ export function StatisticsPage() {
19872019 < span
19882020 className = { cn (
19892021 "text-2xl font-bold" ,
1990- advancedInsights . allostatic_load . composite_score !==
1991- null &&
1992- advancedInsights . allostatic_load . composite_score <
1993- 20
1994- ? "text-green-500"
1995- : advancedInsights . allostatic_load
1996- . composite_score !== null &&
1997- advancedInsights . allostatic_load
1998- . composite_score > 40
1999- ? "text-red-500"
2000- : "text-yellow-500" ,
2022+ getAllostaticScoreColor (
2023+ advancedInsights . allostatic_load . composite_score ,
2024+ ) ,
20012025 ) }
20022026 >
20032027 { advancedInsights . allostatic_load . composite_score ?. toFixed (
@@ -2021,11 +2045,7 @@ export function StatisticsPage() {
20212045 < span
20222046 className = { cn (
20232047 "font-mono" ,
2024- rate > 0.3
2025- ? "text-red-500"
2026- : rate > 0.15
2027- ? "text-yellow-500"
2028- : "text-green-500" ,
2048+ getDysregulationRateColor ( rate ) ,
20292049 ) }
20302050 >
20312051 { ( rate * 100 ) . toFixed ( 0 ) } %
@@ -2234,13 +2254,7 @@ export function StatisticsPage() {
22342254 < span
22352255 className = { cn (
22362256 "font-mono font-medium" ,
2237- pair . correlation !== null &&
2238- pair . correlation > 0.3
2239- ? "text-green-500"
2240- : pair . correlation !== null &&
2241- pair . correlation < - 0.3
2242- ? "text-red-500"
2243- : "" ,
2257+ getCrossCorrelationColor ( pair . correlation ) ,
22442258 ) }
22452259 >
22462260 { pair . correlation ?. toFixed ( 2 ) ?? "—" }
0 commit comments