chore: add ansible backend docker frontend-prep

This commit is contained in:
2026-01-21 13:05:13 +01:00
parent 5a280b6b01
commit 943fe4de7d
14930 changed files with 2341433 additions and 0 deletions
+232
View File
@@ -0,0 +1,232 @@
import { useState } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { useCart } from "../context/CartContext";
import "./Navbar.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faHome,
faBox,
faShoppingCart,
faTruck,
faClockRotateLeft,
faSignOutAlt,
faBars,
faTimes,
faChevronRight,
} from "@fortawesome/free-solid-svg-icons";
import { faTelegram } from "@fortawesome/free-brands-svg-icons";
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
interface MenuItem {
id: string;
label: string;
icon: IconDefinition;
path: string;
}
function Navbar() {
const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false);
const [isLoggingOut, setIsLoggingOut] = useState<boolean>(false);
const { cartCount } = useCart();
const navigate = useNavigate();
const location = useLocation();
const menuItems: MenuItem[] = [
{
id: "accueil",
label: "Accueil",
icon: faHome,
path: "/user/accueil",
},
{
id: "produits",
label: "Nos Produits",
icon: faBox,
path: "/user/nos-produits",
},
{
id: "panier",
label: "Passer Commande",
icon: faShoppingCart,
path: "/user/panier",
},
{
id: "suivi",
label: "Suivi Livraison",
icon: faTruck,
path: "/user/suivi-livraison",
},
{
id: "historique",
label: "Historique",
icon: faClockRotateLeft,
path: "/user/consultation-historique",
},
];
const toggleMenu = (): void => {
setIsMenuOpen(!isMenuOpen);
};
const closeMenu = (): void => {
setIsMenuOpen(false);
};
const handleNavigation = (path: string): void => {
navigate(path);
closeMenu();
};
const handleLogout = async (): Promise<void> => {
if (isLoggingOut) return;
setIsLoggingOut(true);
console.log("🚪 [LOGOUT] Déconnexion en cours...");
try {
const token = sessionStorage.getItem("admin_token");
if (token) {
try {
const response = await fetch(
"http://localhost:8080/api/v2/admin/auth/logout",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
},
);
if (response.ok) {
console.log("✅ [LOGOUT] Déconnexion backend réussie");
} else {
console.warn("⚠️ [LOGOUT] Erreur backend (ignorée)");
}
} catch (error) {
console.warn(
"⚠️ [LOGOUT] Erreur réseau backend (ignorée):",
error,
);
}
}
sessionStorage.removeItem("admin_token");
sessionStorage.removeItem("admin_username");
console.log("✅ [LOGOUT] SessionStorage nettoyé");
navigate("/login/client", { replace: true });
} catch (error) {
console.error("❌ [LOGOUT] Erreur:", error);
sessionStorage.removeItem("admin_token");
sessionStorage.removeItem("admin_username");
navigate("/login/client", { replace: true });
} finally {
setIsLoggingOut(false);
}
};
const handleTelegram = (): void => {
window.open("https://t.me/milieu_nantais", "_blank");
};
return (
<>
{/* Bouton Toggle */}
<button
className={`sidebar-toggle ${isMenuOpen ? "sidebar-open" : ""}`}
onClick={toggleMenu}
aria-label="Toggle menu"
>
<FontAwesomeIcon icon={isMenuOpen ? faTimes : faBars} />
</button>
{/* Overlay */}
{isMenuOpen && (
<div className="sidebar-overlay" onClick={closeMenu} />
)}
{/* Bouton Panier (flottant en haut à droite) */}
<button
className="cart-button-float"
onClick={() => navigate("/user/panier")}
aria-label="Panier"
>
<FontAwesomeIcon
icon={faShoppingCart}
className="cart-icon-fa"
/>
{cartCount > 0 && (
<span className="cart-count">{cartCount}</span>
)}
</button>
{/* Sidebar */}
<aside className={`sidebar ${isMenuOpen ? "open" : ""}`}>
{/* Header */}
<div className="sidebar-header">
<div className="sidebar-logo">
<div className="logo-icon">
<FontAwesomeIcon icon={faShoppingCart} size="lg" />
</div>
<div className="logo-text">
<h2>Milieu-Nantais</h2>
<p>User Panel</p>
</div>
</div>
</div>
{/* Navigation Menu */}
<nav className="sidebar-nav">
<ul className="menu-list">
{menuItems.map((item) => (
<li key={item.id}>
<button
className={`menu-item ${location.pathname === item.path ? "active" : ""}`}
onClick={() => handleNavigation(item.path)}
disabled={isLoggingOut}
>
<span className="menu-icon">
<FontAwesomeIcon icon={item.icon} />
</span>
<span className="menu-label">
{item.label}
</span>
<FontAwesomeIcon
icon={faChevronRight}
className="menu-arrow"
/>
</button>
</li>
))}
</ul>
</nav>
{/* Footer avec boutons Telegram et déconnexion */}
<div className="sidebar-footer">
<button
className="telegram-button"
onClick={handleTelegram}
disabled={isLoggingOut}
>
<FontAwesomeIcon icon={faTelegram} />
<span>Telegram</span>
</button>
<button
className="logout-button"
onClick={handleLogout}
disabled={isLoggingOut}
>
<FontAwesomeIcon icon={faSignOutAlt} />
<span>
{isLoggingOut ? "Déconnexion..." : "Déconnexion"}
</span>
</button>
</div>
</aside>
</>
);
}
export default Navbar;