/**
* MapBox implementation with table view and theme toggle using MapBase
*/
class MapBoxApp extends MapBase {
constructor() {
super();
this.config = { hasMapbox: false, mapboxAccessToken: null };
this.currentView = 'map'; // 'map' or 'table'
this.initializeConfig();
this.initializeMapBoxFeatures();
}
/**
* Initialize API configuration
*/
async initializeConfig() {
try {
const configResponse = await fetch('/api/config');
this.config = await configResponse.json();
console.log('π§ API Configuration:', this.config.hasMapbox ? 'MapBox enabled' : 'Using Nominatim fallback');
} catch (error) {
console.warn('Failed to load API configuration, using fallback');
}
this.initializeMap();
}
/**
* Initialize MapBox-specific features
*/
initializeMapBoxFeatures() {
this.initializeViewToggle();
this.initializeThemeToggle();
}
/**
* Initialize the Leaflet map
*/
initializeMap() {
this.map = L.map('map').setView([42.9634, -85.6681], 10);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
}).addTo(this.map);
}
/**
* Initialize view toggle functionality
*/
initializeViewToggle() {
const mapViewBtn = document.getElementById('map-view-btn');
const tableViewBtn = document.getElementById('table-view-btn');
if (mapViewBtn && tableViewBtn) {
mapViewBtn.addEventListener('click', () => this.switchView('map'));
tableViewBtn.addEventListener('click', () => this.switchView('table'));
}
}
/**
* Initialize theme toggle functionality
*/
initializeThemeToggle() {
const themeToggle = document.getElementById('theme-toggle');
if (themeToggle) {
themeToggle.addEventListener('click', () => this.toggleTheme());
}
// Apply saved theme on load
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.body.dataset.theme = savedTheme;
}
}
/**
* Toggle between light and dark theme
*/
toggleTheme() {
const currentTheme = document.body.dataset.theme || 'light';
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
document.body.dataset.theme = newTheme;
localStorage.setItem('theme', newTheme);
}
/**
* Switch between map and table view
*/
switchView(viewType) {
this.currentView = viewType;
const mapView = document.getElementById('map-view');
const tableView = document.getElementById('table-view');
const mapViewBtn = document.getElementById('map-view-btn');
const tableViewBtn = document.getElementById('table-view-btn');
if (viewType === 'map') {
mapView.style.display = 'block';
tableView.style.display = 'none';
mapViewBtn.classList.add('active');
tableViewBtn.classList.remove('active');
// Invalidate map size after showing
setTimeout(() => this.map.invalidateSize(), 100);
} else {
mapView.style.display = 'none';
tableView.style.display = 'block';
mapViewBtn.classList.remove('active');
tableViewBtn.classList.add('active');
}
}
/**
* Create custom marker for location
*/
createMarker(location) {
const isPersistent = !!location.persistent;
const timeAgo = window.getTimeAgo ? window.getTimeAgo(location.created_at) : '';
const persistentText = isPersistent ? '
π Persistent Report' : '';
const customIcon = this.createCustomIcon(isPersistent);
const marker = L.marker([location.latitude, location.longitude], {
icon: customIcon
})
.addTo(this.map)
.bindPopup(`${location.address}
${location.description || 'No additional details'}
Reported ${timeAgo}${persistentText}`);
return marker;
}
/**
* Create custom icon for markers
*/
createCustomIcon(isPersistent = false) {
const iconColor = isPersistent ? '#28a745' : '#dc3545';
const iconSymbol = isPersistent ? 'π' : 'β οΈ';
return L.divIcon({
className: 'custom-marker',
html: `