Skip to content

Commit 8c5073b

Browse files
author
RoshiniSeelamsetty
committed
fix(total-org-summary): resolve GlobalVolunteerMap rendering and location mapping issues
1 parent 59e2f88 commit 8c5073b

1 file changed

Lines changed: 112 additions & 58 deletions

File tree

Lines changed: 112 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { useEffect } from 'react';
1+
/* eslint-disable react/no-array-index-key */
2+
import { useEffect, useMemo } from 'react';
23
import L from 'leaflet';
34
import { MapContainer, TileLayer, useMap, CircleMarker } from 'react-leaflet';
45
import 'leaflet/dist/leaflet.css';
56
import 'leaflet.heat';
7+
68
import Loading from '~/components/common/Loading';
79

810
const volunteerColors = {
@@ -13,86 +15,138 @@ function HeatMap({ points }) {
1315
const map = useMap();
1416

1517
useEffect(() => {
16-
if (points.length > 0) {
17-
const heat = L.heatLayer(points, {
18-
radius: 20,
19-
blur: 20,
20-
maxZoom: 2,
21-
gradient: {
22-
0.4: '#00f',
23-
0.6: '#0f0',
24-
0.7: '#ff0',
25-
0.8: '#ffa500',
26-
1.0: '#f00',
27-
},
28-
}).addTo(map);
29-
30-
return () => {
31-
map.removeLayer(heat);
32-
};
33-
}
34-
return undefined;
35-
}, [points, map]);
18+
if (!map || !points.length) return undefined;
19+
20+
const heatLayer = L.heatLayer(points, {
21+
radius: 20,
22+
blur: 20,
23+
maxZoom: 4,
24+
gradient: {
25+
0.2: '#00f',
26+
0.4: '#0f0',
27+
0.6: '#ff0',
28+
0.8: '#ffa500',
29+
1.0: '#f00',
30+
},
31+
});
32+
33+
heatLayer.addTo(map);
34+
35+
return () => {
36+
map.removeLayer(heatLayer);
37+
};
38+
}, [map, points]);
3639

3740
return null;
3841
}
3942

40-
function MapComponent({ locations = [], isLoading, error }) {
41-
const heatMapPoints = (locations || []).map(location => [
42-
location._id.lat,
43-
location._id.lng,
44-
location.count,
45-
]);
43+
function GlobalVolunteerMap({ locations = [], isLoading, error }) {
44+
/**
45+
* Normalize backend response safely
46+
*/
47+
const normalizedLocations = useMemo(() => {
48+
if (!Array.isArray(locations)) return [];
49+
50+
return locations
51+
.map(location => {
52+
const lat = location?._id?.lat ?? location?.lat ?? location?.latitude;
53+
54+
const lng = location?._id?.lng ?? location?.lng ?? location?.longitude;
4655

47-
const activeVolunteers = (locations || []).filter(v => v.status === 'active');
56+
const count = Number(location?.count || 1);
57+
58+
return {
59+
lat: Number(lat),
60+
lng: Number(lng),
61+
count,
62+
};
63+
})
64+
.filter(
65+
item =>
66+
!Number.isNaN(item.lat) &&
67+
!Number.isNaN(item.lng) &&
68+
item.lat >= -90 &&
69+
item.lat <= 90 &&
70+
item.lng >= -180 &&
71+
item.lng <= 180,
72+
);
73+
}, [locations]);
74+
75+
/**
76+
* Build heatmap points
77+
*/
78+
const heatMapPoints = useMemo(
79+
() => normalizedLocations.map(location => [location.lat, location.lng, location.count]),
80+
[normalizedLocations],
81+
);
4882

4983
if (isLoading) {
5084
return (
5185
<div className="d-flex justify-content-center align-items-center">
52-
<div className="w-100vh">
86+
<div className="w-100">
5387
<Loading />
5488
</div>
5589
</div>
5690
);
5791
}
5892

93+
if (error) {
94+
return (
95+
<div className="error-container text-center p-4">
96+
<p>Error loading map data</p>
97+
</div>
98+
);
99+
}
100+
101+
if (!normalizedLocations.length) {
102+
return (
103+
<div
104+
className="d-flex justify-content-center align-items-center"
105+
style={{
106+
height: '500px',
107+
border: '1px solid #ddd',
108+
borderRadius: '8px',
109+
}}
110+
>
111+
<p>No volunteer location data available</p>
112+
</div>
113+
);
114+
}
115+
59116
return (
60117
<div className="map-container" style={{ marginTop: '20px' }}>
61-
{error && (
62-
<div className="error-container">
63-
<p>Error: {error}</p>
64-
<button
65-
type="button"
66-
onClick={() => {
67-
/* Add retry logic here */
68-
}}
69-
>
70-
Retry
71-
</button>
72-
</div>
73-
)}
74-
<MapContainer center={[20, 0]} zoom={2} style={{ height: '500px', width: '100%' }}>
118+
<MapContainer
119+
center={[20, 0]}
120+
zoom={2}
121+
scrollWheelZoom
122+
style={{
123+
height: '500px',
124+
width: '100%',
125+
borderRadius: '8px',
126+
}}
127+
>
75128
<TileLayer
76129
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
77-
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
130+
attribution="&copy; OpenStreetMap contributors"
78131
/>
132+
79133
<HeatMap points={heatMapPoints} />
80-
{activeVolunteers.length > 0 &&
81-
activeVolunteers.map(volunteer => (
82-
<CircleMarker
83-
key={`active-${volunteer._id.lat}-${volunteer._id.lng}`}
84-
center={[volunteer._id.lat, volunteer._id.lng]}
85-
radius={8}
86-
pathOptions={{
87-
color: volunteerColors.active,
88-
fillColor: volunteerColors.active,
89-
fillOpacity: 0.8,
90-
}}
91-
/>
92-
))}
134+
135+
{normalizedLocations.map((location, index) => (
136+
<CircleMarker
137+
key={`${location.lat}-${location.lng}-${index}`}
138+
center={[location.lat, location.lng]}
139+
radius={Math.min(10, Math.max(4, location.count))}
140+
pathOptions={{
141+
color: volunteerColors.active,
142+
fillColor: volunteerColors.active,
143+
fillOpacity: 0.7,
144+
}}
145+
/>
146+
))}
93147
</MapContainer>
94148
</div>
95149
);
96150
}
97151

98-
export default MapComponent;
152+
export default GlobalVolunteerMap;

0 commit comments

Comments
 (0)