DebasishDhal99 commited on
Commit
7e40962
·
1 Parent(s): 5758323

Add sidebar on upper left to select units and collapse the geodistance feature

Browse files
frontend/src/components/Map.js CHANGED
@@ -55,6 +55,9 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
55
  const [geoPoints, setGeoPoints] = useState([]);
56
  const [geoDistance, setGeoDistance] = useState(null);
57
 
 
 
 
58
  const handleMouseDown = (e) => {
59
  isDragging.current = true;
60
  startX.current = e.clientX;
@@ -188,17 +191,18 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
188
  lon1: updatedPoints[0].lon,
189
  lat2: updatedPoints[1].lat,
190
  lon2: updatedPoints[1].lon,
191
- unit: 'km',
192
  }),
193
  });
194
  const data = await res.json();
195
  setGeoDistance(data.distance);
 
196
  } catch (err) {
197
  console.error('Failed to fetch distance:', err);
198
  setGeoDistance(null);
199
  }
200
  }
201
- }, [geoPoints]);
202
 
203
  return (
204
  <div ref={containerRef} style={{ display: 'flex', height: '100vh', width: '100%', overflow: 'hidden' }}>
@@ -279,32 +283,34 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
279
  url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
280
  />
281
  <ClickHandler onClick={handleGeoClick} />
282
- {markerPosition && ( // Getting rid of default marker upon start.
283
- <Marker position={markerPosition}>
284
- {contentType === 'summary' && (
285
- <Popup minWidth={250}>
286
- {wikiContent ? (
287
- <>
288
- <strong>{wikiContent.title}</strong><br />
289
- <p style={{ fontSize: '12px' }}>{wikiContent.content}</p>
290
- </>
291
- ) : (
292
- "Search for a location to see information"
293
- )}
294
- </Popup>
295
  )}
296
- </Marker>
297
- )}
298
- {geoPoints.map((pt, index) => (
 
 
 
 
299
  <Marker key={`geo-${index}`} position={[pt.lat, pt.lon]}>
300
  <Popup>
301
  Point {index + 1}: {pt.lat.toFixed(4)}, {pt.lon.toFixed(4)}
302
  </Popup>
303
- </Marker>
304
  ))}
305
 
306
- {/* Polyline if 2 points are selected */}
307
- {geoPoints.length === 2 && (
308
  <Polyline
309
  key={geoPoints.map(pt => `${pt.lat},${pt.lon}`).join('-')}
310
  positions={generateGeodesicPoints(
@@ -330,7 +336,7 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
330
  boxShadow: 'none',
331
  padding: 0
332
  }}>
333
- {geoDistance.toFixed(2)} km
334
  </span>
335
  </Tooltip>
336
  )}
@@ -338,6 +344,101 @@ const Map = ( { onMapClick, searchQuery, contentType } ) => {
338
  )}
339
 
340
  </MapContainer>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  {panelSize === 'closed' && (
342
  <button
343
  onClick={togglePanel}
 
55
  const [geoPoints, setGeoPoints] = useState([]);
56
  const [geoDistance, setGeoDistance] = useState(null);
57
 
58
+ const [geoSidebarOpen, setGeoSidebarOpen] = useState(false);
59
+ const [geoUnit, setGeoUnit] = useState('km');
60
+
61
  const handleMouseDown = (e) => {
62
  isDragging.current = true;
63
  startX.current = e.clientX;
 
191
  lon1: updatedPoints[0].lon,
192
  lat2: updatedPoints[1].lat,
193
  lon2: updatedPoints[1].lon,
194
+ unit: geoUnit,
195
  }),
196
  });
197
  const data = await res.json();
198
  setGeoDistance(data.distance);
199
+ setGeoSidebarOpen(true);
200
  } catch (err) {
201
  console.error('Failed to fetch distance:', err);
202
  setGeoDistance(null);
203
  }
204
  }
205
+ }, [geoPoints, geoUnit]);
206
 
207
  return (
208
  <div ref={containerRef} style={{ display: 'flex', height: '100vh', width: '100%', overflow: 'hidden' }}>
 
283
  url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
284
  />
285
  <ClickHandler onClick={handleGeoClick} />
286
+ {markerPosition && (
287
+ <Marker position={markerPosition}>
288
+ {contentType === 'summary' && (
289
+ <Popup minWidth={250}>
290
+ {wikiContent ? (
291
+ <>
292
+ <strong>{wikiContent.title}</strong><br />
293
+ <p style={{ fontSize: '12px' }}>{wikiContent.content}</p>
294
+ </>
295
+ ) : (
296
+ "Search for a location to see information"
 
 
297
  )}
298
+ </Popup>
299
+ )}
300
+ </Marker>
301
+ )}
302
+
303
+ {/* Only show geodistance markers/polyline if sidebar is open */}
304
+ {geoSidebarOpen && geoPoints.map((pt, index) => (
305
  <Marker key={`geo-${index}`} position={[pt.lat, pt.lon]}>
306
  <Popup>
307
  Point {index + 1}: {pt.lat.toFixed(4)}, {pt.lon.toFixed(4)}
308
  </Popup>
309
+ </Marker>
310
  ))}
311
 
312
+ {/* Polyline if 2 points are selected and sidebar is open */}
313
+ {geoSidebarOpen && geoPoints.length === 2 && (
314
  <Polyline
315
  key={geoPoints.map(pt => `${pt.lat},${pt.lon}`).join('-')}
316
  positions={generateGeodesicPoints(
 
336
  boxShadow: 'none',
337
  padding: 0
338
  }}>
339
+ {geoDistance.toFixed(2)} {geoUnit}
340
  </span>
341
  </Tooltip>
342
  )}
 
344
  )}
345
 
346
  </MapContainer>
347
+
348
+ {/* Geo Tools Button */}
349
+ {!geoSidebarOpen && (
350
+ <button
351
+ onClick={() => setGeoSidebarOpen(true)}
352
+ style={{
353
+ position: 'absolute',
354
+ top: 12,
355
+ right: 12,
356
+ zIndex: 1000,
357
+ padding: '6px 12px',
358
+ backgroundColor: '#1976d2',
359
+ color: 'white',
360
+ border: 'none',
361
+ borderRadius: 4,
362
+ cursor: 'pointer'
363
+ }}
364
+ >
365
+ Geo Tools
366
+ </button>
367
+ )}
368
+
369
+ {/* Geo Sidebar */}
370
+ {geoSidebarOpen && (
371
+ <div style={{
372
+ position: 'fixed',
373
+ top: 24,
374
+ right: 24,
375
+ width: 280,
376
+ background: 'white',
377
+ borderRadius: 10,
378
+ boxShadow: '0 2px 12px rgba(0,0,0,0.12)',
379
+ zIndex: 2000,
380
+ padding: 20,
381
+ display: 'flex',
382
+ flexDirection: 'column',
383
+ gap: 16,
384
+ border: '1px solid #eee'
385
+ }}>
386
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
387
+ <strong>Geodistance</strong>
388
+ <button
389
+ onClick={() => {
390
+ setGeoSidebarOpen(false);
391
+ setGeoPoints([]);
392
+ setGeoDistance(null);
393
+ }}
394
+ style={{
395
+ background: 'none',
396
+ border: 'none',
397
+ fontSize: 18,
398
+ cursor: 'pointer',
399
+ color: '#888'
400
+ }}
401
+ title="Close"
402
+ >×</button>
403
+ </div>
404
+ <div>
405
+ <label style={{ fontWeight: 500, marginRight: 8 }}>Unit:</label>
406
+ <select
407
+ value={geoUnit}
408
+ onChange={e => setGeoUnit(e.target.value)}
409
+ style={{ padding: '4px 8px', borderRadius: 4, border: '1px solid #ccc' }}
410
+ >
411
+ <option value="km">Kilometers</option>
412
+ <option value="mi">Miles</option>
413
+ </select>
414
+ </div>
415
+ {geoDistance !== null && (
416
+ <div style={{ fontSize: 20, fontWeight: 600, color: '#1976d2' }}>
417
+ {geoDistance.toFixed(2)} {geoUnit}
418
+ </div>
419
+ )}
420
+ <button
421
+ onClick={() => {
422
+ setGeoSidebarOpen(false);
423
+ setGeoPoints([]);
424
+ setGeoDistance(null);
425
+ }}
426
+ style={{
427
+ marginTop: 8,
428
+ padding: '6px 0',
429
+ borderRadius: 4,
430
+ border: '1px solid #1976d2',
431
+ background: '#1976d2',
432
+ color: 'white',
433
+ fontWeight: 500,
434
+ cursor: 'pointer'
435
+ }}
436
+ >
437
+ Clear & Collapse
438
+ </button>
439
+ </div>
440
+ )}
441
+
442
  {panelSize === 'closed' && (
443
  <button
444
  onClick={togglePanel}
frontend/src/utils/mapUtils.js CHANGED
@@ -1,5 +1,5 @@
1
  // Haversine-based geodesic interpolator
2
- function generateGeodesicPoints(lat1, lon1, lat2, lon2, numPoints = 128) {
3
  /**
4
  * Generates a series of points along the geodesic path between two geographic coordinates, using Haversine function.
5
  * @returns {Array} An array of points, each represented as [latitude, longitude].
 
1
  // Haversine-based geodesic interpolator
2
+ function generateGeodesicPoints(lat1, lon1, lat2, lon2, numPoints = 512) {
3
  /**
4
  * Generates a series of points along the geodesic path between two geographic coordinates, using Haversine function.
5
  * @returns {Array} An array of points, each represented as [latitude, longitude].