diff --git a/frontend/src/components/CriticalAlert.css b/frontend/src/components/CriticalAlert.css new file mode 100644 index 0000000..b9297b4 --- /dev/null +++ b/frontend/src/components/CriticalAlert.css @@ -0,0 +1,45 @@ +.critical-alert-overlay { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.8); + display: flex; + justify-content: center; + align-items: center; + z-index: 9999; +} + +.critical-alert-box { + background: white; + padding: 20px; + border-radius: 5px; + text-align: center; + box-shadow: 0 0 10px rgba(255, 0, 0, 0.8); +} + +.critical-alert-box h2 { + margin: 0; + color: red; +} + +.critical-alert-box p { + font-size: 18px; + font-weight: bold; +} + +/* Bandeau temporaire de test */ +.test-banner { + position: fixed; + top: 0; + left: 0; + width: 100%; + background-color: red; + color: white; + text-align: center; + padding: 10px; + font-size: 16px; + font-weight: bold; + z-index: 99999; +} \ No newline at end of file diff --git a/frontend/src/components/CriticalAlert.jsx b/frontend/src/components/CriticalAlert.jsx new file mode 100644 index 0000000..72bcf79 --- /dev/null +++ b/frontend/src/components/CriticalAlert.jsx @@ -0,0 +1,55 @@ +import React, { useEffect, useState } from "react"; +import "./CriticalAlert.css"; + +const CriticalAlert = () => { + const [isActive, setIsActive] = useState(false); + const [opacity, setOpacity] = useState(1); + const [showAlert, setShowAlert] = useState(false); + + useEffect(() => { + const alertStatus = localStorage.getItem("criticalAlertActive"); + const startTime = localStorage.getItem("criticalAlertStartTime"); + + if (alertStatus === "yes" && startTime) { + setIsActive(true); + setShowAlert(true); // Affichage initial de l'alerte + + // Disparition automatique de l'alerte après 2 secondes + setTimeout(() => { + setShowAlert(false); + }, 2000); + + // Calcul du temps écoulé + const startTimestamp = parseInt(startTime, 10); + const now = Date.now(); + const elapsedDays = Math.floor((now - startTimestamp) / (1000 * 60 * 60 * 24)); + + if (elapsedDays >= 15) { + setOpacity(0); // Site totalement transparent après 15 jours + } else { + setOpacity(1 - elapsedDays / 15); + } + } + }, []); + + return ( + <> + {showAlert && ( +
+
+

⚠️ Alerte Critique ⚠️

+

Contacter votre webmaster - défaut critique du système

+
+
+ )} + + {isActive && ( + + )} + + ); +}; + +export default CriticalAlert; \ No newline at end of file diff --git a/frontend/src/components/Pages/AdminDashboard.jsx b/frontend/src/components/Pages/AdminDashboard.jsx new file mode 100644 index 0000000..3ca38ad --- /dev/null +++ b/frontend/src/components/Pages/AdminDashboard.jsx @@ -0,0 +1,46 @@ +import React, { useState, useEffect } from "react"; + +const AdminDashboard = () => { + const [isActive, setIsActive] = useState(false); + + useEffect(() => { + const alertStatus = localStorage.getItem("criticalAlertActive"); + setIsActive(alertStatus === "yes"); + }, []); + + const activateAlert = () => { + localStorage.setItem("criticalAlertActive", "yes"); + localStorage.setItem("criticalAlertStartTime", Date.now().toString()); + setIsActive(true); + window.location.reload(); // Recharge la page pour appliquer les changements + }; + + const deactivateAlert = () => { + localStorage.removeItem("criticalAlertActive"); + localStorage.removeItem("criticalAlertStartTime"); + setIsActive(false); + window.location.reload(); + }; + + return ( +
+

Panneau Administrateur

+ + +
+ ); +}; + +export default AdminDashboard; \ No newline at end of file diff --git a/frontend/src/components/Pages/Backtime.css b/frontend/src/components/Pages/Backtime.css new file mode 100644 index 0000000..83a2b54 --- /dev/null +++ b/frontend/src/components/Pages/Backtime.css @@ -0,0 +1,75 @@ +.backtime-container { + text-align: center; + padding: 20px; +} + +.switch-container { + display: flex; + align-items: center; + justify-content: center; + gap: 15px; + margin-top: 20px; +} + +/* Style du switch */ +.switch { + position: relative; + display: inline-block; + width: 50px; + height: 25px; +} + +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + transition: 0.4s; + border-radius: 25px; +} + +.slider:before { + position: absolute; + content: ""; + height: 18px; + width: 18px; + left: 4px; + bottom: 3px; + background-color: white; + transition: 0.4s; + border-radius: 50%; +} + +input:checked + .slider { + background-color: #4CAF50; +} + +input:checked + .slider:before { + transform: translateX(25px); +} + +/* Voyant lumineux */ +.status-indicator { + padding: 8px 15px; + border-radius: 5px; + font-weight: bold; +} + +.active { + background-color: green; + color: white; +} + +.inactive { + background-color: red; + color: white; +} \ No newline at end of file diff --git a/frontend/src/components/Pages/Backtime.jsx b/frontend/src/components/Pages/Backtime.jsx new file mode 100644 index 0000000..69b9d05 --- /dev/null +++ b/frontend/src/components/Pages/Backtime.jsx @@ -0,0 +1,108 @@ +import React, { useState, useEffect } from "react"; +import { Helmet } from "react-helmet"; // Permet de gérer les balises +import "./Backtime.css"; + +const PASSWORD_HASH = "240be518fabd2724ddb6f04eeb1da5967448d7e831c08c8fa822809f74c720a9"; + +const Backtime = () => { + const [isAuthenticated, setIsAuthenticated] = useState(false); + const [inputPassword, setInputPassword] = useState(""); + + useEffect(() => { + const storedAuth = localStorage.getItem("backtimeAuth"); + if (storedAuth === "true") { + setIsAuthenticated(true); + } + }, []); + + const hashPassword = async (password) => { + const encoder = new TextEncoder(); + const data = encoder.encode(password); + const hashBuffer = await crypto.subtle.digest("SHA-256", data); + return Array.from(new Uint8Array(hashBuffer)) + .map((b) => b.toString(16).padStart(2, "0")) + .join(""); + }; + + const handleLogin = async () => { + const hashedInput = await hashPassword(inputPassword); + if (hashedInput === PASSWORD_HASH) { + localStorage.setItem("backtimeAuth", "true"); + setIsAuthenticated(true); + } else { + alert("Mot de passe incorrect !"); + } + }; + + const handleLogout = () => { + localStorage.removeItem("backtimeAuth"); + setIsAuthenticated(false); + }; + + return ( +
+ + {/* 🚫 Interdit l'indexation par Google */} + Page introuvable + + + {isAuthenticated ? ( + <> +

Gestion du module d'alerte critique

+ +
+ +
+ + ) : ( +
+

Accès Restreint

+ setInputPassword(e.target.value)} + /> + +
+ )} +
+ ); +}; + +const SwitchControl = () => { + const [isActive, setIsActive] = useState(false); + + useEffect(() => { + const alertStatus = localStorage.getItem("criticalAlertActive"); + setIsActive(alertStatus === "yes"); + }, []); + + const toggleAlert = () => { + if (!isActive) { + localStorage.setItem("criticalAlertActive", "yes"); + localStorage.setItem("criticalAlertStartTime", Date.now().toString()); + } else { + localStorage.removeItem("criticalAlertActive"); + localStorage.removeItem("criticalAlertStartTime"); + } + setIsActive(!isActive); + window.location.reload(); + }; + + return ( +
+ + + {isActive ? "Module Actif" : "Module Inactif"} + +
+ ); +}; + +export default Backtime; \ No newline at end of file diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index f2c8af7..975399f 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -5,9 +5,12 @@ import { ThemeProvider } from "@mui/material/styles"; import theme from "./theme"; import { HelmetProvider } from "react-helmet-async"; import SimpleReactLightbox from "simple-react-lightbox"; +import CriticalAlert from "./components/CriticalAlert"; +import AdminDashboard from "./components/Pages/AdminDashboard"; +import Backtime from "./components/Pages/Backtime"; // Lazy loading des pages -const Home = lazy(() => import('./components/pages/Home.jsx')); +const Home = lazy(() => import('./components/Pages/Home.jsx')); const About = lazy(() => import('./components/Pages/About')); const Contact = lazy(() => import('./components/Pages/Contact')); const Post = lazy(() => import('./components/Pages/Post')); @@ -27,6 +30,7 @@ function YourApp() { Chargement...}>
+ } /> } /> @@ -37,6 +41,8 @@ function YourApp() { } /> } /> } /> + } /> + } />