diff --git a/templates/partials/projects/project_dashboard.html b/templates/partials/projects/project_dashboard.html index 5b859e2..d8daf49 100644 --- a/templates/partials/projects/project_dashboard.html +++ b/templates/partials/projects/project_dashboard.html @@ -161,7 +161,9 @@ maxZoom: 18, }).addTo(map); - const markers = []; + // Marker store keyed by location id so card-click can find + flash + // the matching pin (bidirectional highlight). + const markersById = {}; const bounds = []; withCoords.forEach(loc => { const marker = L.circleMarker(loc.latlon, { @@ -174,10 +176,53 @@ }).addTo(map); marker.bindTooltip(loc.name, { direction: 'top', offset: [0, -6] }); marker.on('click', () => _flashLocationCard(loc.id)); - markers.push(marker); + markersById[loc.id] = marker; bounds.push(loc.latlon); }); + // Wire up the reverse direction: hovering a card highlights its + // pin on the map. Hover-based instead of click-based because + // clicking the card navigates to the location detail page, so the + // flash would never be visible. Event delegation so cards that + // appear later (htmx swap or reorder) still work. + let _hoverPinId = null; + document.addEventListener('mouseover', (e) => { + const card = e.target.closest('.location-card'); + if (!card) return; + const locId = card.dataset.locationId; + if (locId === _hoverPinId) return; + if (_hoverPinId) _unhighlightPin(_hoverPinId); + _highlightPin(locId); + _hoverPinId = locId; + }); + document.addEventListener('mouseout', (e) => { + const card = e.target.closest('.location-card'); + if (!card) return; + // Only un-highlight if the mouse actually left the card, + // not just moved to a child element. + const related = e.relatedTarget && e.relatedTarget.closest('.location-card'); + if (related === card) return; + if (_hoverPinId) { + _unhighlightPin(_hoverPinId); + _hoverPinId = null; + } + }); + + function _highlightPin(locId) { + const marker = markersById[locId]; + if (!marker) return; + marker.setStyle({ radius: 12, fillColor: '#dc2626', weight: 3 }); + marker.openTooltip(); + marker.bringToFront(); + } + + function _unhighlightPin(locId) { + const marker = markersById[locId]; + if (!marker) return; + marker.setStyle({ radius: 8, fillColor: '#f48b1c', weight: 2 }); + marker.closeTooltip(); + } + if (bounds.length === 1) { map.setView(bounds[0], 14); } else {