update frontend
This commit is contained in:
parent
253346cedc
commit
e0a8e68f33
|
|
@ -20,6 +20,7 @@ import {
|
||||||
matchesTimeFilter,
|
matchesTimeFilter,
|
||||||
} from "./mapFilter";
|
} from "./mapFilter";
|
||||||
import { createMarkerForPost, clearAllMarkers } from "./markerManager";
|
import { createMarkerForPost, clearAllMarkers } from "./markerManager";
|
||||||
|
import PostList from "../Posts/PostList";
|
||||||
|
|
||||||
export default function MapView() {
|
export default function MapView() {
|
||||||
const containerRef = useRef(null);
|
const containerRef = useRef(null);
|
||||||
|
|
@ -64,6 +65,12 @@ export default function MapView() {
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
const [saveError, setSaveError] = useState("");
|
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 ================= */
|
/* ================= INIT MAP ================= */
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -258,6 +265,7 @@ export default function MapView() {
|
||||||
createMarkerForPost(post, mapRef, markersRef, expandedElRef);
|
createMarkerForPost(post, mapRef, markersRef, expandedElRef);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setVisiblePosts(visible);
|
||||||
setStatus(visible.length ? "" : "No posts found.");
|
setStatus(visible.length ? "" : "No posts found.");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -289,6 +297,8 @@ export default function MapView() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setStatus("Loading posts...");
|
setStatus("Loading posts...");
|
||||||
|
setLoadingPosts(true);
|
||||||
|
setLoadError("");
|
||||||
|
|
||||||
const catCode = categoryCode(mainFilter);
|
const catCode = categoryCode(mainFilter);
|
||||||
const subCatParam =
|
const subCatParam =
|
||||||
|
|
@ -333,9 +343,14 @@ export default function MapView() {
|
||||||
};
|
};
|
||||||
|
|
||||||
rebuildMarkersForTimeFilter(timeFilter);
|
rebuildMarkersForTimeFilter(timeFilter);
|
||||||
|
setLoadingPosts(false);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Erreur chargement posts:", 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];
|
allPostsRef.current = [...allPostsRef.current, p];
|
||||||
|
|
||||||
createMarkerForPost(p, mapRef, markersRef, expandedElRef);
|
createMarkerForPost(p, mapRef, markersRef, expandedElRef);
|
||||||
|
setVisiblePosts((current) => [...current, p]);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// 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 ================= */
|
/* ================= RENDER ================= */
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -529,7 +580,7 @@ export default function MapView() {
|
||||||
{/* LEFT — time filters */}
|
{/* LEFT — time filters */}
|
||||||
<div className="map-overlay map-overlay-left">
|
<div className="map-overlay map-overlay-left">
|
||||||
{[
|
{[
|
||||||
["NOW", "Live"],
|
["NOW", "Now"],
|
||||||
["TODAY", "Today"],
|
["TODAY", "Today"],
|
||||||
["RECENT", "Recently"],
|
["RECENT", "Recently"],
|
||||||
["PAST", "Past"],
|
["PAST", "Past"],
|
||||||
|
|
@ -675,6 +726,28 @@ export default function MapView() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* SOCIOWALL + CHAT EN BAS */}
|
||||||
|
<div className="map-overlay map-overlay-wall">
|
||||||
|
<div className="sociowall-panel">
|
||||||
|
<div className="sociowall-header">Sociowall</div>
|
||||||
|
<PostList
|
||||||
|
posts={visiblePosts}
|
||||||
|
loading={loadingPosts}
|
||||||
|
error={loadError}
|
||||||
|
selectedPost={selectedPost}
|
||||||
|
onSelectPost={handleSelectPost}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="chat-panel">
|
||||||
|
<div className="chat-header">Chat</div>
|
||||||
|
<ul className="chat-users">
|
||||||
|
<li>Yan</li>
|
||||||
|
<li>Marc</li>
|
||||||
|
<li>Fiso</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import "./styles/map.css";
|
||||||
import "./styles/markers.css";
|
import "./styles/markers.css";
|
||||||
import "./styles/popup.css";
|
import "./styles/popup.css";
|
||||||
import "./styles/overlays.css";
|
import "./styles/overlays.css";
|
||||||
|
import "./styles/posts.css";
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue