From 26a8bf84e8be3909c0fa6561efac2bb65fe7d23d Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 21 Dec 2025 19:17:06 -0500 Subject: [PATCH] update frontend --- public/pwaInstall.js | 38 +++++-------- src/components/Layout/TopBar.jsx | 94 +++++++++++++++++++++++++++----- 2 files changed, 94 insertions(+), 38 deletions(-) diff --git a/public/pwaInstall.js b/public/pwaInstall.js index 600e819..2fe94d0 100644 --- a/public/pwaInstall.js +++ b/public/pwaInstall.js @@ -2,46 +2,38 @@ let deferredPrompt = null; window.addEventListener('beforeinstallprompt', (e) => { - // Empêche le prompt par défaut e.preventDefault(); deferredPrompt = e; console.log('PWA install prompt ready'); }); -// Fonction pour déclencher l’install (tu peux l’appeler sur un bouton) export function promptInstall() { if (deferredPrompt) { deferredPrompt.prompt(); - deferredPrompt.userChoice.then((choiceResult) => { - if (choiceResult.outcome === 'accepted') { - console.log('PWA installed'); - } else { - console.log('PWA dismissed'); - } + deferredPrompt.userChoice.then((choice) => { + console.log('Install outcome:', choice.outcome); deferredPrompt = null; }); + } else { + console.log('No install prompt available'); } } -// Ajoute un bouton "Installer l’app" dans ton UI (optionnel) -export function addInstallButton() { +// Fonction pour ajouter le bouton dans TopBar (on l'appelle depuis TopBar.jsx) +export function addPwaInstallButton(container) { const btn = document.createElement('button'); - btn.textContent = 'Installer SocioWire'; - btn.style.position = 'fixed'; - btn.style.bottom = '20px'; - btn.style.right = '20px'; - btn.style.padding = '10px 20px'; + btn.innerHTML = ' Installer'; // icône + texte + btn.style.marginLeft = '10px'; + btn.style.padding = '6px 12px'; + btn.style.fontSize = '12px'; btn.style.background = '#0ea5e9'; btn.style.color = 'white'; btn.style.border = 'none'; - btn.style.borderRadius = '8px'; + btn.style.borderRadius = '999px'; btn.style.cursor = 'pointer'; - btn.style.zIndex = '9999'; + btn.style.display = 'flex'; + btn.style.alignItems = 'center'; + btn.style.gap = '6px'; btn.onclick = promptInstall; - document.body.appendChild(btn); -} - -// Détection si déjà installé (cache) -if (window.matchMedia('(display-mode: standalone)').matches || navigator.standalone) { - console.log('App already installed'); + container.appendChild(btn); } \ No newline at end of file diff --git a/src/components/Layout/TopBar.jsx b/src/components/Layout/TopBar.jsx index 8635cbc..c431d73 100644 --- a/src/components/Layout/TopBar.jsx +++ b/src/components/Layout/TopBar.jsx @@ -1,8 +1,57 @@ +Voici les 2 fichiers complets à copier-coller entièrement (remplace tout le contenu actuel) pour que le bouton "Installer SocioWire" soit : +En haut (dans la TopBar, à côté des thèmes) +Petit et beau (icône download + texte discret) +Fonctionnel : clique → popup "Ajouter à l’écran d’accueil" +1. src/pwaInstall.js (copie-colle tout) +// src/pwaInstall.js +let deferredPrompt = null; + +window.addEventListener('beforeinstallprompt', (e) => { + e.preventDefault(); + deferredPrompt = e; + console.log('PWA install prompt ready'); +}); + +export function promptInstall() { + if (deferredPrompt) { + deferredPrompt.prompt(); + deferredPrompt.userChoice.then((choice) => { + console.log('Install outcome:', choice.outcome); + deferredPrompt = null; + }); + } else { + console.log('No install prompt available'); + } +} + +// Ajoute le bouton dans un container (appel depuis TopBar) +export function addPwaInstallButton(container) { + const btn = document.createElement('button'); + btn.innerHTML = ' Installer'; // icône + texte + btn.style.marginLeft = '8px'; + btn.style.padding = '5px 10px'; + btn.style.fontSize = '12px'; + btn.style.background = '#0ea5e9'; + btn.style.color = 'white'; + btn.style.border = 'none'; + btn.style.borderRadius = '999px'; + btn.style.cursor = 'pointer'; + btn.style.display = 'flex'; + btn.style.alignItems = 'center'; + btn.style.gap = '6px'; + btn.style.boxShadow = '0 2px 8px rgba(0,0,0,0.3)'; + btn.onclick = promptInstall; + container.appendChild(btn); +} +2. src/components/Layout/TopBar.jsx (copie-colle tout) import React, { useEffect, useMemo, useState } from "react"; import { useAuth } from "../../auth/AuthContext"; import { registerUser } from "../../api/client"; import AuthToast from "../Auth/AuthToast"; +// Import pour le bouton PWA +import { addPwaInstallButton } from '../../pwaInstall'; + const THEME_LABELS = { dark: "Dark", blue: "Blue", light: "Light" }; const LAST_SIGNUP_KEY = "sociowire:lastSignup"; @@ -33,9 +82,6 @@ function readLastSignup() { } function parseMergedParams() { - // Support both: - // - /?verified=1&email=... - // - /#/something?verified=1&email=... const search = window.location.search || ""; const hash = window.location.hash || ""; @@ -97,22 +143,18 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { setMode(nextMode); setShowAuth(true); setSignupError(""); - // keep signupInfo (so verify/signup notice stays visible) }; const closeModal = () => { setShowAuth(false); setLoginPass(""); setSignupError(""); - // keep signupInfo }; - // Close auth modal automatically when logged in useEffect(() => { if (authenticated) setShowAuth(false); }, [authenticated]); - /* SW_URL_NOTICE:BEGIN */ useEffect(() => { try { const { get, qs, hs, hash } = parseMergedParams(); @@ -141,7 +183,7 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { if (truthyParam(verified)) { const who = (email || uname || last?.email || last?.username || "").trim(); - setSignupInfo(`✅ Email confirmé${who ? ` (${who})` : ""}. Tu peux te connecter.`); + setSignupInfo(`✅ Email confirmé\( {who ? ` ( \){who})` : ""}. Tu peux te connecter.`); setMode("login"); setShowAuth(true); @@ -149,7 +191,7 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { if (prefill) setLoginUser(prefill); } else if (truthyParam(signup)) { const who = (email || uname || last?.email || last?.username || "").trim(); - setSignupInfo(`✅ Compte créé${who ? ` (${who})` : ""}. Vérifie tes emails (et le spam), puis connecte-toi.`); + setSignupInfo(`✅ Compte créé\( {who ? ` ( \){who})` : ""}. Vérifie tes emails (et le spam), puis connecte-toi.`); setMode("login"); setShowAuth(true); @@ -164,7 +206,6 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { } } - // clean URL (remove params without reload) — both search and hash query const touched = qs.has("verified") || qs.has("email_verified") || qs.has("emailVerified") || qs.has("signup") || qs.has("notice") || hs.has("verified") || hs.has("email_verified") || hs.has("emailVerified") || hs.has("signup") || hs.has("notice"); @@ -178,7 +219,14 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { // ignore } }, []); - /* SW_URL_NOTICE:END */ + + // Ajoute le bouton PWA "Installer" en haut à côté des thèmes + useEffect(() => { + const container = document.getElementById('pwa-install-container'); + if (container) { + addPwaInstallButton(container); + } + }, []); const handleLoginSubmit = async (e) => { e.preventDefault(); @@ -209,7 +257,6 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { lastName: lastName.trim(), }); - // Remember for the "verified" return try { localStorage.setItem(LAST_SIGNUP_KEY, JSON.stringify({ username: u, email: em })); } catch {} @@ -265,7 +312,7 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { - {/* Theme dots UNDER the brand (prevents topbar wrapping / overflow) */} + {/* Theme dots + BOUTON INSTALL PWA */}
{["dark", "blue", "light"].map((t) => ( @@ -280,6 +327,9 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { ))}
+ + {/* BOUTON INSTALL PWA ici en haut */} +
@@ -306,7 +356,6 @@ export default function TopBar({ theme = "dark", onChangeTheme }) { )} - {/* Single button: Logon / Logoff (same spot, same style) */}