Skip to content

Commit ac16808

Browse files
committed
fix: availability stats height fix.
1 parent 91db612 commit ac16808

File tree

1 file changed

+58
-65
lines changed

1 file changed

+58
-65
lines changed

thingconnect.pulse.client/src/components/AvailabilityChart.tsx

Lines changed: 58 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useMemo } from 'react';
1+
import { useMemo, useRef, useState, useLayoutEffect } from 'react';
22
import { Box, Text, VStack, Skeleton } from '@chakra-ui/react';
33
import type { RollupBucket, DailyBucket, RawCheck } from '@/api/types';
44
import type { BucketType } from '@/types/bucket';
@@ -24,25 +24,6 @@ export function AvailabilityChart({
2424
height = 300,
2525
isLoading,
2626
}: AvailabilityChartProps) {
27-
if (isLoading) {
28-
return (
29-
<Box
30-
height='100%'
31-
display='flex'
32-
alignItems='center'
33-
justifyContent='center'
34-
borderRadius='md'
35-
borderWidth='1px'
36-
bg='gray.50'
37-
_dark={{ bg: 'gray.800' }}
38-
>
39-
<VStack w='full' px={6} gap={4}>
40-
<Skeleton height='100%' width='100%' />
41-
</VStack>
42-
</Box>
43-
);
44-
}
45-
4627
const chartData = useMemo(() => {
4728
if (!data) return null;
4829
switch (bucket) {
@@ -101,56 +82,67 @@ export function AvailabilityChart({
10182
);
10283
}
10384

85+
const containerRef = useRef<HTMLDivElement>(null);
86+
const [dimensions, setDimensions] = useState({ width: 0, height });
87+
88+
useLayoutEffect(() => {
89+
if (!containerRef.current) return;
90+
91+
const observer = new ResizeObserver(entries => {
92+
const entry = entries[0];
93+
setDimensions({
94+
width: entry.contentRect.width,
95+
height: entry.contentRect.height,
96+
});
97+
});
98+
99+
observer.observe(containerRef.current);
100+
return () => observer.disconnect();
101+
}, []);
102+
104103
const margin = { top: 20, right: 30, bottom: 40, left: 70 };
104+
const chartWidth = Math.max(dimensions.width - margin.left - margin.right, 0);
105+
const chartHeight = Math.max(dimensions.height - margin.top - margin.bottom, 0);
105106

106107
return (
107-
<Box w='full' h='full' position='relative'>
108-
<svg width='100%' height='100%' viewBox={`0 0 1000 ${height}`} preserveAspectRatio='none'>
108+
// <Skeleton loading={isLoading} w='full' h='full' position='relative'>
109+
<Box ref={containerRef} flex={1} minH={0} w='full' h='full' position='relative'>
110+
<svg
111+
width='100%'
112+
height='100%'
113+
viewBox={`0 0 ${dimensions.width} ${dimensions.height}`}
114+
preserveAspectRatio='none'
115+
>
109116
<g transform={`translate(${margin.left}, ${margin.top})`}>
110117
{/* Grid + Y-axis labels */}
111-
{[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100].map(value => (
112-
<g key={value}>
113-
<line
114-
x1={0}
115-
y1={
116-
height -
117-
margin.top -
118-
margin.bottom -
119-
(value / 100) * (height - margin.top - margin.bottom)
120-
}
121-
x2={1000 - margin.left - margin.right}
122-
y2={
123-
height -
124-
margin.top -
125-
margin.bottom -
126-
(value / 100) * (height - margin.top - margin.bottom)
127-
}
128-
stroke='#e2e8f0'
129-
strokeWidth='1'
130-
opacity='0.5'
131-
/>
132-
<text
133-
x={-10}
134-
y={
135-
height -
136-
margin.top -
137-
margin.bottom -
138-
(value / 100) * (height - margin.top - margin.bottom) +
139-
4
140-
}
141-
fill='#718096'
142-
textAnchor='end'
143-
style={{ fontSize: '10px' }}
144-
>
145-
{value}%
146-
</text>
147-
</g>
148-
))}
118+
{[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100].map(value => {
119+
const y = chartHeight - (value / 100) * chartHeight;
120+
return (
121+
<g key={value}>
122+
<line
123+
x1={0}
124+
y1={y}
125+
x2={chartWidth}
126+
y2={y}
127+
stroke='#e2e8f0'
128+
strokeWidth='1'
129+
opacity='0.5'
130+
/>
131+
<text
132+
x={-10}
133+
y={y + 4}
134+
fill='#718096'
135+
textAnchor='end'
136+
style={{ fontSize: '10px' }}
137+
>
138+
{value}%
139+
</text>
140+
</g>
141+
);
142+
})}
149143

150144
{/* Bars */}
151145
{chartData?.map((point, index) => {
152-
const chartWidth = 1000 - margin.left - margin.right;
153-
const chartHeight = height - margin.top - margin.bottom;
154146
const slotWidth = chartWidth / chartData.length;
155147
const barWidth = slotWidth * 0.6;
156148
const x = index * slotWidth + (slotWidth - barWidth) / 2;
@@ -172,16 +164,17 @@ export function AvailabilityChart({
172164
{/* Y-axis label */}
173165
<text
174166
x={-35}
175-
y={(height - margin.top - margin.bottom) / 2.3}
176-
style={{ fontSize: '12' }}
167+
y={chartHeight / 2.2}
168+
style={{ fontSize: '12px' }}
177169
fill='#718096'
178170
textAnchor='middle'
179-
transform={`rotate(-90, -35, ${(height - margin.top - margin.bottom) / 2})`}
171+
transform={`rotate(-90, -35, ${chartHeight / 2})`}
180172
>
181173
Uptime %
182174
</text>
183175
</g>
184176
</svg>
185177
</Box>
178+
// </Skeleton>
186179
);
187180
}

0 commit comments

Comments
 (0)