-
{author ? author[0]?.toUpperCase() : "U"}
+
+ {authorAvatar ?
: (author ? author[0]?.toUpperCase() : "U")}
+
{author}
{timeAgo}
@@ -230,6 +278,7 @@ export default function PostCard({ post, selected, onSelect }) {
requestAuth("Please sign in or create a free account to like this post.");
return;
}
+ trackEvent("post_like_click", { post_id: postId, context: "wall" });
const res = await togglePostLike(postId, !liked);
if (res?.ok) {
setLiked(!!res.liked);
@@ -254,6 +303,7 @@ export default function PostCard({ post, selected, onSelect }) {
requestAuth("Please sign in or create a free account to comment.");
return;
}
+ trackEvent("post_comment_open", { post_id: postId, context: "wall" });
if (onSelect) onSelect(post);
}}
>
@@ -265,6 +315,7 @@ export default function PostCard({ post, selected, onSelect }) {
onClick={async (e) => {
e.stopPropagation();
const shareUrl = `${window.location.origin}/p/${postId}`;
+ trackEvent("post_share_click", { post_id: postId, context: "wall" });
try {
if (navigator.share) {
await navigator.share({ title: title || "SocioWire", url: shareUrl });
diff --git a/src/components/Search/SmartSearchBar.jsx b/src/components/Search/SmartSearchBar.jsx
index 6c35139..6eb9f77 100644
--- a/src/components/Search/SmartSearchBar.jsx
+++ b/src/components/Search/SmartSearchBar.jsx
@@ -1,6 +1,7 @@
import React, { useEffect, useMemo, useRef, useState } from "react";
import { recoSearch } from "../../services/recoSearch";
import "../../styles/smartSearchBar.css";
+import { trackEvent } from "../../utils/analytics";
function defaultZoomForKind(kind) {
const k = (kind || "").toLowerCase();
@@ -144,6 +145,12 @@ export default function SmartSearchBar({
setOpen(false);
setQ(it.title || q);
+ trackEvent("search_pick", {
+ kind: it.kind || "",
+ reason,
+ query_len: (q || "").length,
+ title_len: (it.title || "").length,
+ });
onPick && onPick(it, { zoom, reason });
};
@@ -162,6 +169,7 @@ export default function SmartSearchBar({
// Always filter on Enter; do not auto-pick dropdown items.
skipSearchRef.current = true;
setOpen(false);
+ trackEvent("search_submit", { query_len: q.trim().length });
onSearch && onSearch(q.trim());
}
} else if (e.key === "Escape") {
@@ -178,6 +186,7 @@ export default function SmartSearchBar({
setQ("");
setItems([]);
setOpen(false);
+ trackEvent("search_clear");
onSearch && onSearch(""); // Clear filters
};
@@ -196,6 +205,11 @@ export default function SmartSearchBar({
}
}}
onFocus={() => {
+ if (q.trim()) {
+ setQ("");
+ setItems([]);
+ onSearch && onSearch("");
+ }
setOpen(true);
// Si pas encore cherché et query vide, charger suggestions populaires
if (!hasSearched && !q.trim()) {
@@ -222,20 +236,14 @@ export default function SmartSearchBar({
)}
- onPlaceTourWire && onPlaceTourWire()}
- >
-
-
-
onMySpot && onMySpot()}
+ onClick={() => {
+ trackEvent("search_my_spot");
+ onMySpot && onMySpot();
+ }}
>
diff --git a/src/styles/auth-modal.css b/src/styles/auth-modal.css
index 631acef..9e11599 100644
--- a/src/styles/auth-modal.css
+++ b/src/styles/auth-modal.css
@@ -80,6 +80,21 @@ body[data-theme="light"] .auth-form input {
border-color: rgba(148, 163, 184, 0.9);
}
+.auth-link{
+ border: 0;
+ background: transparent;
+ color: rgba(255,255,255,.75);
+ text-align: left;
+ font-size: .78rem;
+ padding: 0;
+ cursor: pointer;
+ margin-top: -2px;
+}
+.auth-link:hover{
+ color: #fff;
+ text-decoration: underline;
+}
+
.btn-full { width:100%; margin-top:.4rem; }
.auth-divider{
diff --git a/src/styles/island.css b/src/styles/island.css
index 0aa1ae4..7f4f39c 100644
--- a/src/styles/island.css
+++ b/src/styles/island.css
@@ -112,6 +112,66 @@
border-bottom: 1px solid rgba(148, 163, 184, 0.15);
}
+.island-header-row{
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 14px;
+}
+
+.island-header-avatar{
+ width: 64px;
+ height: 64px;
+ border-radius: 14px;
+ overflow: hidden;
+ border: 1px solid rgba(56, 189, 248, 0.6);
+ background: rgba(56, 189, 248, 0.15);
+ display: grid;
+ place-items: center;
+ color: #e2e8f0;
+ font-weight: 800;
+}
+
+.island-header-avatar img{
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ display: block;
+}
+
+.island-header-text{
+ text-align: left;
+}
+
+.island-tabbar{
+ margin-top: 12px;
+ display: inline-flex;
+ gap: 10px;
+ padding: 6px 10px;
+ border-radius: 999px;
+ background: rgba(15, 23, 42, 0.6);
+ border: 1px solid rgba(148, 163, 184, 0.25);
+}
+
+.island-tab{
+ width: 34px;
+ height: 34px;
+ border-radius: 10px;
+ border: 0;
+ background: rgba(255, 255, 255, 0.08);
+ color: #e2e8f0;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+}
+
+.island-tab.is-active{
+ background: rgba(56, 189, 248, 0.25);
+ color: #fff;
+ box-shadow: 0 0 10px rgba(56, 189, 248, 0.35);
+}
+
.island-viewer-header h2 {
color: #f1f5f9;
font-size: 2.25rem;
@@ -139,10 +199,51 @@
background: rgba(15, 23, 42, 0.6);
margin-bottom: 1.5rem;
}
+
+.island-posts-panel{
+ padding: 0.9rem 1rem;
+ border-radius: 14px;
+ border: 1px solid rgba(148, 163, 184, 0.2);
+ background: rgba(15, 23, 42, 0.6);
+ margin-bottom: 1.5rem;
+ max-height: 280px;
+ overflow: auto;
+}
+
+.island-post-row{
+ padding: 10px 12px;
+ border-radius: 12px;
+ background: rgba(2, 6, 23, 0.4);
+ border: 1px solid rgba(148, 163, 184, 0.18);
+ margin-bottom: 10px;
+}
+
+.island-post-title{
+ font-weight: 800;
+ font-size: 0.88rem;
+ color: #f8fafc;
+}
+
+.island-post-snippet{
+ font-size: 0.78rem;
+ color: rgba(226, 232, 240, 0.8);
+ margin-top: 4px;
+}
+
+.island-post-meta{
+ font-size: 0.72rem;
+ color: rgba(148, 163, 184, 0.85);
+ margin-top: 6px;
+}
+
+.island-posts-empty{
+ font-size: 0.85rem;
+ color: rgba(226, 232, 240, 0.75);
+}
.island-profile-avatar {
width: 64px;
height: 64px;
- border-radius: 999px;
+ border-radius: 14px;
overflow: hidden;
border: 1px solid rgba(56, 189, 248, 0.6);
background: rgba(56, 189, 248, 0.2);
@@ -160,6 +261,16 @@
font-weight: 800;
font-size: 1.4rem;
}
+
+.island-viewer-canvas-wrap{
+ position: relative;
+}
+
+.island-tabbar-overlay{
+ position: absolute;
+ right: 16px;
+ top: 16px;
+}
.island-profile-meta {
flex: 1;
min-width: 0;
@@ -175,6 +286,16 @@
flex-direction: column;
gap: 0.35rem;
}
+
+.island-profile-error{
+ font-size: 0.75rem;
+ color: #f87171;
+}
+
+.island-profile-info{
+ font-size: 0.75rem;
+ color: #86efac;
+}
.island-profile-row {
display: flex;
align-items: center;
diff --git a/src/styles/mapMarkers.css b/src/styles/mapMarkers.css
index bae947d..6d2f21d 100644
--- a/src/styles/mapMarkers.css
+++ b/src/styles/mapMarkers.css
@@ -234,6 +234,26 @@
padding-left: 12px;
}
+.sw-user-avatar{
+ width: 22px;
+ height: 22px;
+ border-radius: 6px;
+ display: grid;
+ place-items: center;
+ background: rgba(56,189,248,0.18);
+ border: 1px solid rgba(56,189,248,0.35);
+ color: #e5e7eb;
+ font-weight: 800;
+ overflow: hidden;
+ flex-shrink: 0;
+}
+.sw-user-avatar img{
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ display: block;
+}
+
.sw-chat-line{ font-size: 10px; color:#c7e3ff; }
.sw-chat-bubble{
@@ -246,6 +266,23 @@
background: rgba(15,23,42,0.55);
border:1px solid rgba(56,189,248,0.18);
}
+
+.sw-chat-head{
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+.sw-chat-avatar{
+ width: 20px;
+ height: 20px;
+ border-radius: 6px;
+}
+
+.sw-inline-avatar{
+ width: 18px;
+ height: 18px;
+ border-radius: 6px;
+}
.sw-chat-bubble::before{
content:"";
position:absolute;
@@ -365,6 +402,7 @@ body[data-theme="light"] .sw-chat-bubble::before{
height: 640px !important;
max-height: 640px !important;
overflow: hidden !important;
+ box-sizing: border-box;
}
/* Override hidden overflow for centered modal to allow scroll */
@@ -379,12 +417,16 @@ body[data-theme="light"] .sw-chat-bubble::before{
.sw-template-full-wrap{
display: block !important;
- width: 440px !important;
+ width: 100% !important;
+ max-width: 100% !important;
height: 640px !important;
+ box-sizing: border-box;
}
.sw-template-full-wrap > *{
display: block !important;
+ max-width: 100% !important;
+ box-sizing: border-box;
}
/* Expanded header */
@@ -513,6 +555,19 @@ body[data-theme="light"] .sw-chat-bubble::before{
flex-wrap:wrap;
}
+.sw-modal-author-avatar{
+ width: 20px;
+ height: 20px;
+ border-radius: 6px;
+ border: 1px solid rgba(56,189,248,0.35);
+ background: rgba(56,189,248,0.18);
+ display: grid;
+ place-items: center;
+ overflow: hidden;
+ color: #e5e7eb;
+ font-weight: 800;
+}
+
.sw-modal-x{
border:none;
border-radius:999px;
@@ -530,7 +585,9 @@ body[data-theme="light"] .sw-chat-bubble::before{
width:100%;
height: 180px;
min-height: 180px;
- flex: 0 0 auto;
+ flex: 1 1 auto;
+ min-width: 0;
+ box-sizing: border-box;
border-radius: 16px;
overflow:hidden;
border: 3px solid #000 !important; /* contour plus épais */
@@ -543,6 +600,8 @@ body[data-theme="light"] .sw-chat-bubble::before{
display:flex;
gap:10px;
align-items: stretch;
+ min-width: 0;
+ width: 100%;
}
.sw-truth-rail{
@@ -646,6 +705,7 @@ body[data-theme="light"] .sw-chat-bubble::before{
width:100%;
height:100%;
object-fit: cover;
+ object-position: center center;
display:block;
}
diff --git a/src/styles/posts.css b/src/styles/posts.css
index cc19519..6988b4b 100644
--- a/src/styles/posts.css
+++ b/src/styles/posts.css
@@ -74,7 +74,7 @@
.sw-wall-avatar{
width:34px;
height:34px;
- border-radius:999px;
+ border-radius:10px;
background: rgba(56,189,248,0.22);
border:1px solid rgba(56,189,248,0.55);
color:#e2f2ff;
@@ -82,6 +82,13 @@
display:flex;
align-items:center;
justify-content:center;
+ overflow: hidden;
+}
+.sw-wall-avatar img{
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ display: block;
}
.sw-wall-meta{ flex:1; min-width:0; }
.sw-wall-author{
diff --git a/src/styles/smartSearchBar.css b/src/styles/smartSearchBar.css
index 6044696..0216e3a 100644
--- a/src/styles/smartSearchBar.css
+++ b/src/styles/smartSearchBar.css
@@ -6,6 +6,23 @@
max-width: 560px;
}
+.sw-search-row{
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.sw-search__side{
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ padding: 6px 8px;
+ border-radius: 14px;
+ background: var(--sw-panel-bg, rgba(15, 18, 28, 0.62));
+ border: 1px solid var(--sw-panel-border, rgba(255, 255, 255, 0.10));
+ backdrop-filter: blur(10px);
+}
+
.sw-search__bar {
position: relative;
display: flex;
diff --git a/src/styles/topbar.css b/src/styles/topbar.css
index 00d0790..8dede93 100644
--- a/src/styles/topbar.css
+++ b/src/styles/topbar.css
@@ -43,6 +43,7 @@
flex-shrink: 0;
}
+
.theme-switch{ display:flex; gap:.28rem; }
.theme-dot{
width:22px; height:22px; border-radius:999px;
@@ -482,10 +483,20 @@ body[data-theme="light"] .user-avatar{
margin: 0;
}
+.sw-userchip-btn{
+ border: 0;
+ cursor: pointer;
+}
+
+.sw-userchip-btn:hover{
+ box-shadow: 0 6px 16px rgba(56,189,248,.35);
+ border-color: rgba(56,189,248,.7);
+}
+
.sw-avatar{
width: 26px;
height: 26px;
- border-radius: 999px;
+ border-radius: 8px;
display: grid;
place-items: center;
background: rgba(56,189,248,0.18);
diff --git a/src/utils/analytics.js b/src/utils/analytics.js
new file mode 100644
index 0000000..7d5e0e6
--- /dev/null
+++ b/src/utils/analytics.js
@@ -0,0 +1,17 @@
+export function trackEvent(name, params = {}) {
+ if (typeof window === "undefined") return;
+ if (typeof window.gtag !== "function") return;
+ window.gtag("event", name, params);
+}
+
+export function trackPageView(path, title) {
+ if (typeof window === "undefined") return;
+ const pagePath = path || window.location.pathname || "/";
+ const pageTitle = title || document.title || "SocioWire";
+ trackEvent("page_view", { page_path: pagePath, page_title: pageTitle });
+}
+
+export function trackSection(section, params = {}) {
+ if (!section) return;
+ trackEvent("section_view", { section, ...params });
+}