1
- import L from 'leaflet' ;
2
- import React , { useEffect , useState } from 'react' ;
1
+ import { useEffect , useState , useCallback } from 'react' ;
3
2
import {
4
3
MapContainer ,
5
4
Marker ,
6
5
Popup ,
7
6
TileLayer ,
8
7
useMapEvents ,
9
8
} from 'react-leaflet' ;
9
+ import L from 'leaflet' ;
10
+ import { LatLngExpression , LatLngBounds } from 'leaflet' ;
11
+ import _ from 'lodash' ;
12
+
10
13
import MapMarkerPopup from './MapMarkerPopup' ;
11
14
import { dummyCoordinates } from '../../../constants/coordinates' ;
12
- import { Button , YellowBtn } from '../Forms/Buttons/Buttons' ;
13
- import { IoMdAdd } from 'react-icons/io' ;
14
- import { FaLocationCrosshairs } from 'react-icons/fa6' ;
15
- import { LatLng } from 'leaflet' ;
16
- import Image from 'next/image' ;
17
15
18
- function Map ( ) {
16
+ // Mock function to simulate fetching initial coordinates
17
+ const fetchSellerCoordinates = async ( origin : { lat : number ; lng : number } , radius : number ) : Promise < LatLngExpression [ ] > => {
18
+ console . log ( 'Fetching initial coordinates with origin:' , origin , 'and radius:' , radius ) ;
19
+
20
+ // Replace this mock function with the actual API call
21
+ // const response = await axios.get('/api/sellers', {
22
+ // params: { origin, radius }
23
+ // });
24
+ // return response.data;
25
+
26
+ return new Promise ( ( resolve ) => {
27
+ setTimeout ( ( ) => {
28
+ console . log ( 'Initial coordinates fetched:' , dummyCoordinates ) ;
29
+ resolve ( dummyCoordinates ) ;
30
+ } , 500 ) ;
31
+ } ) ;
32
+ } ;
33
+
34
+ // Mock function to simulate fetching additional data based on the map bounds
35
+ const fetchAdditionalSellerData = async ( center : { lat : number ; lng : number } , radius : number ) : Promise < LatLngExpression [ ] > => {
36
+ console . log ( 'Fetching additional seller data with center:' , center , 'and radius:' , radius ) ;
37
+
38
+ // Replace this mock function with the actual API call
39
+ // const response = await axios.get('/api/sellers/additional', {
40
+ // params: { center, radius }
41
+ // });
42
+ // return response.data;
43
+
44
+ return new Promise ( ( resolve ) => {
45
+ setTimeout ( ( ) => {
46
+ const additionalData = dummyCoordinates . slice ( 0 , 10 ) ; // Simulate fetching a subset of data
47
+ resolve ( additionalData ) ;
48
+ } , 500 ) ;
49
+ } ) ;
50
+ } ;
51
+
52
+ const Map = ( ) => {
19
53
const customIcon = L . icon ( {
20
54
iconUrl : '/favicon-32x32.png' ,
21
55
iconSize : [ 32 , 32 ] ,
22
56
iconAnchor : [ 12 , 41 ] ,
23
57
popupAnchor : [ 1 , - 34 ] ,
24
58
} ) ;
25
59
26
- const [ position , setPosition ] = useState < LatLng | null > ( null ) ;
60
+ const [ position , setPosition ] = useState < L . LatLng | null > ( null ) ;
61
+ const [ sellerCoordinates , setSellerCoordinates ] = useState < LatLngExpression [ ] > ( [ ] ) ;
62
+ const [ origin , setOrigin ] = useState ( { lat : - 1.6279 , lng : 29.7451 } ) ;
63
+ const [ radius , setRadius ] = useState ( 5 ) ; // Initial radius in km
64
+ const [ loading , setLoading ] = useState ( false ) ;
65
+ const [ error , setError ] = useState < string | null > ( null ) ;
66
+
67
+ useEffect ( ( ) => {
68
+ fetchInitialCoordinates ( ) ;
69
+ } , [ ] ) ;
70
+
71
+ const fetchInitialCoordinates = async ( ) => {
72
+ setLoading ( true ) ;
73
+ setError ( null ) ;
74
+ try {
75
+ const coordinates = await fetchSellerCoordinates ( origin , radius ) ;
76
+ setSellerCoordinates ( coordinates ) ;
77
+ } catch ( err ) {
78
+ setError ( 'Failed to fetch initial coordinates' ) ;
79
+ } finally {
80
+ setLoading ( false ) ;
81
+ }
82
+ } ;
83
+
84
+ const handleMapInteraction = async ( newBounds : L . LatLngBounds ) => {
85
+ const newCenter = newBounds . getCenter ( ) ;
86
+ const newRadius = calculateRadius ( newBounds ) ;
87
+ setLoading ( true ) ;
88
+ setError ( null ) ;
89
+ try {
90
+ const additionalData = await fetchAdditionalSellerData ( { lat : newCenter . lat , lng : newCenter . lng } , newRadius ) ;
91
+ if ( additionalData . length > 0 ) {
92
+ setSellerCoordinates ( ( prevCoordinates ) => {
93
+ const newCoordinates = [ ...prevCoordinates , ...additionalData ] ;
94
+ return newCoordinates ;
95
+ } ) ;
96
+ } else {
97
+ console . warn ( 'No additional seller data found for the new bounds.' ) ;
98
+ }
99
+ } catch ( err ) {
100
+ setError ( 'Failed to fetch additional data' ) ;
101
+ } finally {
102
+ setLoading ( false ) ;
103
+ }
104
+ } ;
105
+
106
+ const calculateRadius = ( bounds : L . LatLngBounds ) => {
107
+ // Implement logic to calculate radius based on map bounds
108
+ return 10 ; // Example radius value
109
+ } ;
110
+
111
+ const debouncedHandleMapInteraction = useCallback (
112
+ _ . debounce ( ( bounds : LatLngBounds ) => {
113
+ handleMapInteraction ( bounds ) ;
114
+ } , 500 ) ,
115
+ [ ]
116
+ ) ;
117
+
27
118
function LocationMarker ( ) {
28
119
const map = useMapEvents ( {
29
- // layeradd() {
30
- // map.locate();
31
- // },
32
- // click() {
33
- // map.locate();
34
- // },
35
120
locationfound ( e ) {
36
121
setPosition ( e . latlng ) ;
37
122
map . flyTo ( e . latlng , map . getZoom ( ) ) ;
38
123
} ,
124
+ moveend ( ) {
125
+ const bounds = map . getBounds ( ) ;
126
+ debouncedHandleMapInteraction ( bounds ) ;
127
+ } ,
128
+ zoomend ( ) {
129
+ const bounds = map . getBounds ( ) ;
130
+ debouncedHandleMapInteraction ( bounds ) ;
131
+ } ,
39
132
} ) ;
40
133
41
- return (
42
- < >
43
-
44
- { position === null ? null : (
45
- < Marker position = { position } >
46
- < Popup > You are here</ Popup >
47
- </ Marker >
48
- ) }
49
- </ >
134
+ return position === null ? null : (
135
+ < Marker position = { position } >
136
+ < Popup > You are here</ Popup >
137
+ </ Marker >
50
138
) ;
51
139
}
52
140
53
141
return (
54
142
< >
143
+ { loading && < div className = "loading" > Loading...</ div > }
144
+ { error && < div className = "error" > { error } </ div > }
55
145
< MapContainer
56
- center = { { lat : - 1.6279 , lng : 29.7451 } }
146
+ center = { origin }
57
147
zoom = { 13 }
58
148
zoomControl = { false }
59
- // scrollWheelZoom={false}
60
- className = "w-full flex-1 fixed top-[76.19px] h-[calc(100vh-76.19px)] left-0 right-0 bottom-0" >
149
+ className = "w-full flex-1 fixed top-[90px] h-[calc(100vh-55px)] left-0 right-0 bottom-0" >
61
150
< TileLayer
62
151
attribution = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
63
152
url = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
64
153
/>
65
154
< LocationMarker />
66
- { dummyCoordinates . map ( ( coord , i ) => (
155
+ { sellerCoordinates . map ( ( coord , i ) => (
67
156
< Marker position = { coord } key = { i } icon = { customIcon } >
68
157
< Popup closeButton = { false } >
69
158
< MapMarkerPopup />
@@ -72,7 +161,6 @@ function Map() {
72
161
) ) }
73
162
</ MapContainer >
74
163
</ >
75
- ) ;
76
- }
164
+ ) } ;
77
165
78
166
export default Map ;
0 commit comments