update frontend

This commit is contained in:
Your Name 2025-12-20 22:54:48 -05:00
parent 0989edbd09
commit 0dad16e338
2 changed files with 70 additions and 24 deletions

View File

@ -17,11 +17,7 @@ import TimeFilterButtons from "../Filters/TimeFilterButtons";
export default function MapView({ export default function MapView({
theme = "dark", theme = "dark",
// lift posts to App (so Sociowall is NOT inside the map)
onPostsState, onPostsState,
// selection controlled by App
selectedPost, selectedPost,
onSelectPost, onSelectPost,
}) { }) {
@ -79,7 +75,6 @@ export default function MapView({
const bottomCategories = FILTER_CATEGORY_MAP[mainFilter] || ["All"]; const bottomCategories = FILTER_CATEGORY_MAP[mainFilter] || ["All"];
/* SW_SUBCAT_ICONS:BEGIN */
const getSubcatIcon = (main, sub) => { const getSubcatIcon = (main, sub) => {
const M = { const M = {
All: { All: {
@ -125,15 +120,12 @@ export default function MapView({
return (M[main] && M[main][sub]) || ""; return (M[main] && M[main][sub]) || "";
}; };
/* SW_SUBCAT_ICONS:END */
// keep subFilter valid
useEffect(() => { useEffect(() => {
if (!bottomCategories.length) return; if (!bottomCategories.length) return;
if (!subFilter || !bottomCategories.includes(subFilter)) setSubFilter("All"); if (!subFilter || !bottomCategories.includes(subFilter)) setSubFilter("All");
}, [mainFilter, bottomCategories, subFilter]); }, [mainFilter, bottomCategories, subFilter]);
// push posts state up to App (for Sociowall)
useEffect(() => { useEffect(() => {
if (!onPostsState) return; if (!onPostsState) return;
onPostsState({ onPostsState({
@ -144,7 +136,6 @@ export default function MapView({
}); });
}, [status, visiblePosts, loadingPosts, loadError, onPostsState]); }, [status, visiblePosts, loadingPosts, loadError, onPostsState]);
// if App selects a post (from Sociowall), fly to it on map
useEffect(() => { useEffect(() => {
if (!selectedPost) return; if (!selectedPost) return;
const map = mapRef.current; const map = mapRef.current;
@ -158,7 +149,6 @@ export default function MapView({
} }
}, [selectedPost, mapRef]); }, [selectedPost, mapRef]);
// Hide subcats when map isn't visible enough (keeps UI clean)
useEffect(() => { useEffect(() => {
const el = stageRef.current; const el = stageRef.current;
if (!el || typeof IntersectionObserver === "undefined") return; if (!el || typeof IntersectionObserver === "undefined") return;
@ -176,7 +166,6 @@ export default function MapView({
return () => obs.disconnect(); return () => obs.disconnect();
}, []); }, []);
// Websocket for new posts
useEffect(() => { useEffect(() => {
const proto = window.location.protocol === "https:" ? "wss" : "ws"; const proto = window.location.protocol === "https:" ? "wss" : "ws";
const host = const host =
@ -231,7 +220,6 @@ export default function MapView({
setDraftCoords(null); setDraftCoords(null);
}; };
// Keep submit to allow Enter key, but no popup:
const handleSearchSubmit = (e) => { const handleSearchSubmit = (e) => {
e.preventDefault(); e.preventDefault();
}; };
@ -271,7 +259,6 @@ export default function MapView({
baseLat = center.lat; baseLat = center.lat;
} }
// keep marker visually above pointer
const pixelOffsetY = -20; const pixelOffsetY = -20;
const screenPoint = map.project([baseLng, baseLat]); const screenPoint = map.project([baseLng, baseLat]);
const correctedPoint = { x: screenPoint.x, y: screenPoint.y + pixelOffsetY }; const correctedPoint = { x: screenPoint.x, y: screenPoint.y + pixelOffsetY };
@ -327,7 +314,6 @@ export default function MapView({
setMainFilter(code); setMainFilter(code);
}; };
// allow selecting from map later (optional hook)
const handleSelectPost = (post) => { const handleSelectPost = (post) => {
if (onSelectPost) onSelectPost(post); if (onSelectPost) onSelectPost(post);
const map = mapRef.current; const map = mapRef.current;
@ -345,10 +331,10 @@ export default function MapView({
<div ref={containerRef} className="map-container" /> <div ref={containerRef} className="map-container" />
{status && <div className="map-status">{status}</div>} {status && <div className="map-status">{status}</div>}
{/* === TOP OVERLAY: Search + 2 boutons === */} {/* TOP: Search à gauche, 2 icônes à droite */}
<div className="map-overlay map-overlay-top"> <div className="map-overlay map-overlay-top sw-top-row">
<form <form
className="sw-searchbar" className="sw-searchbar sw-top-search"
onSubmit={handleSearchSubmit} onSubmit={handleSearchSubmit}
role="search" role="search"
aria-label="Search" aria-label="Search"
@ -377,22 +363,28 @@ export default function MapView({
) : null} ) : null}
</form> </form>
<div className="map-top-buttons"> <div className="map-top-actions">
<button <button
className="chip-pill"
type="button" type="button"
className="map-action-btn"
onClick={handleFlyToMe} onClick={handleFlyToMe}
disabled={!userPosition} disabled={!userPosition}
> >
My spot <div className="map-action-icon">
<i className="fa-solid fa-location-crosshairs" />
</div>
<div className="map-action-label">My spot</div>
</button> </button>
<button <button
className="chip-pill"
type="button" type="button"
className="map-action-btn"
onClick={handleOpenCreate} onClick={handleOpenCreate}
> >
Place your wire <div className="map-action-icon">
<i className="fa-solid fa-bolt" />
</div>
<div className="map-action-label">New wire</div>
</button> </button>
</div> </div>
</div> </div>
@ -426,8 +418,6 @@ export default function MapView({
</div> </div>
</div> </div>
{/* On n'a plus besoin du bouton My spot séparé en bas, il est en haut maintenant */}
{isCreating && ( {isCreating && (
<div className="map-overlay map-crosshair"> <div className="map-overlay map-crosshair">
<div className="crosshair-aim" /> <div className="crosshair-aim" />

View File

@ -173,3 +173,59 @@ body[data-theme="light"] .sw-search-clear{
align-items:center; align-items:center;
justify-content:center; justify-content:center;
} }
/* ==== TOP ROW: search + 2 icônes actions ===== */
.sw-top-row{
display:flex;
align-items:center;
justify-content:space-between;
gap:0.75rem;
}
/* la search prend tout l'espace dispo à gauche */
.sw-top-search{
flex:1 1 auto;
}
/* bloc des 2 boutons icônes à droite */
.map-top-actions{
display:flex;
flex-direction:row;
align-items:center;
gap:0.5rem;
}
/* bouton icône: rond + label en dessous */
.map-action-btn{
display:flex;
flex-direction:column;
align-items:center;
justify-content:center;
padding:0.25rem 0.45rem;
border-radius:0.9rem;
border:1px solid rgba(255,255,255,0.08);
background:rgba(8,8,16,0.9);
backdrop-filter:blur(14px);
box-shadow:0 8px 22px rgba(0,0,0,0.55);
font-size:0.7rem;
line-height:1.1;
cursor:pointer;
white-space:nowrap;
}
.map-action-btn:disabled{
opacity:0.45;
cursor:default;
}
.map-action-icon{
font-size:1.05rem;
margin-bottom:0.15rem;
}
.map-action-label{
font-size:0.6rem;
text-transform:uppercase;
letter-spacing:0.04em;
}