2025-04-21 19:41:26 -03:00
|
|
|
|
window.phMap = {
|
2026-06-09 00:59:58 -03:00
|
|
|
|
_maps: {},
|
|
|
|
|
|
_searchAbortController: null,
|
|
|
|
|
|
|
2025-04-21 19:41:26 -03:00
|
|
|
|
initMap: function (mapId, lat, lng, zoom) {
|
2026-06-09 00:59:58 -03:00
|
|
|
|
// Evitar reinicializar si ya existe
|
|
|
|
|
|
if (this._maps[mapId]) {
|
|
|
|
|
|
console.warn(`Map ${mapId} already initialized`);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const map = L.map(mapId, {
|
|
|
|
|
|
zoomControl: true,
|
|
|
|
|
|
attributionControl: true
|
|
|
|
|
|
}).setView([lat, lng], zoom);
|
2025-04-21 19:41:26 -03:00
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
|
|
|
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
|
|
|
|
|
maxZoom: 19,
|
|
|
|
|
|
crossOrigin: true
|
|
|
|
|
|
}).addTo(map);
|
2025-04-21 19:41:26 -03:00
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
const marker = L.marker([lat, lng], {
|
|
|
|
|
|
draggable: false,
|
|
|
|
|
|
keyboard: false
|
|
|
|
|
|
}).addTo(map)
|
|
|
|
|
|
.bindPopup(`<strong>Lat:</strong> ${lat.toFixed(5)}<br><strong>Lng:</strong> ${lng.toFixed(5)}`)
|
|
|
|
|
|
.openPopup();
|
2025-04-21 19:41:26 -03:00
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
this._maps[mapId] = {
|
|
|
|
|
|
map,
|
|
|
|
|
|
marker,
|
|
|
|
|
|
clickHandler: this._createClickHandler.bind(this, mapId)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Agregar event listener para clicks en el mapa
|
|
|
|
|
|
map.on('click', this._maps[mapId].clickHandler);
|
|
|
|
|
|
|
|
|
|
|
|
// Resizable map
|
|
|
|
|
|
map.invalidateSize();
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`Error initializing map ${mapId}:`, error);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-04-21 19:41:26 -03:00
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
_createClickHandler: function (mapId, e) {
|
|
|
|
|
|
const newLat = e.latlng.lat;
|
|
|
|
|
|
const newLng = e.latlng.lng;
|
|
|
|
|
|
const mapData = this._maps[mapId];
|
2025-04-21 19:41:26 -03:00
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
if (!mapData) return;
|
2025-04-21 19:41:26 -03:00
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
mapData.marker.setLatLng([newLat, newLng]);
|
|
|
|
|
|
mapData.marker.setPopupContent(`<strong>Lat:</strong> ${newLat.toFixed(5)}<br><strong>Lng:</strong> ${newLng.toFixed(5)}`);
|
|
|
|
|
|
mapData.marker.getPopup().setLatLng([newLat, newLng]);
|
2025-04-21 19:41:26 -03:00
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
if (typeof DotNet !== 'undefined' && DotNet.invokeMethodAsync) {
|
|
|
|
|
|
DotNet.invokeMethodAsync('phronCare.UIBlazor', 'NotifyLocationChanged', newLat, newLng)
|
|
|
|
|
|
.catch(error => console.error('Error invoking Blazor method NotifyLocationChanged:', error));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.warn('DotNet interop not available');
|
|
|
|
|
|
}
|
2025-04-21 19:41:26 -03:00
|
|
|
|
},
|
|
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
updateLocation: function (mapId, lat, lng) {
|
|
|
|
|
|
const mapData = this._maps[mapId];
|
|
|
|
|
|
if (!mapData) {
|
|
|
|
|
|
console.warn(`Map ${mapId} not found`);
|
2025-04-21 19:41:26 -03:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
mapData.map.setView([lat, lng], mapData.map.getZoom());
|
|
|
|
|
|
mapData.marker.setLatLng([lat, lng]);
|
|
|
|
|
|
mapData.marker.setPopupContent(`<strong>Lat:</strong> ${lat.toFixed(5)}<br><strong>Lng:</strong> ${lng.toFixed(5)}`);
|
|
|
|
|
|
},
|
2025-04-21 19:41:26 -03:00
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
searchAddress: async function (mapId, address) {
|
|
|
|
|
|
const mapData = this._maps[mapId];
|
|
|
|
|
|
if (!mapData) {
|
|
|
|
|
|
console.warn(`Map ${mapId} not found`);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-04-21 19:41:26 -03:00
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
// Cancelar búsquedas anteriores
|
|
|
|
|
|
if (this._searchAbortController) {
|
|
|
|
|
|
this._searchAbortController.abort();
|
|
|
|
|
|
}
|
|
|
|
|
|
this._searchAbortController = new AbortController();
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await fetch(
|
|
|
|
|
|
`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(address)}`,
|
|
|
|
|
|
{
|
|
|
|
|
|
signal: this._searchAbortController.signal,
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Accept': 'application/json'
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
|
throw new Error(`API error: ${response.status}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const data = await response.json();
|
|
|
|
|
|
|
|
|
|
|
|
if (!data || data.length === 0) {
|
|
|
|
|
|
console.warn(`Address not found: ${address}`);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const lat = parseFloat(data[0].lat);
|
|
|
|
|
|
const lon = parseFloat(data[0].lon);
|
|
|
|
|
|
|
|
|
|
|
|
if (isNaN(lat) || isNaN(lon)) {
|
|
|
|
|
|
console.error('Invalid coordinates from API');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mapData.map.setView([lat, lon], 15);
|
|
|
|
|
|
mapData.marker.setLatLng([lat, lon]);
|
|
|
|
|
|
mapData.marker.setPopupContent(`<strong>${address}</strong><br><strong>Lat:</strong> ${lat.toFixed(5)}<br><strong>Lng:</strong> ${lon.toFixed(5)}`);
|
2025-04-21 19:41:26 -03:00
|
|
|
|
|
2026-06-09 00:59:58 -03:00
|
|
|
|
if (typeof DotNet !== 'undefined' && DotNet.invokeMethodAsync) {
|
|
|
|
|
|
DotNet.invokeMethodAsync('phronCare.UIBlazor', 'NotifyLocationChanged', lat, lon)
|
|
|
|
|
|
.catch(error => console.error('Error invoking Blazor method NotifyLocationChanged:', error));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.warn('DotNet interop not available');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
if (error.name === 'AbortError') {
|
|
|
|
|
|
console.log('Search cancelled');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.error('Search error:', error);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
destroyMap: function (mapId) {
|
|
|
|
|
|
const mapData = this._maps[mapId];
|
|
|
|
|
|
if (!mapData) return;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
mapData.map.off('click', mapData.clickHandler);
|
|
|
|
|
|
mapData.map.remove();
|
|
|
|
|
|
delete this._maps[mapId];
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`Error destroying map ${mapId}:`, error);
|
|
|
|
|
|
}
|
2025-04-21 19:41:26 -03:00
|
|
|
|
}
|
|
|
|
|
|
};
|