@@ -8,6 +8,54 @@ import { useNow } from '@/hooks/useNow'
88import HrTile from '@/components/HrTile'
99import { getActiveHrmData } from '@/utils/hrm'
1010
11+ const LoadingSkeleton = ( ) => (
12+ < >
13+ < Box
14+ data-testid = "hr-tile-grid-item"
15+ sx = { {
16+ width : { xs : '100%' , sm : 'calc(50% - 8px)' } ,
17+ } }
18+ >
19+ < Skeleton variant = "rectangular" height = { 220 } sx = { { borderRadius : 3 } } />
20+ </ Box >
21+ < Box
22+ data-testid = "hr-tile-grid-item"
23+ sx = { {
24+ display : { xs : 'none' , md : 'block' } ,
25+ width : { sm : 'calc(50% - 8px)' } ,
26+ } }
27+ >
28+ < Skeleton variant = "rectangular" height = { 220 } sx = { { borderRadius : 3 } } />
29+ </ Box >
30+ </ >
31+ )
32+
33+ const EmptyDataMessage = ( ) => (
34+ < Box
35+ sx = { {
36+ display : 'flex' ,
37+ flexDirection : 'column' ,
38+ justifyContent : 'center' ,
39+ alignItems : 'center' ,
40+ width : '100%' ,
41+ height : '100%' , // Ensure the container fills the grid cell
42+ gap : 2 ,
43+ p : 2 ,
44+ border : 1 ,
45+ borderColor : 'divider' ,
46+ borderRadius : 2 ,
47+ } }
48+ >
49+ < Typography variant = "h6" gutterBottom >
50+ No Heart Rate Data
51+ </ Typography >
52+ < Typography variant = "body1" color = "text.secondary" align = "center" >
53+ Heart rate data will be displayed here once a monitor is connected and
54+ streaming.
55+ </ Typography >
56+ </ Box >
57+ )
58+
1159const HrmConnectionPanel = ( ) => {
1260 const { hrmData, connectionStatus, activeAlerts } = useWebSocket ( )
1361 const now = useNow ( )
@@ -22,6 +70,39 @@ const HrmConnectionPanel = () => {
2270 connectionStatus === 'Connecting...' ||
2371 connectionStatus === 'Reconnecting...'
2472
73+ const renderContent = ( ) => {
74+ if ( isLoading ) {
75+ return < LoadingSkeleton />
76+ }
77+
78+ if ( tileData . length === 0 ) {
79+ return < EmptyDataMessage />
80+ }
81+
82+ return tileData . map ( ( user ) => {
83+ // Destructure to remove volatile timestamps causing re-renders
84+ const {
85+ updatedAt : _updatedAt ,
86+ lastUpdated : _lastUpdated ,
87+ ...tileProps
88+ } = user
89+ return (
90+ < Box
91+ key = { user . clientId }
92+ data-testid = "hr-tile-grid-item"
93+ sx = { {
94+ width : {
95+ xs : '100%' ,
96+ sm : 'calc(50% - 8px)' , // Adjusted for 16px gap (gap: 2)
97+ } ,
98+ } }
99+ >
100+ < HrTile { ...tileProps } />
101+ </ Box >
102+ )
103+ } )
104+ }
105+
25106 return (
26107 < Box
27108 data-testid = "hrm-connection-panel"
@@ -32,83 +113,9 @@ const HrmConnectionPanel = () => {
32113 height : '100%' ,
33114 } }
34115 >
35- { isLoading ? (
36- < >
37- < Box
38- data-testid = "hr-tile-grid-item"
39- sx = { {
40- width : { xs : '100%' , sm : 'calc(50% - 8px)' } ,
41- } }
42- >
43- < Skeleton
44- variant = "rectangular"
45- height = { 220 }
46- sx = { { borderRadius : 3 } }
47- />
48- </ Box >
49- < Box
50- data-testid = "hr-tile-grid-item"
51- sx = { {
52- display : { xs : 'none' , md : 'block' } ,
53- width : { sm : 'calc(50% - 8px)' } ,
54- } }
55- >
56- < Skeleton
57- variant = "rectangular"
58- height = { 220 }
59- sx = { { borderRadius : 3 } }
60- />
61- </ Box >
62- </ >
63- ) : tileData . length === 0 ? (
64- < Box
65- sx = { {
66- display : 'flex' ,
67- flexDirection : 'column' ,
68- justifyContent : 'center' ,
69- alignItems : 'center' ,
70- width : '100%' ,
71- height : '100%' , // Ensure the container fills the grid cell
72- gap : 2 ,
73- p : 2 ,
74- border : 1 ,
75- borderColor : 'divider' ,
76- borderRadius : 2 ,
77- } }
78- >
79- < Typography variant = "h6" gutterBottom >
80- No Heart Rate Data
81- </ Typography >
82- < Typography variant = "body1" color = "text.secondary" align = "center" >
83- Heart rate data will be displayed here once a monitor is connected
84- and streaming.
85- </ Typography >
86- </ Box >
87- ) : (
88- tileData . map ( ( user ) => {
89- // Destructure to remove volatile timestamps causing re-renders
90- const {
91- updatedAt : _updatedAt ,
92- lastUpdated : _lastUpdated ,
93- ...tileProps
94- } = user
95- return (
96- < Box
97- key = { user . clientId }
98- data-testid = "hr-tile-grid-item"
99- sx = { {
100- width : {
101- xs : '100%' ,
102- sm : 'calc(50% - 8px)' , // Adjusted for 16px gap (gap: 2)
103- } ,
104- } }
105- >
106- < HrTile { ...tileProps } />
107- </ Box >
108- )
109- } )
110- ) }
116+ { renderContent ( ) }
111117 </ Box >
112118 )
113119}
120+
114121export default HrmConnectionPanel
0 commit comments