update the import statement for sitePoints to match the correct file name (sitepoints instead of sitePoints)

This commit is contained in:
wayanrivan
2026-07-03 11:20:01 +07:00
parent fb11249d3f
commit c9e28043e4

View File

@ -1,9 +1,6 @@
import { useEffect, useRef, useState, useMemo } from 'react'; import { useEffect, useRef, useState, useMemo } from 'react';
import L from 'leaflet'; import L from 'leaflet';
import 'leaflet/dist/leaflet.css'; import 'leaflet/dist/leaflet.css';
import 'leaflet.markercluster';
import 'leaflet.markercluster/dist/MarkerCluster.css';
import 'leaflet.markercluster/dist/MarkerCluster.Default.css';
import { sitePoints, SitePoint } from '../sitepoints'; import { sitePoints, SitePoint } from '../sitepoints';
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -11,9 +8,13 @@ import { sitePoints, SitePoint } from '../sitepoints';
// pin for every Cell/Sector row from the uploaded Excel // pin for every Cell/Sector row from the uploaded Excel
// (Sites_Coordinates_untuk_CC.xlsm -> "site coordinates 4G"). // (Sites_Coordinates_untuk_CC.xlsm -> "site coordinates 4G").
// //
// No clustering — every site is shown as its own blue pin, directly at its
// real coordinates (previously multi-sector sites used a marker cluster
// plugin, which rendered green/yellow/orange group bubbles; that's removed).
//
// SETUP REQUIRED: // SETUP REQUIRED:
// npm install leaflet leaflet.markercluster // npm install leaflet
// npm install --save-dev @types/leaflet @types/leaflet.markercluster // npm install --save-dev @types/leaflet
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const DILI_CENTER: [number, number] = [-8.5586, 125.5736]; const DILI_CENTER: [number, number] = [-8.5586, 125.5736];
@ -30,12 +31,11 @@ const groupByCoordinate = (points: SitePoint[]) => {
return map; return map;
}; };
// Signal-tower badge icon: colored circle background + white "broadcast // Signal-tower badge icon: blue circle background + white "broadcast tower"
// tower" glyph, sized up slightly for pins that represent more than one // glyph. Same size/style for every site pin.
// cell/sector at the same coordinates. const pinIcon = () => {
const pinIcon = (multi: boolean) => { const size = 28;
const size = multi ? 30 : 26; const bg = '#2563eb';
const bg = multi ? '#2563eb' : '#ef4444';
return L.divIcon({ return L.divIcon({
className: '', className: '',
@ -65,8 +65,8 @@ const pinIcon = (multi: boolean) => {
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// "Signal detail" popup (blue pins only) — mimics the tabbed // "Signal detail" popup — tabbed Signal / RAN 2G / RAN 3G / Alarm dialog,
// Signal / RAN 2G / RAN 3G / Alarm dialog from the reference screenshot. // shown for every pin.
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const QUALITY_LEVELS = ['Low', 'Moderate', 'Good', 'Very Good', 'Excellent']; const QUALITY_LEVELS = ['Low', 'Moderate', 'Good', 'Very Good', 'Excellent'];
@ -206,7 +206,6 @@ const wireSignalPopup = (container: HTMLElement, site: string) => {
const SitesSatelliteMap = () => { const SitesSatelliteMap = () => {
const mapContainerRef = useRef<HTMLDivElement | null>(null); const mapContainerRef = useRef<HTMLDivElement | null>(null);
const mapRef = useRef<L.Map | null>(null); const mapRef = useRef<L.Map | null>(null);
const clusterRef = useRef<L.MarkerClusterGroup | null>(null);
const markerByKeyRef = useRef<Map<string, L.Marker>>(new Map()); const markerByKeyRef = useRef<Map<string, L.Marker>>(new Map());
const [search, setSearch] = useState(''); const [search, setSearch] = useState('');
const [selectedCount, setSelectedCount] = useState(sitePoints.length); const [selectedCount, setSelectedCount] = useState(sitePoints.length);
@ -239,39 +238,15 @@ const SitesSatelliteMap = () => {
{ maxZoom: 19, opacity: 0.9 } { maxZoom: 19, opacity: 0.9 }
).addTo(map); ).addTo(map);
const cluster = L.markerClusterGroup({ maxClusterRadius: 50 }); // Every site gets its own blue pin placed directly on the map — no
clusterRef.current = cluster; // clustering, no group bubbles.
grouped.forEach((points, key) => { grouped.forEach((points, key) => {
const [lat, lng] = key.split(',').map(Number); const [lat, lng] = key.split(',').map(Number);
const isMulti = points.length > 1; const marker = L.marker([lat, lng], { icon: pinIcon() }).addTo(map);
const marker = L.marker([lat, lng], { icon: pinIcon(isMulti) }); marker.bindPopup(buildSignalPopupHtml(points, lat, lng), { maxWidth: 320, minWidth: 290 });
if (isMulti) {
// Blue pin -> rich "Signal" dialog.
marker.bindPopup(buildSignalPopupHtml(points, lat, lng), { maxWidth: 320, minWidth: 290 });
} else {
// Red pin -> simple cell/sector info (unchanged).
const site = points[0].site;
const location = points[0].location;
const rows = points
.map((p) => `<tr><td style="padding-right:8px;">${p.cell}</td><td>${p.sector}</td></tr>`)
.join('');
marker.bindPopup(`
<div style="font-family: Arial, sans-serif; font-size: 13px; max-width: 240px;">
<div style="font-weight:600; margin-bottom:2px;">${site}</div>
<div style="color:#666; margin-bottom:6px;">${location} &middot; ${lat.toFixed(5)}, ${lng.toFixed(5)}</div>
<table style="width:100%; border-collapse:collapse;">${rows}</table>
</div>
`);
}
markerByKeyRef.current.set(key, marker); markerByKeyRef.current.set(key, marker);
cluster.addLayer(marker);
}); });
map.addLayer(cluster);
// Wire up the rich popup's interactive bits (tabs + buttons) every time // Wire up the rich popup's interactive bits (tabs + buttons) every time
// one is opened, since Leaflet re-renders the DOM content on each open. // one is opened, since Leaflet re-renders the DOM content on each open.
const onPopupOpen = (e: L.PopupEvent) => { const onPopupOpen = (e: L.PopupEvent) => {
@ -287,7 +262,6 @@ const SitesSatelliteMap = () => {
map.off('popupopen', onPopupOpen); map.off('popupopen', onPopupOpen);
map.remove(); map.remove();
mapRef.current = null; mapRef.current = null;
clusterRef.current = null;
markerByKeyRef.current.clear(); markerByKeyRef.current.clear();
}; };
}, [grouped]); }, [grouped]);
@ -314,9 +288,7 @@ const SitesSatelliteMap = () => {
const key = `${first.lat.toFixed(6)},${first.lng.toFixed(6)}`; const key = `${first.lat.toFixed(6)},${first.lng.toFixed(6)}`;
mapRef.current.setView([first.lat, first.lng], 17); mapRef.current.setView([first.lat, first.lng], 17);
const marker = markerByKeyRef.current.get(key); const marker = markerByKeyRef.current.get(key);
if (marker && clusterRef.current) { if (marker) marker.openPopup();
clusterRef.current.zoomToShowLayer(marker, () => marker.openPopup());
}
} }
}; };