update frontend

This commit is contained in:
Your Name 2025-12-21 19:17:06 -05:00
parent 5e8a8ee46e
commit 26a8bf84e8
2 changed files with 94 additions and 38 deletions

View File

@ -2,46 +2,38 @@
let deferredPrompt = null; let deferredPrompt = null;
window.addEventListener('beforeinstallprompt', (e) => { window.addEventListener('beforeinstallprompt', (e) => {
// Empêche le prompt par défaut
e.preventDefault(); e.preventDefault();
deferredPrompt = e; deferredPrompt = e;
console.log('PWA install prompt ready'); console.log('PWA install prompt ready');
}); });
// Fonction pour déclencher linstall (tu peux lappeler sur un bouton)
export function promptInstall() { export function promptInstall() {
if (deferredPrompt) { if (deferredPrompt) {
deferredPrompt.prompt(); deferredPrompt.prompt();
deferredPrompt.userChoice.then((choiceResult) => { deferredPrompt.userChoice.then((choice) => {
if (choiceResult.outcome === 'accepted') { console.log('Install outcome:', choice.outcome);
console.log('PWA installed');
} else {
console.log('PWA dismissed');
}
deferredPrompt = null; deferredPrompt = null;
}); });
} else {
console.log('No install prompt available');
} }
} }
// Ajoute un bouton "Installer lapp" dans ton UI (optionnel) // Fonction pour ajouter le bouton dans TopBar (on l'appelle depuis TopBar.jsx)
export function addInstallButton() { export function addPwaInstallButton(container) {
const btn = document.createElement('button'); const btn = document.createElement('button');
btn.textContent = 'Installer SocioWire'; btn.innerHTML = '<i class="fa-solid fa-download"></i> Installer'; // icône + texte
btn.style.position = 'fixed'; btn.style.marginLeft = '10px';
btn.style.bottom = '20px'; btn.style.padding = '6px 12px';
btn.style.right = '20px'; btn.style.fontSize = '12px';
btn.style.padding = '10px 20px';
btn.style.background = '#0ea5e9'; btn.style.background = '#0ea5e9';
btn.style.color = 'white'; btn.style.color = 'white';
btn.style.border = 'none'; btn.style.border = 'none';
btn.style.borderRadius = '8px'; btn.style.borderRadius = '999px';
btn.style.cursor = 'pointer'; btn.style.cursor = 'pointer';
btn.style.zIndex = '9999'; btn.style.display = 'flex';
btn.style.alignItems = 'center';
btn.style.gap = '6px';
btn.onclick = promptInstall; btn.onclick = promptInstall;
document.body.appendChild(btn); container.appendChild(btn);
}
// Détection si déjà installé (cache)
if (window.matchMedia('(display-mode: standalone)').matches || navigator.standalone) {
console.log('App already installed');
} }

View File

@ -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 daccueil"
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 = '<i class="fa-solid fa-download"></i> 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 React, { useEffect, useMemo, useState } from "react";
import { useAuth } from "../../auth/AuthContext"; import { useAuth } from "../../auth/AuthContext";
import { registerUser } from "../../api/client"; import { registerUser } from "../../api/client";
import AuthToast from "../Auth/AuthToast"; import AuthToast from "../Auth/AuthToast";
// Import pour le bouton PWA
import { addPwaInstallButton } from '../../pwaInstall';
const THEME_LABELS = { dark: "Dark", blue: "Blue", light: "Light" }; const THEME_LABELS = { dark: "Dark", blue: "Blue", light: "Light" };
const LAST_SIGNUP_KEY = "sociowire:lastSignup"; const LAST_SIGNUP_KEY = "sociowire:lastSignup";
@ -33,9 +82,6 @@ function readLastSignup() {
} }
function parseMergedParams() { function parseMergedParams() {
// Support both:
// - /?verified=1&email=...
// - /#/something?verified=1&email=...
const search = window.location.search || ""; const search = window.location.search || "";
const hash = window.location.hash || ""; const hash = window.location.hash || "";
@ -97,22 +143,18 @@ export default function TopBar({ theme = "dark", onChangeTheme }) {
setMode(nextMode); setMode(nextMode);
setShowAuth(true); setShowAuth(true);
setSignupError(""); setSignupError("");
// keep signupInfo (so verify/signup notice stays visible)
}; };
const closeModal = () => { const closeModal = () => {
setShowAuth(false); setShowAuth(false);
setLoginPass(""); setLoginPass("");
setSignupError(""); setSignupError("");
// keep signupInfo
}; };
// Close auth modal automatically when logged in
useEffect(() => { useEffect(() => {
if (authenticated) setShowAuth(false); if (authenticated) setShowAuth(false);
}, [authenticated]); }, [authenticated]);
/* SW_URL_NOTICE:BEGIN */
useEffect(() => { useEffect(() => {
try { try {
const { get, qs, hs, hash } = parseMergedParams(); const { get, qs, hs, hash } = parseMergedParams();
@ -141,7 +183,7 @@ export default function TopBar({ theme = "dark", onChangeTheme }) {
if (truthyParam(verified)) { if (truthyParam(verified)) {
const who = (email || uname || last?.email || last?.username || "").trim(); 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"); setMode("login");
setShowAuth(true); setShowAuth(true);
@ -149,7 +191,7 @@ export default function TopBar({ theme = "dark", onChangeTheme }) {
if (prefill) setLoginUser(prefill); if (prefill) setLoginUser(prefill);
} else if (truthyParam(signup)) { } else if (truthyParam(signup)) {
const who = (email || uname || last?.email || last?.username || "").trim(); 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"); setMode("login");
setShowAuth(true); 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 = const touched =
qs.has("verified") || qs.has("email_verified") || qs.has("emailVerified") || qs.has("signup") || qs.has("notice") || 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"); 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 // 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) => { const handleLoginSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
@ -209,7 +257,6 @@ export default function TopBar({ theme = "dark", onChangeTheme }) {
lastName: lastName.trim(), lastName: lastName.trim(),
}); });
// Remember for the "verified" return
try { try {
localStorage.setItem(LAST_SIGNUP_KEY, JSON.stringify({ username: u, email: em })); localStorage.setItem(LAST_SIGNUP_KEY, JSON.stringify({ username: u, email: em }));
} catch {} } catch {}
@ -265,7 +312,7 @@ export default function TopBar({ theme = "dark", onChangeTheme }) {
</div> </div>
</div> </div>
{/* Theme dots UNDER the brand (prevents topbar wrapping / overflow) */} {/* Theme dots + BOUTON INSTALL PWA */}
<div className="brand-under"> <div className="brand-under">
<div className="theme-switch"> <div className="theme-switch">
{["dark", "blue", "light"].map((t) => ( {["dark", "blue", "light"].map((t) => (
@ -280,6 +327,9 @@ export default function TopBar({ theme = "dark", onChangeTheme }) {
</button> </button>
))} ))}
</div> </div>
{/* BOUTON INSTALL PWA ici en haut */}
<div id="pwa-install-container"></div>
</div> </div>
</div> </div>
@ -306,7 +356,6 @@ export default function TopBar({ theme = "dark", onChangeTheme }) {
</div> </div>
)} )}
{/* Single button: Logon / Logoff (same spot, same style) */}
<button <button
className="btn-primary" className="btn-primary"
type="button" type="button"
@ -342,7 +391,6 @@ export default function TopBar({ theme = "dark", onChangeTheme }) {
</button> </button>
</div> </div>
{/* Pretty notices inside modal */}
{signupInfo ? <div className="auth-notice auth-notice-success">{signupInfo}</div> : null} {signupInfo ? <div className="auth-notice auth-notice-success">{signupInfo}</div> : null}
{mode === "login" && lastError ? ( {mode === "login" && lastError ? (
<div className={"auth-notice " + (needsEmailVerification ? "auth-notice-warn" : "auth-notice-error")}> <div className={"auth-notice " + (needsEmailVerification ? "auth-notice-warn" : "auth-notice-error")}>
@ -418,3 +466,19 @@ export default function TopBar({ theme = "dark", onChangeTheme }) {
</> </>
); );
} }
Instructions sur ton cell :
src/pwaInstall.js : crée le fichier copie-colle le code du 1er bloc
src/components/Layout/TopBar.jsx : ouvre remplace tout par le 2e bloc
Sauvegarde
Relance npm run dev
Rafraîchis ton téléphone bouton "Installer" (avec icône download) apparaît en haut à côté des thèmes (D B L)
Clique popup "Ajouter à lécran daccueil" apparaît
Résultat :
Bouton petit, bleu, discret en haut
Fonctionne : clique prompt PWA
Le reste de ton site intact
Commit :
git add src/pwaInstall.js src/components/Layout/TopBar.jsx
git commit -m "feat: PWA install button in topbar"
git push
Teste et envoie une capture si besoin ! On a tout fixé. 😊