datastake-daf 0.6.273 β†’ 0.6.274

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.
@@ -48,30 +48,15 @@ export const useGlobe = ({
48
48
  const isMounted = useRef(true);
49
49
 
50
50
  const addAllDataToMap = useCallback(() => {
51
- console.log('πŸš€ [GLOBE HOOK] addAllDataToMap called');
52
- console.log('πŸš€ [GLOBE HOOK] data:', data);
53
- console.log('πŸš€ [GLOBE HOOK] mapRef exists:', !!mapRef);
54
- console.log('πŸš€ [GLOBE HOOK] style loaded:', mapRef?.isStyleLoaded());
55
-
56
- if (!data || !mapRef) {
57
- console.log('❌ [GLOBE HOOK] addAllDataToMap early return - missing data or mapRef');
58
- return;
59
- }
60
-
61
- if (!mapRef.isStyleLoaded()) {
62
- console.log('⏳ [GLOBE HOOK] Style not loaded yet, retrying in 100ms...');
63
- setTimeout(() => {
64
- addAllDataToMap();
65
- }, 100);
51
+
52
+ if (!data || !mapRef || !mapRef.isStyleLoaded()) {
66
53
  return;
67
54
  }
68
55
 
56
+ // Prevent multiple calls with empty data
69
57
  if (data.length === 0) {
70
- console.log('❌ [GLOBE HOOK] addAllDataToMap early return - no data');
71
58
  return;
72
59
  }
73
-
74
- console.log('βœ… [GLOBE HOOK] Starting to add markers to map...');
75
60
 
76
61
  // Clear existing markers using functional update to avoid dependency issues
77
62
  setMapMarkers(currentMarkers => {
@@ -123,14 +108,8 @@ export const useGlobe = ({
123
108
  const newMarkers = [];
124
109
  const maxTotal = Math.max(...(data || []).map((d) => d.total || 0));
125
110
 
126
- console.log('🎯 [GLOBE HOOK] Processing data items:', data.length);
127
111
  data.forEach((d, i) => {
128
- console.log(`🎯 [GLOBE HOOK] Processing item ${i}:`, d);
129
- console.log(`🎯 [GLOBE HOOK] Item ${i} marker:`, d?.marker);
130
- console.log(`🎯 [GLOBE HOOK] Item ${i} lat/lng:`, d?.marker?.lat, d?.marker?.lng);
131
-
132
112
  if (d?.marker?.lat && d?.marker?.lng) {
133
- console.log(`βœ… [GLOBE HOOK] Item ${i} has valid coordinates, creating marker...`);
134
113
  let marker;
135
114
  let iconClassName = "";
136
115
  let innerHtml = "";
@@ -233,8 +212,6 @@ export const useGlobe = ({
233
212
  .setLngLat([d.marker.lng, d.marker.lat])
234
213
  .setPopup(new mapboxgl.Popup().setDOMContent(div))
235
214
  .addTo(mapRef);
236
-
237
- console.log(`πŸŽ‰ [GLOBE HOOK] Marker ${i} added to map at:`, [d.marker.lng, d.marker.lat]);
238
215
 
239
216
  } else if (type === "territory") {
240
217
  // Handle territory polygons
@@ -320,8 +297,6 @@ export const useGlobe = ({
320
297
  .setLngLat([d.marker.lng, d.marker.lat])
321
298
  .setPopup(new mapboxgl.Popup().setDOMContent(div))
322
299
  .addTo(mapRef);
323
-
324
- console.log(`πŸŽ‰ [GLOBE HOOK] Default marker ${i} added to map at:`, [d.marker.lng, d.marker.lat]);
325
300
  }
326
301
 
327
302
  // Add click handler
@@ -355,7 +330,6 @@ export const useGlobe = ({
355
330
  mapboxgl.accessToken = MAP_TOKEN;
356
331
 
357
332
  // Create the map with Mapbox GL JS - 3D globe
358
- console.log('πŸ—ΊοΈ [GLOBE HOOK] Creating map with style:', STYLE_URL);
359
333
  const map = new mapboxgl.Map({
360
334
  container: container.current,
361
335
  style: STYLE_URL,
@@ -374,13 +348,9 @@ export const useGlobe = ({
374
348
 
375
349
  // Configure the map when style loads
376
350
  map.on('style.load', () => {
377
- console.log('🎨 [GLOBE HOOK] Style loaded event triggered');
378
- console.log('🎨 [GLOBE HOOK] Map style loaded:', map.isStyleLoaded());
379
351
 
380
352
  // Wait a bit for the style to fully load
381
353
  setTimeout(() => {
382
- console.log('🎨 [GLOBE HOOK] After timeout - Map style loaded:', map.isStyleLoaded());
383
-
384
354
  // Set fog for the space background effect with stars - simplified to avoid errors
385
355
  try {
386
356
  map.setFog({
@@ -475,10 +445,9 @@ export const useGlobe = ({
475
445
  // Add navigation controls
476
446
  map.addControl(new mapboxgl.NavigationControl(), 'top-right');
477
447
 
478
- console.log('πŸ—ΊοΈ [GLOBE HOOK] Map created successfully');
479
448
  return map;
480
449
  } catch (error) {
481
- console.error('❌ [GLOBE HOOK] Error creating Mapbox GL JS globe:', error);
450
+ console.error('Error creating Mapbox GL JS globe:', error);
482
451
  return null;
483
452
  }
484
453
  }, []);
@@ -491,13 +460,10 @@ export const useGlobe = ({
491
460
  // }, [initialMarkerSetIsDone]);
492
461
 
493
462
  useEffect(() => {
494
- console.log('πŸ”„ [GLOBE HOOK] useEffect for map creation - mapRef:', !!mapRef);
495
463
 
496
464
  if (!mapRef) {
497
- console.log('πŸ”„ [GLOBE HOOK] Creating map instance...');
498
465
  const instance = createInstance();
499
466
  if (instance) {
500
- console.log('πŸ”„ [GLOBE HOOK] Map instance created, setting mapRef');
501
467
  setMapRef(instance);
502
468
 
503
469
  // Add comprehensive resize detection for Mapbox GL JS responsiveness
@@ -586,24 +552,15 @@ export const useGlobe = ({
586
552
  }, [polygon, mapRef]);
587
553
 
588
554
  useEffect(() => {
589
- console.log('πŸ“₯ [GLOBE HOOK] allData received:', allData);
590
- console.log('πŸ“₯ [GLOBE HOOK] allData length:', allData?.length);
591
-
555
+
592
556
  if (allData) {
593
557
  if (allData.length === 0) {
594
- console.log('⚠️ [GLOBE HOOK] Empty data array');
595
558
  setEmptyStateIsVisible(true);
596
559
  } else if (emptyStateIsVisible) {
597
560
  setEmptyStateIsVisible(false);
598
561
  }
599
-
600
- console.log('πŸ” [GLOBE HOOK] Filtering data with filterValidGPS...');
601
- const filteredData = filterValidGPS(allData);
602
- console.log('πŸ” [GLOBE HOOK] filtered data result:', filteredData);
603
- console.log('πŸ” [GLOBE HOOK] filtered data length:', filteredData.length);
604
- setData(filteredData);
562
+ setData(filterValidGPS(allData));
605
563
  } else {
606
- console.log('❌ [GLOBE HOOK] No allData provided');
607
564
  setData(null);
608
565
  }
609
566
  }, [allData, emptyStateIsVisible]);
@@ -634,20 +591,7 @@ export const useGlobe = ({
634
591
  }, [user, mapRef, allData]);
635
592
 
636
593
  useEffect(() => {
637
- console.log('πŸ”„ [GLOBE HOOK] useEffect triggered:', {
638
- mapRef: !!mapRef,
639
- data: !!data,
640
- dataLength: data?.length,
641
- initialMarkerSetIsDone,
642
- styleLoaded: mapRef?.isStyleLoaded()
643
- });
644
-
645
- if (mapRef && data && !initialMarkerSetIsDone) {
646
- console.log('πŸš€ [GLOBE HOOK] Attempting to add markers...');
647
- console.log('πŸš€ [GLOBE HOOK] Style loaded check:', mapRef.isStyleLoaded());
648
-
649
- // Try to add markers immediately, and if style isn't loaded,
650
- // the addAllDataToMap function will handle it
594
+ if (mapRef && data && !initialMarkerSetIsDone && mapRef.isStyleLoaded()) {
651
595
  setInitialMarkerSetIsDone(true);
652
596
  addAllDataToMap();
653
597
  }
@@ -111,7 +111,7 @@ function Globe({
111
111
  renderSider = null,
112
112
  renderMarker = null,
113
113
  type = "default",
114
- showSider = false,
114
+ showSider = true,
115
115
  filtersConfig,
116
116
  onFilterChange = () => { },
117
117
  isSatellite = false,
@@ -122,29 +122,11 @@ function Globe({
122
122
  }) {
123
123
  // Map data to include marker coordinates
124
124
  const mappedData = useMemo(
125
- () => {
126
- console.log('πŸ“Š [GLOBE COMPONENT] Original data received:', data);
127
- console.log('πŸ“Š [GLOBE COMPONENT] Data length:', data?.length);
128
-
129
- if (!data || data.length === 0) {
130
- console.log('❌ [GLOBE COMPONENT] No data to map');
131
- return [];
132
- }
133
-
134
- const mapped = data.map((d, i) => {
135
- console.log(`πŸ“Š [GLOBE COMPONENT] Mapping item ${i}:`, d);
136
- console.log(`πŸ“Š [GLOBE COMPONENT] Item ${i} GPS:`, d?.gps);
137
- const result = {
138
- ...d,
139
- marker: { lat: d?.gps?.latitude, lng: d?.gps?.longitude },
140
- };
141
- console.log(`πŸ“Š [GLOBE COMPONENT] Item ${i} mapped result:`, result);
142
- return result;
143
- });
144
-
145
- console.log('πŸ“Š [GLOBE COMPONENT] Final mapped data:', mapped);
146
- return mapped;
147
- },
125
+ () =>
126
+ data.map((d) => ({
127
+ ...d,
128
+ marker: { lat: d?.gps?.latitude, lng: d?.gps?.longitude },
129
+ })),
148
130
  [data],
149
131
  );
150
132
 
@@ -59,22 +59,38 @@ const Style = styled.div`
59
59
  height: 100%;
60
60
  }
61
61
 
62
- /* Narrow marker styling used by legacy components; avoid width/height overrides for SimpleGlobe */
63
62
  .map-marker {
64
63
  text-align: center;
64
+ width 100%;
65
+ height: 100%;
65
66
  border-radius: 50% 50% 50% 0;
66
67
 
67
68
  span {
68
69
  color: white;
69
70
  }
70
71
 
71
- &.rounded { border-radius: 100%; }
72
- &.incident { border-radius: 100%; }
73
- &.marker { background: var(--color-primary-70); border: 1px solid white; box-shadow: 0px 3.45px 3.45px 0px #00000029; }
74
- }
72
+ &.rounded {
73
+ border-radius: 100%;
74
+ }
75
+
76
+ &.incident {
77
+ border-radius: 100%;
75
78
 
76
- /* Scoped class used by SimpleGlobe to avoid picking up broad .map-marker rules */
77
- .daf-globe-marker { text-align: center; }
79
+ .main {
80
+ border-radius: 100%;
81
+ height: 100%;
82
+ display: flex;
83
+ flex-direction: column;
84
+ justify-content: center;
85
+ }
86
+ }
87
+
88
+ &.marker {
89
+ background: var(--color-primary-70);
90
+ border: 1px solid white;
91
+ box-shadow: 0px 3.45px 3.45px 0px #00000029;
92
+ }
93
+ }
78
94
 
79
95
  #globe {
80
96
  flex: 1;
@@ -154,11 +154,11 @@ export const renderTooltipJsx = ({
154
154
  />
155
155
  </div>
156
156
  )}
157
- <Tooltip title={item.label}>
157
+ <Tooltip title={item.tooltipLabel || item.label}>
158
158
  <span className="daf-tooltip-name">{item.label}</span>
159
159
  </Tooltip>
160
160
 
161
- <Tooltip title={item.value}>
161
+ <Tooltip title={item.tooltipValue || item.value}>
162
162
  <div
163
163
  style={{
164
164
  height: "20px",
package/src/index.js CHANGED
@@ -62,7 +62,6 @@ export { default as TooltipIcon } from "./@daf/core/components/Icon/TooltipIcon.
62
62
  export { default as MineSiteMap } from "./@daf/core/components/Dashboard/Map/index.jsx";
63
63
  export { default as InExpandableWidgetMap } from "./@daf/core/components/Dashboard/Map/InExpandableWidgetMap/index.jsx";
64
64
  export { default as Globe } from "./@daf/core/components/Dashboard/Globe/index.jsx";
65
- export { default as SimpleGlobe } from "./@daf/core/components/Dashboard/Globe/SimpleGlobe.jsx";
66
65
  export { default as WidgetPlaceholder } from "./@daf/core/components/Dashboard/Widget/WidgetPlaceholder/index.jsx";
67
66
  export { default as Steps } from "./@daf/core/components/Dashboard/Steps/index.jsx";
68
67
  export { default as DashboardLayout } from "./@daf/core/components/Dashboard/DashboardLayout/index.jsx";
@@ -1,106 +0,0 @@
1
- # SimpleGlobe Component
2
-
3
- A simplified wrapper for the Globe component that makes it easy to display project data as pins on a 3D globe.
4
-
5
- ## Features
6
-
7
- - πŸ—ΊοΈ **3D Globe Visualization**: Interactive 3D globe using Mapbox GL JS
8
- - πŸ“ **Pin-based Display**: Projects are displayed as clickable pins on the globe
9
- - 🎯 **Simple Integration**: Just pass your project data and it works
10
- - πŸ“Š **Rich Tooltips**: Hover over pins to see project details
11
- - 🎨 **Customizable**: Support for custom map configurations
12
-
13
- ## Quick Start
14
-
15
- ```jsx
16
- import SimpleGlobe from './SimpleGlobe';
17
-
18
- const MyComponent = () => {
19
- const projects = [
20
- {
21
- name: "Solar Project",
22
- latitude: 14.7167,
23
- longitude: -17.4677,
24
- percentageCompletion: 75,
25
- projectDescription: "Large-scale solar energy project"
26
- }
27
- ];
28
-
29
- return (
30
- <div style={{ width: '100%', height: '600px' }}>
31
- <SimpleGlobe
32
- projects={projects}
33
- onProjectClick={(project) => console.log('Clicked:', project)}
34
- />
35
- </div>
36
- );
37
- };
38
- ```
39
-
40
- ## Props
41
-
42
- | Prop | Type | Default | Description |
43
- |------|------|---------|-------------|
44
- | `projects` | `Array` | `[]` | Array of project objects |
45
- | `mapConfig` | `Object` | `{}` | Map configuration options |
46
- | `showSider` | `boolean` | `false` | Whether to show the sidebar |
47
- | `onProjectClick` | `Function` | `() => {}` | Callback when a project pin is clicked |
48
-
49
- ## Project Data Format
50
-
51
- Your project objects should have the following structure:
52
-
53
- ```javascript
54
- {
55
- _id: "unique-id", // Optional: Unique identifier
56
- name: "Project Name", // Required: Project name
57
- latitude: 14.7167, // Required: Latitude coordinate
58
- longitude: -17.4677, // Required: Longitude coordinate
59
- projectDescription: "Description", // Optional: Project description
60
- country: "SN", // Optional: Country code
61
- sectoralScope: "energy", // Optional: Project sector
62
- percentageCompletion: 75, // Optional: Completion percentage
63
- author: { name: "Author Name" } // Optional: Author information
64
- }
65
- ```
66
-
67
- ## Examples
68
-
69
- ### Basic Usage
70
- ```jsx
71
- <SimpleGlobe projects={myProjects} />
72
- ```
73
-
74
- ### With Sidebar
75
- ```jsx
76
- <SimpleGlobe
77
- projects={myProjects}
78
- showSider={true}
79
- />
80
- ```
81
-
82
- ### With Custom Configuration
83
- ```jsx
84
- <SimpleGlobe
85
- projects={myProjects}
86
- mapConfig={{
87
- maxZoom: 8,
88
- minZoom: 2
89
- }}
90
- onProjectClick={(project) => {
91
- // Handle project click
92
- console.log('Project clicked:', project);
93
- }}
94
- />
95
- ```
96
-
97
- ## Storybook
98
-
99
- You can see all examples in Storybook under "Dashboard/Globe/SimpleGlobe".
100
-
101
- ## Notes
102
-
103
- - The component automatically transforms your project data to the format expected by the underlying Globe component
104
- - Pins are displayed as circular markers with project completion percentage
105
- - Tooltips show project details when hovering over pins
106
- - The globe is fully interactive - you can zoom, pan, and rotate
@@ -1,259 +0,0 @@
1
- import React, { useEffect, useRef } from 'react';
2
- import mapboxgl from 'mapbox-gl';
3
- import 'mapbox-gl/dist/mapbox-gl.css';
4
- import Style from './style';
5
-
6
- /**
7
- * SimpleGlobe - A simplified wrapper for the Globe component
8
- *
9
- * This component makes it easy to display project data as pins on a 3D globe.
10
- * Just pass your project data and it will automatically create pins at the specified locations.
11
- *
12
- * @param {Array} projects - Array of project objects with location data
13
- * @param {string} projects[].name - Project name
14
- * @param {number} projects[].latitude - Latitude coordinate
15
- * @param {number} projects[].longitude - Longitude coordinate
16
- * @param {string} projects[].description - Project description (optional)
17
- * @param {string} projects[].country - Country code (optional)
18
- * @param {string} projects[].sectoralScope - Project sector (optional)
19
- * @param {number} projects[].percentageCompletion - Completion percentage (optional)
20
- * @param {Object} projects[].author - Author information (optional)
21
- * @param {Object} mapConfig - Map configuration options (optional)
22
- * @param {boolean} showSider - Whether to show the sidebar (default: false)
23
- * @param {Function} onProjectClick - Callback when a project pin is clicked
24
- * @param {string} type - Marker type: "default" for circular markers, "location" for map pin markers
25
- * @param {string} color - Marker color (default: "var(--color-primary-60)")
26
- */
27
- const SimpleGlobe = ({
28
- projects = [],
29
- mapConfig = {},
30
- showSider = false,
31
- onProjectClick = () => {},
32
- type = "default",
33
- color = "var(--color-primary-60)"
34
- }) => {
35
- const mapContainer = useRef(null);
36
- const map = useRef(null);
37
-
38
- useEffect(() => {
39
- if (map.current) return; // Initialize map only once
40
-
41
- console.log('πŸ—ΊοΈ [SIMPLE GLOBE] Creating map...');
42
-
43
- // Set Mapbox access token
44
- mapboxgl.accessToken = 'pk.eyJ1IjoicmVkaXM5OTkiLCJhIjoiY2x4YWV5MzA5MmtuZzJpcXM5Y201Z2E2YiJ9.m5bwPg-Tj4Akesl1yQUa3w';
45
-
46
- // Create map with custom Straatos style
47
- map.current = new mapboxgl.Map({
48
- container: mapContainer.current,
49
- style: 'mapbox://styles/pietragottardo/cm9tt9zfi00d101pg1vdx26si',
50
- center: [0, 0],
51
- zoom: mapConfig.maxZoom || 3,
52
- projection: 'globe',
53
- attributionControl: false
54
- });
55
-
56
- // Add markers when map loads
57
- map.current.on('load', () => {
58
- console.log('πŸ—ΊοΈ [SIMPLE GLOBE] Map loaded, adding markers...');
59
-
60
- // Hide Mapbox logo and attribution completely
61
- const mapContainer = map.current.getContainer();
62
- const style = document.createElement('style');
63
- style.textContent = `
64
- .mapboxgl-ctrl-logo,
65
- .mapboxgl-ctrl-attrib,
66
- .mapboxgl-ctrl-bottom-left,
67
- .mapboxgl-ctrl-bottom-right {
68
- display: none !important;
69
- }
70
- .mapboxgl-canvas-container {
71
- overflow: hidden !important;
72
- }
73
- .mapboxgl-canvas {
74
- overflow: hidden !important;
75
- }
76
- `;
77
- document.head.appendChild(style);
78
-
79
- // Set the space background with stars
80
- try {
81
- map.current.setFog({
82
- 'color': 'rgb(0, 0, 0)',
83
- 'high-color': 'rgb(0, 0, 0)',
84
- 'horizon-blend': 0.1,
85
- 'space-color': 'rgb(0, 0, 0)',
86
- 'star-intensity': 0.6
87
- });
88
- console.log('✨ [SIMPLE GLOBE] Space background with stars set');
89
- } catch (e) {
90
- console.log('⚠️ [SIMPLE GLOBE] Could not set fog, trying alternative...');
91
- // Fallback: try simpler fog configuration
92
- try {
93
- map.current.setFog({
94
- 'color': 'rgb(0, 0, 0)',
95
- 'high-color': 'rgb(0, 0, 0)',
96
- 'horizon-blend': 0.1
97
- });
98
- console.log('✨ [SIMPLE GLOBE] Alternative space background set');
99
- } catch (e2) {
100
- console.log('⚠️ [SIMPLE GLOBE] Could not set any fog configuration');
101
- }
102
- }
103
-
104
- // Calculate bounds to fit all markers
105
- const bounds = new mapboxgl.LngLatBounds();
106
- let hasValidCoordinates = false;
107
-
108
- projects.forEach((project, index) => {
109
- console.log(`πŸ“ [SIMPLE GLOBE] Adding marker ${index}:`, project);
110
-
111
- // Create marker element based on type
112
- const el = document.createElement('div');
113
- // Use a scoped class to avoid picking up broad styles like `.map-marker { width:100% }`
114
- el.className = 'daf-globe-marker';
115
- el.style.cursor = 'pointer';
116
- el.style.boxShadow = '0px 3.45px 3.45px 0px #00000029';
117
- el.style.display = 'flex';
118
- el.style.alignItems = 'center';
119
- el.style.justifyContent = 'center';
120
-
121
- if (type === "location") {
122
- // Location marker - SVG map pin style
123
- el.style.width = '28px';
124
- el.style.height = '33px';
125
- el.innerHTML = `
126
- <svg
127
- width="28"
128
- height="33"
129
- viewBox="0 0 28 33"
130
- fill="none"
131
- xmlns="http://www.w3.org/2000/svg"
132
- >
133
- <path
134
- d="M5.14346 4.87419C10.0688 -0.15896 18.0528 -0.162058 22.9757 4.86861C27.6563 9.65161 27.8841 17.2616 23.6622 22.3255H23.6608C23.427 22.6141 23.1808 22.894 22.9211 23.1623L14.0671 32.2101L5.44057 23.3948L5.13868 23.096C0.215857 18.0655 0.218422 9.90737 5.14346 4.87419Z"
135
- fill="${color}"
136
- stroke="white"
137
- />
138
- </svg>
139
- `;
140
- } else {
141
- // Default circular marker style
142
- el.style.width = '30px';
143
- el.style.height = '30px';
144
- el.style.backgroundColor = color;
145
- el.style.borderRadius = '50%';
146
- el.style.border = '2px solid white';
147
- el.style.color = 'white';
148
- el.style.fontWeight = 'bold';
149
- el.style.fontSize = '14px';
150
- el.style.textAlign = 'center';
151
- el.style.lineHeight = '1';
152
- el.innerHTML = `<span style="display: block; line-height: 1;">${project.percentageCompletion || 0}</span>`;
153
- }
154
-
155
- // Create popup content using the same structure as minesitemap
156
- const popupContent = `
157
- <div class="daf-tooltip-cont">
158
- <div class="daf-tooltip-head">
159
- <div class="daf-tooltip-title">
160
- <div>
161
- <h4>${project.name}</h4>
162
- <h5>${project.sectoralScope || 'Project'}</h5>
163
- </div>
164
- </div>
165
- </div>
166
- <div class="daf-tooltip-list">
167
- <div class="daf-tooltip-list-item">
168
- <span class="daf-tooltip-name">Country</span>
169
- <span class="daf-tooltip-value">${project.country || 'N/A'}</span>
170
- </div>
171
- <div class="daf-tooltip-list-item">
172
- <span class="daf-tooltip-name">Completion</span>
173
- <span class="daf-tooltip-value">${project.percentageCompletion || 0}%</span>
174
- </div>
175
- <div class="daf-tooltip-list-item">
176
- <span class="daf-tooltip-name">Author</span>
177
- <span class="daf-tooltip-value">${project.author?.name || 'N/A'}</span>
178
- </div>
179
- <div class="daf-tooltip-list-item">
180
- <span class="daf-tooltip-name">ID</span>
181
- <span class="daf-tooltip-value">${project.datastakeId || 'N/A'}</span>
182
- </div>
183
- </div>
184
- </div>
185
- `;
186
-
187
- // Create popup
188
- const popup = new mapboxgl.Popup({
189
- offset: 25,
190
- closeButton: true,
191
- closeOnClick: false
192
- }).setHTML(popupContent);
193
-
194
- // Ensure coordinates are valid numbers
195
- const lng = Number(project.longitude);
196
- const lat = Number(project.latitude);
197
-
198
- console.log(`πŸ“ [SIMPLE GLOBE] Marker ${index} coordinates:`, { lng, lat });
199
-
200
- // Validate coordinates
201
- if (isNaN(lng) || isNaN(lat) || lng < -180 || lng > 180 || lat < -90 || lat > 90) {
202
- console.error(`❌ [SIMPLE GLOBE] Invalid coordinates for project ${index}:`, { lng, lat });
203
- return;
204
- }
205
-
206
- // Add coordinates to bounds
207
- bounds.extend([lng, lat]);
208
- hasValidCoordinates = true;
209
-
210
- // Add marker to map with proper coordinate order [lng, lat]
211
- const marker = new mapboxgl.Marker(el)
212
- .setLngLat([lng, lat])
213
- .setPopup(popup)
214
- .addTo(map.current);
215
-
216
- // Add click handler
217
- el.addEventListener('click', () => {
218
- console.log('πŸ“ [SIMPLE GLOBE] Marker clicked:', project);
219
- onProjectClick(project);
220
- });
221
-
222
- console.log(`βœ… [SIMPLE GLOBE] Marker ${index} added at:`, [lng, lat]);
223
- });
224
-
225
- // Fit map to show all markers if we have valid coordinates
226
- if (hasValidCoordinates && !bounds.isEmpty()) {
227
- console.log('πŸ—ΊοΈ [SIMPLE GLOBE] Fitting map to bounds:', bounds);
228
- map.current.fitBounds(bounds, {
229
- padding: { top: 20, bottom: 20, left: 20, right: 20 },
230
- maxZoom: 6,
231
- duration: 1000
232
- });
233
- }
234
- });
235
-
236
- return () => {
237
- if (map.current) {
238
- map.current.remove();
239
- map.current = null;
240
- }
241
- };
242
- }, [projects, onProjectClick, mapConfig]);
243
-
244
- return (
245
- <Style>
246
- <div
247
- ref={mapContainer}
248
- style={{
249
- width: '100%',
250
- height: '500px',
251
- overflow: 'hidden',
252
- position: 'relative'
253
- }}
254
- />
255
- </Style>
256
- );
257
- };
258
-
259
- export default SimpleGlobe;