sw-fe/src/components/Map/markerManager.js

174 lines
4.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import maplibregl from "maplibre-gl";
/**
* Supprime tous les marqueurs
*/
export function clearAllMarkers(markersRef, expandedElRef) {
if (markersRef.current) {
for (const m of markersRef.current) {
try {
m.marker.remove();
} catch {
// ignore
}
}
}
markersRef.current = [];
if (expandedElRef) {
expandedElRef.current = null;
}
}
/**
* Crée un marqueur pour un post :
* - état compact : petite bulle + pointe
* - état étendu : gros post (carte) comme sur ton dessin
*/
export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) {
const map = mapRef.current;
if (!map) return;
// --- coordonnées ---
const lat =
typeof post.lat === "number"
? post.lat
: typeof post.Lat === "number"
? post.Lat
: typeof post.latitude === "number"
? post.latitude
: null;
const lon =
typeof post.lon === "number"
? post.lon
: typeof post.Lon === "number"
? post.Lon
: typeof post.longitude === "number"
? post.longitude
: null;
if (lat == null || lon == null) {
console.warn("post sans coordonnée:", post);
return;
}
const title = (post.title || post.Title || "").trim() || "Untitled";
const body =
(post.snippet || post.Snippet || "").trim() ||
(post.body || post.Body || "").trim() ||
title;
const author = (post.author || post.Author || "").trim() || "unknown";
const created =
(post.created_at || post.CreatedAt || "").toString().slice(0, 19);
const category = (post.category || post.Category || "").toUpperCase() || "";
const subCat = (post.sub_category || post.SubCategory || "").toString();
const root = document.createElement("div");
root.className = "post-pin post-pin--compact";
function renderCompact() {
root.className = "post-pin post-pin--compact";
root.innerHTML = `
<div class="post-pin-bubble">
<div class="post-pin-dot"></div>
<div class="post-pin-text">${escapeHtml(title)}</div>
</div>
<div class="post-pin-pointer-small"></div>
`;
}
function renderExpanded() {
root.className = "post-pin post-pin--expanded";
root.innerHTML = `
<div class="post-card">
<div class="post-card-header">
<div class="post-card-cat">
${escapeHtml(category || "NEWS")}
${subCat ? "· " + escapeHtml(subCat) : ""}
</div>
<div class="post-card-time">
${escapeHtml(created || "")}
</div>
</div>
<div class="post-card-main">
<div class="post-card-media">
<div class="post-card-media-label">
Image / Vidéo
</div>
</div>
<div class="post-card-info">
<div class="post-card-title">
${escapeHtml(title)}
</div>
<div class="post-card-meta">
by ${escapeHtml(author)} · lat ${lat.toFixed(3)} · lon ${lon.toFixed(3)}
</div>
<div class="post-card-body">
${escapeHtml(body)}
</div>
</div>
</div>
<div class="post-card-footer">
<button class="post-card-btn">Live</button>
<button class="post-card-btn">Like</button>
<button class="post-card-btn">Share</button>
<button class="post-card-btn">Fix</button>
</div>
<div class="post-card-comments">
Live chat / comments (placeholder)
</div>
</div>
<div class="post-card-pointer"></div>
`;
}
// état initial : compact
renderCompact();
const marker = new maplibregl.Marker({
element: root,
anchor: "bottom", // la pointe touche exactement la coordonnée
})
.setLngLat([lon, lat])
.addTo(map);
markersRef.current.push({ id: post.id, marker, el: root, post });
root.addEventListener("click", (ev) => {
ev.stopPropagation();
// Fermer l'ancien gros post
if (expandedElRef.current && expandedElRef.current !== root) {
expandedElRef.current.__renderCompact &&
expandedElRef.current.__renderCompact();
expandedElRef.current = null;
}
// Toggle pour ce post
const isExpanded = root.classList.contains("post-pin--expanded");
if (isExpanded) {
renderCompact();
expandedElRef.current = null;
} else {
renderExpanded();
expandedElRef.current = root;
// on garde les fonctions pour pouvoir re-compactifier
root.__renderCompact = renderCompact;
}
});
}
/* petite fonction pour éviter dinjecter du HTML sale */
function escapeHtml(str) {
return String(str)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}