-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Analytics: Download toast added #2200
Changes from 6 commits
eaad5b2
420962e
39fa56b
193a3c8
f22cd49
49844b6
f45975a
53124ec
a54c56a
21d8045
39fd0c6
abc7b44
09cacfd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import React, { useState, useCallback, useMemo, useEffect } from 'react'; | ||
// MoreInsightsChart.jsx | ||
import React, { useState, useCallback, useMemo, useRef } from 'react'; | ||
import { | ||
LineChart, | ||
Line, | ||
|
@@ -27,24 +28,30 @@ import { parseAndValidateISODate } from '@/core/utils/dateUtils'; | |
import { WHO_STANDARD_VALUES } from './constants'; | ||
import { formatYAxisTick, CustomizedAxisTick } from './utils'; | ||
import SkeletonLoader from './components/SkeletonLoader'; | ||
import useResizeObserver from '@/core/utils/useResizeObserver'; | ||
|
||
/** | ||
* MoreInsightsChart Component | ||
*/ | ||
const MoreInsightsChart = React.memo( | ||
({ | ||
data = [], | ||
selectedSites = [], // Array of site IDs; if empty, include all sites | ||
selectedSites = [], | ||
chartType = 'line', | ||
frequency = 'daily', | ||
width = '100%', | ||
height = '300px', | ||
id, | ||
pollutantType, | ||
isLoading = false, | ||
isLoading, | ||
}) => { | ||
const [activeIndex, setActiveIndex] = useState(null); | ||
|
||
// Reference to the chart container | ||
const containerRef = useRef(null); | ||
// Use the custom hook to get container dimensions | ||
const { width: containerWidth } = useResizeObserver(containerRef); | ||
|
||
/** | ||
* Processes raw chart data by validating dates and organizing data by time and site. | ||
*/ | ||
|
@@ -152,40 +159,31 @@ const MoreInsightsChart = React.memo( | |
const DataComponent = chartType === 'line' ? Line : Bar; | ||
|
||
/** | ||
* Calculates the interval for the X-axis ticks based on screen width. | ||
* Calculate step based on container width and number of ticks. | ||
* Assume each label requires a minimum width | ||
*/ | ||
const calculateXAxisInterval = useCallback(() => { | ||
const screenWidth = window.innerWidth; | ||
if (screenWidth < 768) return Math.ceil(chartData.length / 4); | ||
if (screenWidth < 1024) return Math.ceil(chartData.length / 6); | ||
return Math.ceil(chartData.length / 8); | ||
}, [chartData.length]); | ||
const calculateStep = useCallback(() => { | ||
const minLabelWidth = 40; | ||
if (containerWidth === 0) return 1; | ||
const maxLabels = Math.floor(containerWidth / minLabelWidth); | ||
const step = Math.ceil(chartData.length / maxLabels); | ||
return step; | ||
}, [containerWidth, chartData.length]); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Smart approach to dynamic step calculation! 🎯 The Consider extracting the configuration: +const CHART_CONFIG = {
+ MIN_LABEL_WIDTH: 40,
+ DEFAULT_STEP: 1
+};
const calculateStep = useCallback(() => {
- const minLabelWidth = 40;
+ const minLabelWidth = CHART_CONFIG.MIN_LABEL_WIDTH;
if (containerWidth === 0) return 1;
const maxLabels = Math.floor(containerWidth / minLabelWidth);
const step = Math.ceil(chartData.length / maxLabels);
return step;
}, [containerWidth, chartData.length]);
|
||
/** | ||
* Memoized X-axis interval | ||
* Memoized step for labels | ||
*/ | ||
const xAxisInterval = useMemo( | ||
() => calculateXAxisInterval(), | ||
[calculateXAxisInterval], | ||
); | ||
|
||
/** | ||
* Effect to update X-axis interval on window resize for responsiveness | ||
*/ | ||
useEffect(() => { | ||
const handleResize = () => { | ||
// Force recalculation by updating a state or triggering a re-render | ||
// Here, we do nothing because xAxisInterval is recalculated on dependency change | ||
}; | ||
window.addEventListener('resize', handleResize); | ||
return () => window.removeEventListener('resize', handleResize); | ||
}, []); | ||
const step = useMemo(() => calculateStep(), [calculateStep]); | ||
|
||
/** | ||
* Render the chart or appropriate messages based on state | ||
*/ | ||
const renderChart = useMemo(() => { | ||
if (chartData.length === 0 && !isLoading) { | ||
if (isLoading) { | ||
return <SkeletonLoader width={width} height={height} />; | ||
} | ||
|
||
if (chartData.length === 0) { | ||
return ( | ||
<div className="w-full flex flex-col justify-center items-center h-[380px] text-gray-500"> | ||
<p className="text-lg font-medium mb-2">No Data Available</p> | ||
|
@@ -200,7 +198,7 @@ const MoreInsightsChart = React.memo( | |
<ResponsiveContainer width={width} height={height}> | ||
<ChartComponent | ||
data={chartData} | ||
margin={{ top: 38, right: 10, left: -15, bottom: 10 }} | ||
margin={{ top: 38, right: 10, left: -15, bottom: 20 }} | ||
style={{ cursor: 'pointer' }} | ||
> | ||
{/* Grid */} | ||
|
@@ -213,7 +211,7 @@ const MoreInsightsChart = React.memo( | |
{/* X-Axis */} | ||
<XAxis | ||
dataKey="time" | ||
tickLine | ||
tickLine={false} | ||
tick={({ x, y, payload, fill, index }) => ( | ||
<CustomizedAxisTick | ||
x={x} | ||
|
@@ -222,12 +220,11 @@ const MoreInsightsChart = React.memo( | |
fill={fill} | ||
frequency={frequency} | ||
index={index} | ||
numTicks={chartData.length} | ||
step={step} | ||
/> | ||
)} | ||
interval={xAxisInterval} | ||
axisLine={false} | ||
scale="point" | ||
scale="auto" | ||
padding={{ left: 30, right: 30 }} | ||
/> | ||
|
||
|
@@ -318,7 +315,7 @@ const MoreInsightsChart = React.memo( | |
chartType, | ||
width, | ||
height, | ||
xAxisInterval, | ||
step, | ||
getColor, | ||
handleMouseLeave, | ||
activeIndex, | ||
|
@@ -332,12 +329,8 @@ const MoreInsightsChart = React.memo( | |
]); | ||
|
||
return ( | ||
<div id={id} className="pt-4"> | ||
{isLoading ? ( | ||
<SkeletonLoader width={width} height={height} /> | ||
) : ( | ||
renderChart | ||
)} | ||
<div id={id} ref={containerRef} className="pt-4"> | ||
{renderChart} | ||
</div> | ||
); | ||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider using URL.createObjectURL for downloads
Instead of manipulating the DOM directly, consider using URL.createObjectURL for a cleaner approach to handling downloads.