diff --git a/src/components/Map/MapView.jsx b/src/components/Map/MapView.jsx
index e2eec77..63229cf 100644
--- a/src/components/Map/MapView.jsx
+++ b/src/components/Map/MapView.jsx
@@ -20,6 +20,7 @@ import {
matchesTimeFilter,
} from "./mapFilter";
import { createMarkerForPost, clearAllMarkers } from "./markerManager";
+import PostList from "../Posts/PostList";
export default function MapView() {
const containerRef = useRef(null);
@@ -64,6 +65,12 @@ export default function MapView() {
const [isSaving, setIsSaving] = useState(false);
const [saveError, setSaveError] = useState("");
+ // SOCIOWALL
+ const [visiblePosts, setVisiblePosts] = useState([]);
+ const [selectedPost, setSelectedPost] = useState(null);
+ const [loadingPosts, setLoadingPosts] = useState(false);
+ const [loadError, setLoadError] = useState("");
+
/* ================= INIT MAP ================= */
useEffect(() => {
@@ -258,6 +265,7 @@ export default function MapView() {
createMarkerForPost(post, mapRef, markersRef, expandedElRef);
});
+ setVisiblePosts(visible);
setStatus(visible.length ? "" : "No posts found.");
};
@@ -289,6 +297,8 @@ export default function MapView() {
try {
setStatus("Loading posts...");
+ setLoadingPosts(true);
+ setLoadError("");
const catCode = categoryCode(mainFilter);
const subCatParam =
@@ -333,9 +343,14 @@ export default function MapView() {
};
rebuildMarkersForTimeFilter(timeFilter);
+ setLoadingPosts(false);
} catch (err) {
console.error("Erreur chargement posts:", err);
- if (!cancelled) setStatus("Error loading posts.");
+ if (!cancelled) {
+ setStatus("Error loading posts.");
+ setLoadError("Error loading posts.");
+ setLoadingPosts(false);
+ }
}
}
@@ -402,6 +417,7 @@ export default function MapView() {
allPostsRef.current = [...allPostsRef.current, p];
createMarkerForPost(p, mapRef, markersRef, expandedElRef);
+ setVisiblePosts((current) => [...current, p]);
}
} catch {
// ignore
@@ -505,6 +521,41 @@ export default function MapView() {
}
};
+ const handleSelectPost = (post) => {
+ setSelectedPost(post);
+ const map = mapRef.current;
+ if (!map) return;
+
+ const lng =
+ post.lon ??
+ post.lng ??
+ (Array.isArray(post.coords) ? post.coords[0] : null);
+ const lat =
+ post.lat ??
+ post.latitude ??
+ (Array.isArray(post.coords) ? post.coords[1] : null);
+
+ if (typeof lng === "number" && typeof lat === "number") {
+ map.flyTo({
+ center: [lng, lat],
+ zoom: Math.max(map.getZoom(), 8),
+ speed: 1.4,
+ curve: 1.6,
+ essential: true,
+ });
+ }
+
+ // ouvre le gros post si on a le marker
+ const markerEntry = markersRef.current.find((m) => m.id === post.id);
+ if (markerEntry && markerEntry.el) {
+ const root = markerEntry.el;
+ const isExpanded = root.classList.contains("post-pin--expanded");
+ if (!isExpanded) {
+ root.click();
+ }
+ }
+ };
+
/* ================= RENDER ================= */
return (
@@ -529,7 +580,7 @@ export default function MapView() {
{/* LEFT — time filters */}
{[
- ["NOW", "Live"],
+ ["NOW", "Now"],
["TODAY", "Today"],
["RECENT", "Recently"],
["PAST", "Past"],
@@ -675,6 +726,28 @@ export default function MapView() {
)}
+
+ {/* SOCIOWALL + CHAT EN BAS */}
+
);
}
diff --git a/src/main.jsx b/src/main.jsx
index 14724fd..bb1e263 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -9,6 +9,7 @@ import "./styles/map.css";
import "./styles/markers.css";
import "./styles/popup.css";
import "./styles/overlays.css";
+import "./styles/posts.css";
ReactDOM.createRoot(document.getElementById("root")).render(
diff --git a/src/styles/posts.css b/src/styles/posts.css
new file mode 100644
index 0000000..3f72da4
--- /dev/null
+++ b/src/styles/posts.css
@@ -0,0 +1,184 @@
+/* ==========================================
+ SOCIOWALL + CHAT (bas de l'écran)
+ ========================================== */
+
+.map-overlay-wall {
+ position: absolute;
+ left: 0.7rem;
+ right: 0.7rem;
+ bottom: 0.7rem;
+ display: flex;
+ gap: 0.6rem;
+ align-items: stretch;
+ pointer-events: none;
+ z-index: 25;
+}
+
+.map-overlay-wall * {
+ pointer-events: auto;
+}
+
+/* --------- SOCIOWALL (liste de posts) --------- */
+
+.sociowall-panel {
+ flex: 1.5;
+ min-height: 120px;
+ max-height: 220px;
+ background: rgba(15, 23, 42, 0.96);
+ border-radius: 14px;
+ border: 1px solid rgba(148, 163, 184, 0.9);
+ box-shadow:
+ 0 14px 40px rgba(0, 0, 0, 0.9),
+ 0 0 22px rgba(56, 189, 248, 0.45);
+ padding: 0.5rem 0.6rem;
+ display: flex;
+ flex-direction: column;
+}
+
+.sociowall-header {
+ font-size: 0.78rem;
+ font-weight: 600;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ color: #bfdbfe;
+ margin-bottom: 0.3rem;
+}
+
+/* --------- LISTE DES POSTS --------- */
+
+.post-list {
+ flex: 1;
+ overflow-y: auto;
+ padding-right: 0.2rem;
+}
+
+.post-list-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.5rem;
+ margin-bottom: 0.25rem;
+ font-size: 0.7rem;
+ color: #cbd5f5;
+}
+
+.km-filter label {
+ font-size: 0.7rem;
+}
+
+.km-filter span {
+ font-weight: 600;
+}
+
+/* slider 0–1000 km */
+.km-filter input[type="range"] {
+ width: 130px;
+}
+
+/* texte de statut (chargement / erreur / vide) */
+.status-text {
+ font-size: 0.72rem;
+ opacity: 0.85;
+ margin: 0.15rem 0;
+}
+
+.status-error {
+ color: #fecaca;
+}
+
+/* --------- CARTE D’UN POST --------- */
+
+.post-card {
+ border-radius: 10px;
+ border: 1px solid rgba(55, 65, 81, 0.9);
+ background: rgba(15, 23, 42, 0.92);
+ padding: 0.3rem 0.45rem;
+ margin-bottom: 0.25rem;
+ font-size: 0.76rem;
+ cursor: pointer;
+ transition: background 0.15s ease, border-color 0.15s ease,
+ box-shadow 0.15s ease, transform 0.1s ease;
+}
+
+.post-card:hover {
+ background: rgba(17, 24, 39, 0.95);
+ border-color: rgba(96, 165, 250, 0.9);
+ box-shadow: 0 0 12px rgba(56, 189, 248, 0.4);
+ transform: translateY(-1px);
+}
+
+.post-card.selected {
+ background: linear-gradient(135deg, #1d4ed8, #0ea5e9);
+ border-color: #bfdbfe;
+ box-shadow:
+ 0 0 16px rgba(56, 189, 248, 0.6),
+ 0 12px 26px rgba(15, 23, 42, 0.98);
+}
+
+.post-card h3 {
+ margin: 0 0 0.15rem 0;
+ font-size: 0.8rem;
+}
+
+.post-card p {
+ margin: 0;
+ font-size: 0.72rem;
+ opacity: 0.9;
+}
+
+.post-km {
+ display: inline-block;
+ margin-top: 0.12rem;
+ font-size: 0.68rem;
+ padding: 0.05rem 0.35rem;
+ border-radius: 999px;
+ background: rgba(15, 118, 110, 0.2);
+ border: 1px solid rgba(45, 212, 191, 0.7);
+ color: #a5f3fc;
+}
+
+/* --------- PANEL CHAT (à droite) --------- */
+
+.chat-panel {
+ width: 150px;
+ min-width: 130px;
+ max-height: 220px;
+ background: rgba(15, 23, 42, 0.96);
+ border-radius: 14px;
+ border: 1px solid rgba(148, 163, 184, 0.9);
+ box-shadow:
+ 0 14px 40px rgba(0, 0, 0, 0.9),
+ 0 0 22px rgba(56, 189, 248, 0.45);
+ padding: 0.45rem 0.5rem;
+ display: flex;
+ flex-direction: column;
+}
+
+.chat-header {
+ font-size: 0.78rem;
+ font-weight: 600;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ color: #bfdbfe;
+ margin-bottom: 0.25rem;
+}
+
+.chat-users {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ font-size: 0.76rem;
+}
+
+.chat-users li {
+ display: flex;
+ align-items: center;
+ gap: 0.3rem;
+ padding: 0.18rem 0.1rem;
+}
+
+.chat-users li::before {
+ content: "👤";
+ font-size: 0.72rem;
+ opacity: 0.9;
+}