From 4753cacdcc3bdc00015227b3665f0d181921ed60 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 18 Dec 2025 15:45:46 -0500 Subject: [PATCH] goood --- src/App.jsx | 51 +++++- src/components/Map/MapView.jsx | 274 +++++++++++++++------------- src/components/Map/templateSpecs.js | 46 ++++- src/styles/layout.css | 19 +- src/styles/map.css | 33 ++-- src/styles/mapMarkers.css | 31 ++++ src/styles/posts.css | 21 ++- 7 files changed, 317 insertions(+), 158 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index c2c26ad..ab708fa 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,6 @@ -import React, { Suspense, useEffect, useState } from "react"; +import React, { Suspense, useEffect, useState, useCallback } from "react"; import TopBar from "./components/Layout/TopBar"; +import PostList from "./components/Posts/PostList"; // Lazy-load de la carte (gros chunk : maplibre, CSS, etc.) const MapView = React.lazy(() => import("./components/Map/MapView")); @@ -9,6 +10,19 @@ const THEME_KEY = "sociowire:theme"; export default function App() { const [theme, setTheme] = useState("blue"); + // Wall state (lifted from MapView) + const [wallPosts, setWallPosts] = useState([]); + const [wallLoading, setWallLoading] = useState(false); + const [wallError, setWallError] = useState(""); + const [selectedPost, setSelectedPost] = useState(null); + + const handlePostsState = useCallback((next) => { + if (!next) return; + if (Array.isArray(next.posts)) setWallPosts(next.posts); + setWallLoading(!!next.loading); + setWallError(next.error || ""); + }, []); + // charge le thème au démarrage useEffect(() => { if (typeof window === "undefined") return; @@ -39,12 +53,45 @@ export default function App() { return (
+
Loading map…
}> - +
+ + {/* BELOW THE MAP (page scroll like Facebook) */} +
+
+
+
SOCIOWALL
+ +
+ +
+
CHAT
+
    +
  • Yan
  • +
  • Marc
  • +
  • Fiso
  • +
+
+
+
+ +
); diff --git a/src/components/Map/MapView.jsx b/src/components/Map/MapView.jsx index e72320d..c4cf18b 100644 --- a/src/components/Map/MapView.jsx +++ b/src/components/Map/MapView.jsx @@ -11,15 +11,24 @@ import { FILTER_MAIN_CATEGORIES, FILTER_CATEGORY_MAP, CREATE_CATEGORY_MAP } from import { useMapCore } from "./useMapCore"; import { useUserPosition } from "./useUserPosition"; import { usePostsEngine } from "./usePostsEngine"; -import PostList from "../Posts/PostList"; import { useAuth } from "../../auth/AuthContext"; import FilterButtons from "../Filters/FilterButtons"; import TimeFilterButtons from "../Filters/TimeFilterButtons"; -export default function MapView({ theme = "dark" }) { +export default function MapView({ + theme = "dark", + + // lift posts to App (so Sociowall is NOT inside the map) + onPostsState, + + // selection controlled by App + selectedPost, + onSelectPost, +}) { const { authenticated, username, token } = useAuth(); - const { containerRef, mapRef, markersRef, expandedElRef, viewParams, hasLastView } = useMapCore(theme); + const { containerRef, mapRef, markersRef, expandedElRef, viewParams, hasLastView } = + useMapCore(theme); const [mainFilter, setMainFilter] = useState("All"); const [timeFilter, setTimeFilter] = useState("RECENT"); @@ -37,8 +46,6 @@ export default function MapView({ theme = "dark" }) { expandedElRef, }); - const [selectedPost, setSelectedPost] = useState(null); - const [isCreating, setIsCreating] = useState(false); const [draftTitle, setDraftTitle] = useState(""); const [draftBody, setDraftBody] = useState(""); @@ -50,11 +57,38 @@ export default function MapView({ theme = "dark" }) { const bottomCategories = FILTER_CATEGORY_MAP[mainFilter] || ["All"]; + // keep subFilter valid useEffect(() => { if (!bottomCategories.length) return; if (!subFilter || !bottomCategories.includes(subFilter)) setSubFilter("All"); }, [mainFilter, bottomCategories, subFilter]); + // push posts state up to App (for Sociowall) + useEffect(() => { + if (!onPostsState) return; + onPostsState({ + status, + posts: visiblePosts, + loading: loadingPosts, + error: loadError, + }); + }, [status, visiblePosts, loadingPosts, loadError, onPostsState]); + + // if App selects a post (from Sociowall), fly to it on map + useEffect(() => { + if (!selectedPost) return; + const map = mapRef.current; + if (!map) return; + + const lng = selectedPost.lon ?? selectedPost.lng; + const lat = selectedPost.lat ?? selectedPost.latitude; + + if (typeof lng === "number" && typeof lat === "number") { + map.flyTo({ center: [lng, lat], zoom: 8, speed: 1.4 }); + } + }, [selectedPost, mapRef]); + + // Websocket for new posts useEffect(() => { const proto = window.location.protocol === "https:" ? "wss" : "ws"; const host = @@ -108,6 +142,7 @@ export default function MapView({ theme = "dark" }) { const handleSubmitPost = async () => { if (isSaving) return; setSaveError(""); + const map = mapRef.current; if (!map) return; @@ -130,8 +165,8 @@ export default function MapView({ theme = "dark" }) { baseLat = center.lat; } + // keep marker visually above pointer const pixelOffsetY = -20; - const screenPoint = map.project([baseLng, baseLat]); const correctedPoint = { x: screenPoint.x, y: screenPoint.y + pixelOffsetY }; const correctedLngLat = map.unproject([correctedPoint.x, correctedPoint.y]); @@ -170,146 +205,133 @@ export default function MapView({ theme = "dark" }) { } }; - const handleSelectPost = (post) => { - setSelectedPost(post); - const map = mapRef.current; - if (!map) return; - const lng = post.lon ?? post.lng; - const lat = post.lat ?? post.latitude; - if (typeof lng === "number" && typeof lat === "number") map.flyTo({ center: [lng, lat], zoom: 8, speed: 1.4 }); - }; - const handleMainFilterSelect = (code) => { if (!FILTER_MAIN_CATEGORIES.includes(code)) return; setMainFilter(code); }; + // allow selecting from map later (optional hook) + const handleSelectPost = (post) => { + if (onSelectPost) onSelectPost(post); + const map = mapRef.current; + if (!map) return; + const lng = post.lon ?? post.lng; + const lat = post.lat ?? post.latitude; + if (typeof lng === "number" && typeof lat === "number") { + map.flyTo({ center: [lng, lat], zoom: 8, speed: 1.4 }); + } + }; + return ( -
\n
-
- {status &&
{status}
} +
+
+
+ {status &&
{status}
} -
- - -
- -
- setTimeFilter(code)} /> -
- -
- -
- -
-
- {bottomCategories.map((c) => ( - - ))} +
+ +
-
-
- -
- - {isCreating && ( -
-
+
+ setTimeFilter(code)} />
- )} - {isCreating && ( -
-
- Create wire - -
- - Move the map, aim with the crosshair — your wire will be pinned there. - -
- - -
- setDraftTitle(e.target.value)} - /> -