From 04dc5f695c38d562feb70e9ca93449ea31d13ea7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 20 Dec 2025 23:17:28 -0500 Subject: [PATCH] update frontend --- src/components/Map/MapView.jsx | 195 ++++++++++------- src/styles/map.css | 381 ++++++++++++++++++++++++++++++++- 2 files changed, 493 insertions(+), 83 deletions(-) diff --git a/src/components/Map/MapView.jsx b/src/components/Map/MapView.jsx index e0bf43c..6d30431 100644 --- a/src/components/Map/MapView.jsx +++ b/src/components/Map/MapView.jsx @@ -1,5 +1,6 @@ import React, { useEffect, useRef, useState } from "react"; import "maplibre-gl/dist/maplibre-gl.css"; +import "../../styles/map.css"; import "../../styles/mapMarkers.css"; import "../../styles/overlays.css"; @@ -7,7 +8,11 @@ import "../../styles/posts.css"; import "../../styles/filters.css"; import { createPost } from "../../api/client"; -import { FILTER_MAIN_CATEGORIES, FILTER_CATEGORY_MAP, CREATE_CATEGORY_MAP } from "./mapConfig"; +import { + FILTER_MAIN_CATEGORIES, + FILTER_CATEGORY_MAP, + CREATE_CATEGORY_MAP, +} from "./mapConfig"; import { useMapCore } from "./useMapCore"; import { useUserPosition } from "./useUserPosition"; import { usePostsEngine } from "./usePostsEngine"; @@ -52,23 +57,26 @@ export default function MapView({ const [searchQuery, setSearchQuery] = useState(""); - const { status, visiblePosts, loadingPosts, loadError, handleIncomingPost } = usePostsEngine({ - theme, - mapRef, - viewParams, - mainFilter, - subFilter, - timeFilter, - searchQuery, - markersRef, - expandedElRef, - }); + const { status, visiblePosts, loadingPosts, loadError, handleIncomingPost } = + usePostsEngine({ + theme, + mapRef, + viewParams, + mainFilter, + subFilter, + timeFilter, + searchQuery, + markersRef, + expandedElRef, + }); const [isCreating, setIsCreating] = useState(false); const [draftTitle, setDraftTitle] = useState(""); const [draftBody, setDraftBody] = useState(""); const [draftCategory, setDraftCategory] = useState("News"); - const [draftSubCategory, setDraftSubCategory] = useState(CREATE_CATEGORY_MAP.News[0]); + const [draftSubCategory, setDraftSubCategory] = useState( + CREATE_CATEGORY_MAP.News[0] + ); const [draftCoords, setDraftCoords] = useState(null); const [isSaving, setIsSaving] = useState(false); const [saveError, setSaveError] = useState(""); @@ -241,7 +249,9 @@ export default function MapView({ } if (needsEmailVerification) { - setSaveError("Verify your email to post. Use 'Resend email' in the top bar, then login again."); + setSaveError( + "Verify your email to post. Use 'Resend email' in the top bar, then login again." + ); return; } @@ -278,7 +288,8 @@ export default function MapView({ { title: draftTitle.trim(), snippet: draftBody.trim() || draftTitle.trim(), - category: draftCategory === "Events" ? "EVENT" : draftCategory.toUpperCase(), + category: + draftCategory === "Events" ? "EVENT" : draftCategory.toUpperCase(), sub_category: draftSubCategory || "ALL", lat, lon: lng, @@ -299,10 +310,14 @@ export default function MapView({ const msg = String((e && e.message) || "").toLowerCase(); const isNotVerified = code === "email_not_verified" || - (e && e.status === 403 && (msg.includes("not verified") || msg.includes("verify"))); + (e && + e.status === 403 && + (msg.includes("not verified") || msg.includes("verify"))); if (isNotVerified) { - setSaveError("Verify your email to post. Use 'Resend email' in the top bar, then login again."); + setSaveError( + "Verify your email to post. Use 'Resend email' in the top bar, then login again." + ); } else { setSaveError((e && e.message) || "Error creating post."); } @@ -331,66 +346,71 @@ export default function MapView({
{status &&
{status}
} - {/* TOP: Search à gauche, 2 icônes à droite */} -
-
- - setSearchQuery(e.target.value)} - autoCapitalize="none" - autoCorrect="off" - spellCheck={false} - /> - {searchQuery ? ( + {/* TOP: Search à gauche, 2 icônes à droite, sur une seule ligne */} +
+
+ + + setSearchQuery(e.target.value)} + autoCapitalize="none" + autoCorrect="off" + spellCheck={false} + /> + {searchQuery ? ( + + ) : null} + + +
- ) : null} - -
- - - + +
- setTimeFilter(code)} /> + setTimeFilter(code)} + />
@@ -403,13 +423,21 @@ export default function MapView({
- Move the map, aim with the crosshair — your wire will be pinned there. + Move the map, aim with the crosshair — your wire will be pinned + there.
@@ -443,7 +475,9 @@ export default function MapView({ onChange={(e) => { const cat = e.target.value; setDraftCategory(cat); - setDraftSubCategory((CREATE_CATEGORY_MAP[cat] || CREATE_CATEGORY_MAP.News)[0]); + setDraftSubCategory( + (CREATE_CATEGORY_MAP[cat] || CREATE_CATEGORY_MAP.News)[0] + ); }} > {["News", "Friends", "Events", "Market"].map((cat) => ( @@ -451,8 +485,13 @@ export default function MapView({ ))} - setDraftSubCategory(e.target.value)} + > + {(CREATE_CATEGORY_MAP[draftCategory] || + CREATE_CATEGORY_MAP.News + ).map((sub) => ( ))} @@ -476,7 +515,11 @@ export default function MapView({ {saveError &&
{saveError}
}
-
diff --git a/src/styles/map.css b/src/styles/map.css index 6832f52..79da097 100644 --- a/src/styles/map.css +++ b/src/styles/map.css @@ -1,9 +1,13 @@ :root{ --sw-subcats-nudge: -45px; /* subcats vertical nudge */ - --sw-below-overlap: 40px; /* wall overlaps map a bit */ + --sw-below-overlap: 40px; /* wall overlaps map a bit */ } -.map-page{ display:flex; flex-direction:column; width:100%; } +.map-page{ + display:flex; + flex-direction:column; + width:100%; +} /* Map stage first */ .map-stage{ @@ -18,14 +22,22 @@ .map-stage{ height: clamp(360px, 62vh, 720px); } } -.map-container, .maplibre-container{ - position:absolute; inset:0; width:100%; height:100%; +.map-container, +.maplibre-container{ + position:absolute; + inset:0; + width:100%; + height:100%; } .map-status{ - position:absolute; left:.5rem; bottom:.5rem; - font-size:.7rem; padding:.2rem .4rem; - background:rgba(0,0,0,.6); border-radius:.5rem; + position:absolute; + left:.5rem; + bottom:.5rem; + font-size:.7rem; + padding:.2rem .4rem; + background:rgba(0,0,0,.6); + border-radius:.5rem; z-index:30; } @@ -48,3 +60,358 @@ @media (max-width: 340px){ .below-row{ flex-direction:column; } } + +/* ======== OVERLAYS ======== */ + +.map-overlay{ + position:absolute; + pointer-events:none; + z-index:40; +} +.map-overlay *{ pointer-events:auto; } + +/* TOP: centré horizontalement, petit offset en haut */ +.map-overlay-top{ + top: .7rem; + left:50%; + transform:translateX(-50%); + max-width: min(980px, calc(100vw - 24px)); +} + +/* Left / right: filtres */ +.map-overlay-left{ + left:.7rem; + top:44%; + transform:translateY(-50%); + display:flex; + flex-direction:column; + gap:.5rem; +} +.map-overlay-right{ + right:.7rem; + top:44%; + transform:translateY(-50%); + display:flex; + flex-direction:column; + gap:.5rem; +} + +/* BOTTOM: sub-cats au-dessus du Sociowall */ +.map-overlay-bottom{ + bottom: calc(3.2rem + var(--sw-below-overlap, 0px) + env(safe-area-inset-bottom) + var(--sw-subcats-nudge, 0px)); + left:50%; + transform:translateX(-50%); + display:flex; + gap:.4rem; +} + +/* Crosshair pour création */ +.map-crosshair{ + left:50%; + top:40%; + transform:translate(-50%,-50%); +} +.crosshair-aim{ + width:34px; + height:34px; + border-radius:999px; + border:1px solid #38bdf8; + position:relative; + box-shadow:0 0 14px rgba(56,189,248,.9); +} +.crosshair-aim::before, +.crosshair-aim::after{ + content:""; + position:absolute; + left:50%; + top:50%; + background:#38bdf8; + transform:translate(-50%,-50%); +} +.crosshair-aim::before{ + width:70%; + height:1px; +} +.crosshair-aim::after{ + width:1px; + height:70px; +} + +/* Panneau de création */ +.create-post-panel{ + left:50%; + bottom:20%; + transform:translateX(-50%); + width:92%; + max-width:520px; + background: rgba(15, 23, 42, 0.96); + border-radius:16px; + border:1px solid rgba(148, 163, 184, 0.9); + box-shadow: 0 16px 40px rgba(0,0,0,.9), 0 0 24px rgba(56,189,248,.6); + padding: .6rem .7rem .7rem; +} +.create-post-header{ + display:flex; + justify-content:space-between; + align-items:center; + font-size:.8rem; + margin-bottom:.4rem; + color:#e5e7eb; +} +.create-close{ + background:transparent; + border:none; + color:#9ca3af; + font-size:.85rem; + padding:.1rem .3rem; + cursor:pointer; +} +.create-row{ + display:flex; + align-items:center; + gap:.5rem; + margin-bottom:.4rem; +} +.crosshair-label{ + font-size:.75rem; + color:#cbd5f5; +} + +.create-row select{ + flex:1; + background:#020617; + border-radius:999px; + border:1px solid #4b5563; + padding:.35rem .7rem; + font-size:.75rem; + color:#e5e7eb; +} +.create-input{ + width:100%; + margin-bottom:.3rem; + border-radius:999px; + border:1px solid #4b5563; + padding:.35rem .7rem; + background:#020617; + color:#e5e7eb; + font-size:.8rem; +} +.create-textarea{ + width:100%; + border-radius:.75rem; + border:1px solid #4b5563; + padding:.35rem .7rem; + background:#020617; + color:#e5e7eb; + resize:none; + font-size:.78rem; +} +.create-error{ + margin-top:.25rem; + font-size:.7rem; + color:#f97373; +} +.create-actions{ + margin-top:.4rem; + display:flex; + justify-content:flex-end; +} + +.chip-pill{ + background: rgba(15, 23, 42, 0.96); + border: 1px solid rgba(148, 163, 184, 0.85); + color: #e5e7eb; + padding: 0.45rem 0.9rem; + font-size: 0.78rem; + border-radius: 999px; + cursor: pointer; + box-shadow: 0 5px 12px rgba(0,0,0,.7), 0 0 12px rgba(56,189,248,.35); +} + +/* ===== SEARCHBAR TOP ===== */ + +.sw-searchbar{ + pointer-events: auto; + display:flex; + align-items:center; + gap: .55rem; + padding: 0.42rem 0.70rem; + border-radius: 999px; + background: rgba(15, 23, 42, 0.92); + border: 1px solid rgba(148, 163, 184, 0.85); + box-shadow: 0 5px 12px rgba(0,0,0,.70), 0 0 14px rgba(56,189,248,.22); + backdrop-filter: blur(10px); + min-height: 38px; +} + +.sw-searchbar:focus-within{ + border-color: rgba(56,189,248,.85); + box-shadow: 0 8px 18px rgba(0,0,0,.72), 0 0 18px rgba(56,189,248,.35); +} + +.sw-search-icon{ + font-size: 14px; + opacity: .95; +} + +.sw-search-input{ + border: none; + outline: none; + background: transparent; + color: #e5e7eb; + font-size: 0.80rem; + font-weight: 800; + width: min(52vw, 360px); + min-width: 160px; +} + +.sw-search-input::placeholder{ + color: rgba(203, 213, 225, 0.88); + font-weight: 800; +} + +.sw-search-clear{ + border: none; + cursor: pointer; + width: 28px; + height: 28px; + border-radius: 999px; + background: rgba(2,6,23,.35); + border: 1px solid rgba(148,163,184,.35); + color: #e5e7eb; + font-weight: 900; + display:grid; + place-items:center; +} +.sw-search-clear:active{ + transform: scale(0.97); +} + +/* Light theme */ +body[data-theme="light"] .sw-searchbar{ + background: rgba(255,255,255,0.92); + border-color: rgba(148, 163, 184, 0.85); + box-shadow: 0 8px 18px rgba(0,0,0,.10); +} +body[data-theme="light"] .sw-search-input{ + color:#0B1220; +} +body[data-theme="light"] .sw-search-input::placeholder{ + color: rgba(91, 103, 122, 0.92); +} +body[data-theme="light"] .sw-search-clear{ + background: rgba(255,255,255,.85); + color:#0B1220; + border-color: rgba(148,163,184,.55); +} + +/* Tight phones: keep it clean */ +@media (max-width: 420px){ + .sw-search-input{ + width: min(72vw, 320px); + min-width: 120px; + } +} + +/* ===== TOP ROW: search + 2 icônes ===== */ + +.sw-top-row{ + display:flex; + align-items:center; + justify-content:space-between; + gap:0.75rem; +} + +/* search = prend la place à gauche */ +.sw-top-search{ + flex:1 1 auto; +} + +/* bloc des 2 boutons à droite */ +.map-top-actions{ + display:flex; + flex-direction:row; + align-items:center; + gap:0.5rem; +} + +/* boutons icône */ +.map-action-btn{ + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + padding:0.35rem 0.55rem; + border-radius:999px; + border:1px solid rgba(255,255,255,0.15); + background:rgba(5, 25, 60, 0.25); + backdrop-filter:blur(8px); + box-shadow:0 6px 14px rgba(0,0,0,0.35); + 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; +} + +.map-top-actions .map-action-btn i{ + display:block; + font-size:1.05rem; + margin-bottom:0.15rem; +} + +.map-top-actions .map-action-btn span{ + font-size:0.65rem; + font-weight:600; + letter-spacing:0.03em; +} + +/* TOP layout: 75% search / 25% boutons */ +.map-overlay-top .sw-top-row{ + display:flex; + align-items:center; + justify-content:space-between; + gap:0.75rem; +} + +.map-overlay-top .sw-searchbar{ + flex:0 0 75%; + max-width:75%; +} + +.map-overlay-top .map-top-actions{ + flex:0 0 25%; + max-width:25%; + display:flex; + justify-content:flex-end; + gap:0.5rem; +} + +/* petits écrans */ +@media (max-width:480px){ + .map-overlay-top .sw-top-row{ + gap:0.4rem; + } + .map-top-actions .map-action-btn{ + padding:0.3rem 0.45rem; + } + .map-overlay-top .sw-searchbar{ + flex:1 1 auto; + max-width:100%; + } +}