import { map } from './map-manager.js';
import { showStatus } from './utils.js';
import { openAddModal } from './location-manager.js';
let edmontonParcelsLayer = null;
let isLoading = false;
let isLayerVisible = false;
let lastBounds = null;
let lastZoom = null;
/**
* Toggles the visibility of the Edmonton Parcel Addresses layer.
* Uses smart loading based on map bounds and zoom level.
*/
export async function toggleEdmontonParcelsLayer() {
const toggleBtn = document.getElementById('toggle-edmonton-layer-btn');
const mobileToggleBtn = document.getElementById('mobile-toggle-edmonton-layer-btn');
if (isLoading) {
console.log('Edmonton layer is already loading...');
return;
}
if (isLayerVisible) {
// Hide the layer
if (edmontonParcelsLayer && map.hasLayer(edmontonParcelsLayer)) {
map.removeLayer(edmontonParcelsLayer);
}
isLayerVisible = false;
toggleBtn?.classList.remove('active');
mobileToggleBtn?.classList.remove('active');
console.log('Edmonton addresses layer hidden');
// Remove map event listeners
map.off('moveend', onMapMoveEnd);
map.off('zoomend', onMapZoomEnd);
} else {
// Show the layer
isLayerVisible = true;
toggleBtn?.classList.add('active');
mobileToggleBtn?.classList.add('active');
console.log('Edmonton addresses layer enabled');
// Add map event listeners for dynamic loading
map.on('moveend', onMapMoveEnd);
map.on('zoomend', onMapZoomEnd);
// Load data for current view
await loadEdmontonData();
}
}
/**
* Loads Edmonton data for the current map bounds and zoom level
*/
async function loadEdmontonData(force = false) {
if (!isLayerVisible || isLoading) return;
const currentBounds = map.getBounds();
const currentZoom = map.getZoom();
// Check if we need to reload data
if (!force && lastBounds && lastZoom === currentZoom &&
lastBounds.contains(currentBounds)) {
return; // Current view is already covered
}
// Only load data if zoomed in enough (reduces server load)
if (currentZoom < 11) {
if (edmontonParcelsLayer && map.hasLayer(edmontonParcelsLayer)) {
map.removeLayer(edmontonParcelsLayer);
}
console.log('Zoom level too low for Edmonton data, zoom in to see addresses');
return;
}
isLoading = true;
const toggleBtn = document.getElementById('toggle-edmonton-layer-btn');
const mobileToggleBtn = document.getElementById('mobile-toggle-edmonton-layer-btn');
if (toggleBtn) toggleBtn.disabled = true;
if (mobileToggleBtn) mobileToggleBtn.disabled = true;
try {
// Expand bounds slightly to avoid edge loading issues
const expandedBounds = currentBounds.pad(0.1);
const boundsString = [
expandedBounds.getSouth(),
expandedBounds.getWest(),
expandedBounds.getNorth(),
expandedBounds.getEast()
].join(',');
const params = new URLSearchParams({
bounds: boundsString,
zoom: currentZoom.toString(),
limit: currentZoom > 15 ? '2000' : currentZoom > 12 ? '1000' : '500'
});
console.log(`Loading Edmonton addresses for zoom level ${currentZoom}, bounds: ${boundsString}`);
const response = await fetch(`/api/external/edmonton-parcels?${params}`);
if (!response.ok) {
throw new Error('Failed to fetch layer data from server.');
}
const result = await response.json();
if (result.success) {
// Remove existing layer
if (edmontonParcelsLayer && map.hasLayer(edmontonParcelsLayer)) {
map.removeLayer(edmontonParcelsLayer);
}
// Create new layer with clustering optimized for the zoom level
const clusterRadius = currentZoom > 15 ? 30 : currentZoom > 12 ? 50 : 80;
edmontonParcelsLayer = L.markerClusterGroup({
chunkedLoading: true,
maxClusterRadius: clusterRadius,
disableClusteringAtZoom: 18,
showCoverageOnHover: false,
zoomToBoundsOnClick: true,
spiderfyOnMaxZoom: true,
removeOutsideVisibleBounds: true
});
const geoJsonLayer = L.geoJSON(result.data, {
pointToLayer: (feature, latlng) => {
const isMultiUnit = feature.properties.isMultiUnit;
return L.circleMarker(latlng, {
radius: Math.max(3, Math.min(6, currentZoom - 10)),
fillColor: isMultiUnit ? "#ff6b35" : "#ba001e", // Orange for multi-unit buildings
color: "#ffffff",
weight: isMultiUnit ? 2 : 1,
opacity: 0.9,
fillOpacity: 0.7
});
},
onEachFeature: (feature, layer) => {
const props = feature.properties;
if (props.isMultiUnit) {
// Create apartment-style popup for multi-unit buildings
const popup = L.popup({
maxWidth: 320,
minWidth: 280,
closeButton: true,
className: 'apartment-popup'
}).setContent(createApartmentPopup(props));
layer.bindPopup(popup);
// Add event listener for when popup opens
layer.on('popupopen', function(e) {
setupApartmentPopupListeners(props);
});
} else {
// Simple popup for single units
const suite = props.suites && props.suites[0] ? props.suites[0] : {};
// Better suite/unit display logic
let suiteDisplay = '';
if (suite.suite && suite.suite.trim()) {
const unitLabel = (suite.object_type && suite.object_type.toLowerCase().includes('suite')) ? 'Suite' : 'Unit';
suiteDisplay = `${unitLabel}: ${suite.suite.trim()}
`;
}
const popupContent = `