@navigoo/map-components 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@navigoo/map-components",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Reusable React components for mapping and routing in Yaoundé",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useRef } from 'react';
1
+ import React, { useEffect, useRef, useState } from 'react';
2
2
  import L from 'leaflet';
3
3
  import 'leaflet/dist/leaflet.css';
4
4
  import { parse } from 'wellknown';
@@ -28,6 +28,77 @@ const MapView: React.FC<MapViewProps> = ({
28
28
  const routeLayerRef = useRef<L.LayerGroup | null>(null);
29
29
  const clickMarkerRef = useRef<L.Marker | null>(null);
30
30
  const routePolylinesRef = useRef<L.Polyline[]>([]);
31
+ const [ipLocation, setIpLocation] = useState<{ lat: number; lng: number } | null>(null);
32
+
33
+ // Fonction pour obtenir la localisation par IP
34
+ const getLocationByIP = async (): Promise<{ lat: number; lng: number } | null> => {
35
+ try {
36
+ const response = await fetch('https://ipapi.co/json/');
37
+ const data = await response.json();
38
+
39
+ if (data.latitude && data.longitude) {
40
+ return {
41
+ lat: data.latitude,
42
+ lng: data.longitude
43
+ };
44
+ }
45
+ return null;
46
+ } catch (error) {
47
+ console.error('Erreur de géolocalisation par IP:', error);
48
+ return null;
49
+ }
50
+ };
51
+
52
+ // Fonction pour obtenir la localisation par le navigateur
53
+ const getBrowserLocation = (): Promise<{ lat: number; lng: number }> => {
54
+ return new Promise((resolve, reject) => {
55
+ if (!navigator.geolocation) {
56
+ reject(new Error('Géolocalisation non supportée'));
57
+ return;
58
+ }
59
+
60
+ navigator.geolocation.getCurrentPosition(
61
+ (position) => {
62
+ resolve({
63
+ lat: position.coords.latitude,
64
+ lng: position.coords.longitude
65
+ });
66
+ },
67
+ (error) => {
68
+ reject(error);
69
+ },
70
+ {
71
+ enableHighAccuracy: true,
72
+ timeout: 10000,
73
+ maximumAge: 60000
74
+ }
75
+ );
76
+ });
77
+ };
78
+
79
+ // Effet pour la géolocalisation au démarrage
80
+ useEffect(() => {
81
+ const initializeLocation = async () => {
82
+ try {
83
+ // Essayer d'abord la géolocalisation du navigateur
84
+ const browserLocation = await getBrowserLocation();
85
+ setIpLocation(browserLocation);
86
+ } catch (browserError) {
87
+ console.log('Géolocalisation navigateur échouée, tentative par IP...', browserError);
88
+
89
+ // Fallback sur la géolocalisation par IP
90
+ const ipLocation = await getLocationByIP();
91
+ if (ipLocation) {
92
+ setIpLocation(ipLocation);
93
+ } else {
94
+ // Fallback final sur une position par défaut (centre du monde)
95
+ setIpLocation({ lat: 20, lng: 0 });
96
+ }
97
+ }
98
+ };
99
+
100
+ initializeLocation();
101
+ }, []);
31
102
 
32
103
  const parseWKTLineString = (wkt: string): [number, number][] => {
33
104
  try {
@@ -52,18 +123,20 @@ const MapView: React.FC<MapViewProps> = ({
52
123
 
53
124
  useEffect(() => {
54
125
  if (mapContainerRef.current && !mapRef.current) {
126
+ // Position par défaut centrée sur le monde, sera mise à jour par la géolocalisation
127
+ const defaultCenter = ipLocation || { lat: 20, lng: 0 };
128
+
55
129
  mapRef.current = L.map(mapContainerRef.current, {
56
- center: [3.8480, 11.5021], // Centre par défaut : Yaoundé
130
+ center: [defaultCenter.lat, defaultCenter.lng],
57
131
  zoom: 12,
58
- minZoom: 11,
59
- maxZoom: 16,
60
- maxBounds: [[3.7, 11.4], [4.0, 11.6]],
61
- maxBoundsViscosity: 1.0,
132
+ minZoom: 2, // Zoom minimal réduit pour voir le monde entier
133
+ maxZoom: 18, // Zoom maximal augmenté pour plus de détails
134
+ // Suppression des limites de la carte
62
135
  });
63
136
 
64
137
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
65
138
  attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
66
- maxZoom: 16,
139
+ maxZoom: 18,
67
140
  }).addTo(mapRef.current);
68
141
 
69
142
  L.Icon.Default.mergeOptions({
@@ -91,13 +164,26 @@ const MapView: React.FC<MapViewProps> = ({
91
164
  });
92
165
  }
93
166
 
167
+ // Mettre à jour le centre de la carte quand la localisation par IP est disponible
168
+ if (mapRef.current && ipLocation && !userLocation && !searchedPlace && !routes) {
169
+ mapRef.current.setView([ipLocation.lat, ipLocation.lng], 12, { animate: true });
170
+
171
+ // Ajouter un marqueur pour la position détectée
172
+ if (!markerRef.current) {
173
+ markerRef.current = L.marker([ipLocation.lat, ipLocation.lng])
174
+ .addTo(mapRef.current)
175
+ .bindPopup(`<b>Votre position approximative</b><br>Détectée par IP<br>Lat: ${ipLocation.lat.toFixed(6)}<br>Lng: ${ipLocation.lng.toFixed(6)}`)
176
+ .openPopup();
177
+ }
178
+ }
179
+
94
180
  return () => {
95
181
  if (mapRef.current) {
96
182
  mapRef.current.remove();
97
183
  mapRef.current = null;
98
184
  }
99
185
  };
100
- }, [apiClient]);
186
+ }, [apiClient, ipLocation]);
101
187
 
102
188
  useEffect(() => {
103
189
  if (!mapRef.current) return;
@@ -190,10 +276,14 @@ const MapView: React.FC<MapViewProps> = ({
190
276
  centerOnPoint(searchedPlace.coordinates.lat, searchedPlace.coordinates.lng, searchedPlace.name);
191
277
  } else if (userLocation) {
192
278
  centerOnPoint(userLocation.latitude, userLocation.longitude, 'Votre position');
279
+ } else if (ipLocation) {
280
+ // Centrer sur la position IP si aucune autre position n'est disponible
281
+ centerOnPoint(ipLocation.lat, ipLocation.lng, 'Votre position approximative', 12);
193
282
  } else {
194
- mapRef.current!.setView([3.8480, 11.5021], 12, { animate: true });
283
+ // Position de fallback centrée sur le monde
284
+ mapRef.current!.setView([20, 0], 2, { animate: true });
195
285
  }
196
- }, [apiClient, userLocation, searchedPlace, routes, selectedRouteIndex, setSelectedRouteIndex]);
286
+ }, [apiClient, userLocation, searchedPlace, routes, selectedRouteIndex, setSelectedRouteIndex, ipLocation]);
197
287
 
198
288
  return <div className="w-full h-screen" ref={mapContainerRef} />;
199
289
  };