start theme implementation
This commit is contained in:
parent
b4e0d0fa3d
commit
c553ff14da
@ -10,6 +10,7 @@ import {ToastContainer} from "react-toastify";
|
||||
|
||||
import './App.css'
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
import {ThemeProvider} from "./hooks/useTheme.jsx";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
@ -82,7 +83,9 @@ function App() {
|
||||
console.log('render')
|
||||
|
||||
return <KeycloakContextProvider>
|
||||
<RouterProvider router={router}/>
|
||||
<ThemeProvider>
|
||||
<RouterProvider router={router}/>
|
||||
</ThemeProvider>
|
||||
</KeycloakContextProvider>;
|
||||
}
|
||||
|
||||
|
||||
@ -1,38 +1,53 @@
|
||||
import LogoIcon from '../assets/FFSSAF-bord-blanc-fond-transparent.webp'
|
||||
import './Nav.css'
|
||||
// import './Nav.css'
|
||||
import {NavLink} from "react-router-dom";
|
||||
import {useAuth} from "../hooks/useAuth.jsx";
|
||||
import {login, logout} from "../utils/auth.js";
|
||||
import {ThemeCss, useTheme} from "../hooks/useTheme.jsx";
|
||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||
import {faMoon, faSun} from "@fortawesome/free-regular-svg-icons";
|
||||
|
||||
const themeSwitcherVariant = {
|
||||
light: "outline-primary bg-light",
|
||||
dark: "outline-light bg-dark"
|
||||
};
|
||||
|
||||
export function Nav() {
|
||||
const {theme} = useTheme();
|
||||
|
||||
return <nav className="navbar navbar-light navbar-expand-md bg-body-tertiary " id="main-navbar">
|
||||
<div className="container-fluid">
|
||||
<a className="navbar-brand" href="/">
|
||||
<img className="logo" src={LogoIcon} alt="logo"/>
|
||||
FFSAF Intra
|
||||
</a>
|
||||
return <>
|
||||
<ThemeCss path="./nav"/>
|
||||
<nav className={"navbar navbar-" + theme + " navbar-expand-md bg-body-tertiary bg-" + theme}
|
||||
id="main-navbar">
|
||||
<div className="container-fluid">
|
||||
<a className="navbar-brand" href="/">
|
||||
<img className="logo" src={LogoIcon} alt="logo"/>
|
||||
FFSAF Intra
|
||||
</a>
|
||||
|
||||
<button className="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown"
|
||||
aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div className="collapse navbar-collapse" id="navbarNavDropdown">
|
||||
<div className="collapse-item">
|
||||
<ul className="navbar-nav">
|
||||
<li className="nav-item"><NavLink className="nav-link" to="/">Accueil</NavLink></li>
|
||||
<AdminMenu/>
|
||||
<LoginMenu/>
|
||||
</ul>
|
||||
<button className="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown"
|
||||
aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div className={"collapse navbar-collapse bg-" + theme} id="navbarNavDropdown">
|
||||
<div className="collapse-item">
|
||||
<ul className="navbar-nav">
|
||||
<li className="nav-item"><NavLink className="nav-link" to="/">Accueil</NavLink></li>
|
||||
<AdminMenu/>
|
||||
<LoginMenu/>
|
||||
<li className="nav-item"><ThemeSwitcher/></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
</>
|
||||
}
|
||||
|
||||
function AdminMenu() {
|
||||
const {is_authenticated, userinfo} = useAuth()
|
||||
const {theme} = useTheme();
|
||||
|
||||
if (!is_authenticated || !userinfo?.roles?.includes("federation_admin"))
|
||||
return <></>
|
||||
@ -41,7 +56,7 @@ function AdminMenu() {
|
||||
<div className="nav-link dropdown-toggle" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Administration
|
||||
</div>
|
||||
<ul className="dropdown-menu">
|
||||
<ul className={"dropdown-menu " + themeSwitcherVariant[theme]}>
|
||||
<li className="nav-item"><NavLink className="nav-link" to="/admin/member">Member</NavLink></li>
|
||||
<li className="nav-item"><NavLink className="nav-link" to="/admin/b">B</NavLink></li>
|
||||
</ul>
|
||||
@ -58,4 +73,10 @@ function LoginMenu() {
|
||||
<div className="nav-link" onClick={() => logout()}>Déconnexion</div>
|
||||
)}
|
||||
</li>
|
||||
}
|
||||
|
||||
function ThemeSwitcher() {
|
||||
const {isLight, toggleTheme} = useTheme()
|
||||
return <div className="nav-link" onClick={toggleTheme}>{isLight ? <FontAwesomeIcon icon={faSun}/> :
|
||||
<FontAwesomeIcon icon={faMoon}/>}</div>
|
||||
}
|
||||
42
src/main/webapp/src/hooks/useTheme.jsx
Normal file
42
src/main/webapp/src/hooks/useTheme.jsx
Normal file
@ -0,0 +1,42 @@
|
||||
import React, {createContext, useContext, useLayoutEffect, useState} from "react";
|
||||
|
||||
export const ThemeContext = createContext({
|
||||
theme: 'light',
|
||||
toggleTheme: () => {
|
||||
}
|
||||
});
|
||||
|
||||
export function useTheme() {
|
||||
const {theme, toggleTheme} = useContext(ThemeContext);
|
||||
return {
|
||||
isLight: theme === 'light',
|
||||
isDark: theme === 'dark',
|
||||
theme,
|
||||
toggleTheme
|
||||
};
|
||||
}
|
||||
|
||||
export function ThemeCss({path}) {
|
||||
const {theme} = useTheme();
|
||||
|
||||
const Light = React.lazy(() => import(path + ".css"));
|
||||
const Dark = React.lazy(() => import(path + ".dark.css"));
|
||||
|
||||
return <>
|
||||
<React.Suspense fallback={<></>}>
|
||||
{theme === "light" && <Light />}
|
||||
{theme === "dark" && <Dark />}
|
||||
</React.Suspense>
|
||||
</>
|
||||
}
|
||||
|
||||
export function ThemeProvider({children}) {
|
||||
const [theme, setTheme] = useState('light');
|
||||
const toggleTheme = () => {
|
||||
setTheme(theme === 'light' ? 'dark' : 'light');
|
||||
}
|
||||
|
||||
return <ThemeContext.Provider value={{theme, toggleTheme}}>
|
||||
{children}
|
||||
</ThemeContext.Provider>
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user