1
-
2
1
'use client' ;
3
2
4
3
import 'leaflet/dist/leaflet.css' ;
@@ -11,6 +10,7 @@ import {
11
10
TileLayer ,
12
11
Marker ,
13
12
useMapEvents ,
13
+ useMap ,
14
14
} from 'react-leaflet' ;
15
15
import L from 'leaflet' ;
16
16
import 'leaflet-control-geocoder' ;
@@ -33,8 +33,7 @@ const crosshairIcon = new L.Icon({
33
33
34
34
const MapCenter = ( ) => {
35
35
const t = useTranslations ( ) ;
36
-
37
- const [ showPopup , setShowPopup ] = useState ( false ) ; // State for controlling the visibility of the confirmation popup
36
+ const [ showPopup , setShowPopup ] = useState ( false ) ;
38
37
const [ center , setCenter ] = useState < { lat : number ; lng : number } > ( { lat : 50.064192 , lng : 19.944544 } ) ;
39
38
const { currentUser, autoLoginUser } = useContext ( AppContext ) ;
40
39
const mapRef = useRef < L . Map | null > ( null ) ;
@@ -45,6 +44,7 @@ const MapCenter = () => {
45
44
autoLoginUser ( ) ;
46
45
}
47
46
47
+ // Fetch the map center from the backend if the user is authenticated
48
48
const getMapCenter = async ( ) => {
49
49
if ( currentUser ?. pi_uid ) {
50
50
try {
@@ -65,19 +65,19 @@ const MapCenter = () => {
65
65
getMapCenter ( ) ;
66
66
} , [ currentUser ] ) ;
67
67
68
- // Handle search query to update map center and zoom level
68
+ // Geocode the query and update the map center
69
69
const handleSearch = async ( query : string ) => {
70
70
try {
71
71
const geocoder = new ( L . Control as any ) . Geocoder . nominatim ( ) ;
72
72
geocoder . geocode ( query , ( results : any ) => {
73
73
if ( results . length > 0 ) {
74
74
const { center : resultCenter } = results [ 0 ] ;
75
- setCenter ( { lat : resultCenter . lat , lng : resultCenter . lng } ) ; // Update map center
76
- if ( mapRef . current ) {
77
- mapRef . current . setView ( [ resultCenter . lat , resultCenter . lng ] , 13 ) ;
78
- logger . info ( `Map center updated and zoomed to: ${ resultCenter . lat } , ${ resultCenter . lng } ` ) ;
79
- } else {
80
- logger . warn ( 'Map reference is not set' ) ;
75
+ // Check if the new center is different from the current center before setting it
76
+ if ( resultCenter . lat !== center . lat || resultCenter . lng !== center . lng ) {
77
+ setCenter ( { lat : resultCenter . lat , lng : resultCenter . lng } ) ;
78
+ if ( mapRef . current ) {
79
+ mapRef . current . setView ( [ resultCenter . lat , resultCenter . lng ] , 13 ) ;
80
+ }
81
81
}
82
82
} else {
83
83
logger . warn ( `No result found for the query: ${ query } ` ) ;
@@ -88,95 +88,94 @@ const MapCenter = () => {
88
88
}
89
89
} ;
90
90
91
- // Component to handle map events and update the center state
91
+ // Access the map instance and set initial center without causing an infinite loop
92
+ const MapHandler = ( ) => {
93
+ const map = useMap ( ) ;
94
+
95
+ useEffect ( ( ) => {
96
+ if ( mapRef . current !== map ) {
97
+ mapRef . current = map ; // Set map reference only once
98
+ setCenter ( map . getCenter ( ) ) ; // Set the center once when the map is ready
99
+ logger . debug ( 'Map instance and reference set on load.' ) ;
100
+ }
101
+ } , [ map ] ) ;
102
+
103
+ return null ;
104
+ } ;
105
+
106
+ // Component to handle map events without triggering infinite loops
92
107
const CenterMarker = ( ) => {
93
- const map = useMapEvents ( {
108
+ useMapEvents ( {
94
109
moveend ( ) {
95
- setCenter ( map . getCenter ( ) ) ; // Update center state when the map stops moving
96
- } ,
97
- load ( ) {
98
- setCenter ( map . getCenter ( ) ) ; // Set initial center when the map loads
99
- mapRef . current = map ;
110
+ const newCenter = mapRef . current ?. getCenter ( ) ;
111
+ if ( newCenter && ( newCenter . lat !== center . lat || newCenter . lng !== center . lng ) ) {
112
+ setCenter ( newCenter ) ; // Update center state when the map stops moving
113
+ logger . debug ( `Map center updated to: ${ newCenter . lat } , ${ newCenter . lng } ` ) ;
114
+ }
100
115
} ,
101
116
} ) ;
102
117
103
- return center ? (
104
- < Marker position = { center } icon = { crosshairIcon } > </ Marker >
105
- ) : null ;
118
+ return center ? < Marker position = { center } icon = { crosshairIcon } > </ Marker > : null ;
106
119
} ;
107
120
108
- // Function to save the map center directly to the backend
109
121
const setMapCenter = async ( ) => {
110
122
if ( center !== null && currentUser ?. pi_uid ) {
111
- logger . info ( 'Setting map center to:' , { center } ) ;
112
123
try {
113
- const response = await saveMapCenter ( center . lat , center . lng ) ;
114
- logger . info ( 'Map center saved successfully:' , { response } ) ;
124
+ await saveMapCenter ( center . lat , center . lng ) ;
115
125
setShowPopup ( true ) ;
126
+ logger . info ( 'Map center successfully saved.' ) ;
116
127
} catch ( error ) {
117
- logger . error ( 'Error saving map center:' , { error } ) ;
128
+ logger . error ( 'Error saving map center:' , error ) ;
118
129
}
119
- } else {
120
- logger . warn ( 'User not authenticated or center coordinates are null' ) ; // Handle the case where the user is not authenticated or coordinates are null
121
130
}
122
131
} ;
123
132
124
- // Function to handle the closing of the confirmation popup
125
133
const handleClickDialog = ( ) => {
126
134
setShowPopup ( false ) ;
127
135
} ;
128
136
129
- // define map boundaries
130
- const bounds = L . latLngBounds (
131
- L . latLng ( - 90 , - 180 ) , // SW corner
132
- L . latLng ( 90 , 180 ) // NE corner
133
- ) ;
137
+ const bounds = L . latLngBounds ( L . latLng ( - 90 , - 180 ) , L . latLng ( 90 , 180 ) ) ;
134
138
135
139
return (
136
140
< div className = "search-container" >
137
- < p className = "search-text" > { t ( 'SHARED.MAP_CENTER.SEARCH_BAR_PLACEHOLDER' ) } </ p >
138
- < SearchBar
139
- onSearch = { handleSearch }
140
- page = { 'map_center' } />
141
- < MapContainer
142
- center = { center }
143
- zoom = { 2 }
144
- zoomControl = { false }
145
- minZoom = { 2 }
146
- maxZoom = { 18 }
147
- maxBounds = { bounds }
148
- maxBoundsViscosity = { 1.0 }
149
- className = "w-full flex-1 fixed top-[76.19px] h-[calc(100vh-76.19px)] left-0 right-0 bottom-0"
150
- whenReady = { ( ) => {
151
- if ( mapRef . current ) {
152
- // Perform actions if mapRef.current is already set
153
- }
154
- } }
155
- >
141
+ < p className = "search-text" > { t ( 'SHARED.MAP_CENTER.SEARCH_BAR_PLACEHOLDER' ) } </ p >
142
+ < SearchBar onSearch = { handleSearch } page = { 'map_center' } />
143
+ < MapContainer
144
+ center = { center }
145
+ zoom = { 2 }
146
+ zoomControl = { false }
147
+ minZoom = { 2 }
148
+ maxZoom = { 18 }
149
+ // maxBounds={bounds}
150
+ // maxBoundsViscosity={1.0}
151
+ className = "w-full flex-1 fixed top-[76.19px] h-[calc(100vh-76.19px)] left-0 right-0 bottom-0"
152
+ whenReady = { ( ) => {
153
+ const mapInstance : any = mapRef . current ;
154
+ if ( mapInstance ) {
155
+ logger . info ( 'Map instance set during map container ready state.' ) ;
156
+ }
157
+ } }
158
+ >
156
159
< TileLayer
157
160
url = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
158
161
attribution = "Map data © OpenStreetMap contributors"
159
162
noWrap = { true }
160
163
/>
161
164
< CenterMarker />
165
+ < MapHandler />
162
166
< RecenterAutomatically position = { center } />
163
167
</ MapContainer >
164
168
< div className = "absolute bottom-8 z-10 flex justify-center px-6 right-0 left-0 m-auto" >
165
169
< Button
166
170
label = "Set Map Center"
167
171
onClick = { setMapCenter }
168
- styles = { {
169
- borderRadius : '10px' ,
170
- color : '#ffc153' ,
171
- paddingLeft : '50px' ,
172
- paddingRight : '50px' ,
173
- } }
172
+ styles = { { borderRadius : '10px' , color : '#ffc153' , paddingLeft : '50px' , paddingRight : '50px' } }
174
173
/>
175
174
</ div >
176
175
{ showPopup && (
177
176
< ConfirmDialogX
178
177
toggle = { ( ) => setShowPopup ( false ) }
179
- handleClicked = { handleClickDialog } // Handles closing the confirmation popup
178
+ handleClicked = { handleClickDialog }
180
179
message = { t ( 'SHARED.MAP_CENTER.VALIDATION.SEARCH_CENTER_SUCCESS_MESSAGE' ) }
181
180
/>
182
181
) }
0 commit comments