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 */} +
+
+
Sociowall
+ +
+
+
Chat
+ +
+
); } 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; +}