diff --git a/src/components/Map/MapView.jsx b/src/components/Map/MapView.jsx
index 5aaf42b..4f3f2c9 100644
--- a/src/components/Map/MapView.jsx
+++ b/src/components/Map/MapView.jsx
@@ -100,7 +100,7 @@ const CATEGORY_MAP = {
export default function MapView() {
const containerRef = useRef(null);
const mapRef = useRef(null);
- const markersRef = useRef([]);
+ const markersRef = useRef([]); // [{ id, marker, el, compactHTML, expandedHTML }]
const expandedElRef = useRef(null);
const [status, setStatus] = useState("Loading posts...");
@@ -110,7 +110,6 @@ export default function MapView() {
const [subFilter, setSubFilter] = useState(null); // sous-catégorie du bas
const [userPosition, setUserPosition] = useState(null); // [lng, lat]
- const [reloadToken, setReloadToken] = useState(0);
const [viewParams, setViewParams] = useState({
center: null,
@@ -307,6 +306,102 @@ export default function MapView() {
}
}, [mainFilter, bottomCategories, subFilter]);
+ /* ------------ FACTEUR EN COMMUN: CREATION D'UN MARKER POUR UN POST -------------- */
+ const createMarkerForPost = (post) => {
+ const map = mapRef.current;
+ if (!map) return;
+
+ const coords = getCoords(post);
+ if (!coords) return;
+
+ // évite les doublons (même id déjà affiché)
+ if (
+ typeof post.id === "number" &&
+ markersRef.current.some((m) => m.id === post.id)
+ ) {
+ return;
+ }
+
+ const [lngP, latP] = coords;
+ if (
+ typeof lngP !== "number" ||
+ typeof latP !== "number" ||
+ Number.isNaN(lngP) ||
+ Number.isNaN(latP)
+ ) {
+ return;
+ }
+
+ const { title, body, short } = extract(post);
+
+ const compactHTML = `
+
+ `;
+
+ const expandedHTML = `
+
+ `;
+
+ const el = document.createElement("div");
+ el.className = "post-marker post-marker-compact";
+ el.innerHTML = compactHTML;
+
+ const marker = new maplibregl.Marker({
+ element: el,
+ anchor: "bottom",
+ })
+ .setLngLat(coords)
+ .addTo(map);
+
+ const meta = {
+ id: post.id ?? null,
+ marker,
+ el,
+ compactHTML,
+ expandedHTML,
+ };
+ markersRef.current.push(meta);
+
+ const toggle = () => {
+ if (expandedElRef.current && expandedElRef.current !== el) {
+ const prev = markersRef.current.find(
+ (m) => m.el === expandedElRef.current
+ );
+ if (prev) {
+ prev.el.className = "post-marker post-marker-compact";
+ prev.el.innerHTML = prev.compactHTML;
+ }
+ }
+
+ if (expandedElRef.current === el) {
+ el.className = "post-marker post-marker-compact";
+ el.innerHTML = compactHTML;
+ expandedElRef.current = null;
+ } else {
+ el.className = "post-marker post-marker-expanded";
+ el.innerHTML = expandedHTML;
+ expandedElRef.current = el;
+ }
+ };
+
+ el.addEventListener("click", toggle);
+ el.addEventListener("touchend", (e) => {
+ e.preventDefault();
+ toggle();
+ });
+ };
+
/* ------------ LOAD POSTS POUR LA ZONE COURANTE + FILTRES -------------- */
useEffect(() => {
const map = mapRef.current;
@@ -337,86 +432,13 @@ export default function MapView() {
if (cancelled) return;
+ // ici on recharge la vue => on enlève tout puis on remet
markersRef.current.forEach((m) => m.marker.remove());
markersRef.current = [];
expandedElRef.current = null;
posts.forEach((post) => {
- const coords = getCoords(post);
- if (!coords) return;
-
- const [lngP, latP] = coords;
- if (
- typeof lngP !== "number" ||
- typeof latP !== "number" ||
- Number.isNaN(lngP) ||
- Number.isNaN(latP)
- ) {
- return;
- }
-
- const { title, body, short } = extract(post);
-
- const compactHTML = `
-
- `;
-
- const expandedHTML = `
-
- `;
-
- const el = document.createElement("div");
- el.className = "post-marker post-marker-compact";
- el.innerHTML = compactHTML;
-
- const marker = new maplibregl.Marker({
- element: el,
- anchor: "bottom",
- })
- .setLngLat(coords)
- .addTo(map);
-
- const meta = { marker, el, compactHTML, expandedHTML };
- markersRef.current.push(meta);
-
- const toggle = () => {
- if (expandedElRef.current && expandedElRef.current !== el) {
- const prev = markersRef.current.find(
- (m) => m.el === expandedElRef.current
- );
- if (prev) {
- prev.el.className = "post-marker post-marker-compact";
- prev.el.innerHTML = prev.compactHTML;
- }
- }
-
- if (expandedElRef.current === el) {
- el.className = "post-marker post-marker-compact";
- el.innerHTML = compactHTML;
- expandedElRef.current = null;
- } else {
- el.className = "post-marker post-marker-expanded";
- el.innerHTML = expandedHTML;
- expandedElRef.current = el;
- }
- };
-
- el.addEventListener("click", toggle);
- el.addEventListener("touchend", (e) => {
- e.preventDefault();
- toggle();
- });
+ createMarkerForPost(post);
});
setStatus(posts.length ? "" : "No posts found.");
@@ -431,9 +453,9 @@ export default function MapView() {
return () => {
cancelled = true;
};
- }, [viewParams, mainFilter, timeFilter, subFilter, reloadToken]);
+ }, [viewParams, mainFilter, timeFilter, subFilter]);
- /* ------------ WEBSOCKET : RELOAD SUR new_post -------------- */
+ /* ------------ WEBSOCKET : AJOUTER JUSTE LE NOUVEAU POST -------------- */
useEffect(() => {
const proto = window.location.protocol === "https:" ? "wss" : "ws";
const host =
@@ -454,10 +476,35 @@ export default function MapView() {
ws.onmessage = (ev) => {
try {
const msg = JSON.parse(ev.data);
- if (msg.type === "new_post") {
- setReloadToken((n) => n + 1);
+ if (msg.type === "new_post" && msg.post) {
+ const p = msg.post;
+
+ // Optionnel: respecter les filtres actuels
+ const catCode = categoryCode(mainFilter);
+ if (catCode && p.category && p.category.toUpperCase() !== catCode) {
+ return;
+ }
+
+ // Position: ne l'afficher que s'il est dans le rayon courant
+ if (viewParams.center && viewParams.radiusKm) {
+ const coords = getCoords(p);
+ if (coords) {
+ const [lngP, latP] = coords;
+ const [lngC, latC] = viewParams.center;
+ const dKm = haversineKm(latC, lngC, latP, lngP);
+ if (dKm > viewParams.radiusKm * 1.2) {
+ // trop loin de la vue actuelle → on ignore
+ return;
+ }
+ }
+ }
+
+ // On ajoute juste ce post, sans effacer les autres
+ createMarkerForPost(p);
}
- } catch (_) {}
+ } catch (_) {
+ // ignore
+ }
};
ws.onerror = (e) => {
@@ -469,7 +516,7 @@ export default function MapView() {
ws.close();
}
};
- }, []);
+ }, [mainFilter, viewParams]);
/* ------------ ACTIONS UI -------------- */
@@ -479,7 +526,7 @@ export default function MapView() {
map.flyTo({
center: userPosition,
zoom: 9,
- speed: 1.1,
+ speed: 1.2,
curve: 1.5,
essential: true,
});
@@ -550,7 +597,7 @@ export default function MapView() {
await createPost(payload);
setIsSaving(false);
setIsCreating(false);
- setReloadToken((n) => n + 1);
+ // On ne refetch pas tout ici, on laisse le WS rajouter le nouveau
} catch (e) {
console.error("createPost error:", e);
setIsSaving(false);