Can toggle dark theme
This commit is contained in:
parent
f93bc704a5
commit
099e517688
@ -1,4 +1,3 @@
|
||||
import { ThemeProvider, createTheme } from "@mui/material/styles";
|
||||
import React from "react";
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
import "./App.css";
|
||||
@ -24,12 +23,6 @@ interface AuthContext {
|
||||
|
||||
const AuthContextK = React.createContext<AuthContext | null>(null);
|
||||
|
||||
const darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: "dark", // TODO : switch back to light
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Core app
|
||||
*/
|
||||
@ -42,37 +35,35 @@ export function App(): React.ReactElement {
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={darkTheme}>
|
||||
<AuthContextK.Provider value={context}>
|
||||
<Routes>
|
||||
<Route path="delete_account" element={<DeleteAccountRoute />} />
|
||||
<AuthContextK.Provider value={context}>
|
||||
<Routes>
|
||||
<Route path="delete_account" element={<DeleteAccountRoute />} />
|
||||
|
||||
{signedIn ? (
|
||||
<Route path="*" element={<BaseAuthenticatedPage />}>
|
||||
<Route path="" element={<FamiliesListRoute />} />
|
||||
<Route path="profile" element={<ProfileRoute />} />
|
||||
<Route path="family/:familyId/*" element={<BaseFamilyRoute />}>
|
||||
<Route path="" element={<FamilyHomeRoute />} />
|
||||
<Route path="*" element={<NotFoundRoute />} />
|
||||
</Route>
|
||||
{signedIn ? (
|
||||
<Route path="*" element={<BaseAuthenticatedPage />}>
|
||||
<Route path="" element={<FamiliesListRoute />} />
|
||||
<Route path="profile" element={<ProfileRoute />} />
|
||||
<Route path="family/:familyId/*" element={<BaseFamilyRoute />}>
|
||||
<Route path="" element={<FamilyHomeRoute />} />
|
||||
<Route path="*" element={<NotFoundRoute />} />
|
||||
</Route>
|
||||
) : (
|
||||
<Route path="*" element={<BaseLoginPage />}>
|
||||
<Route path="" element={<LoginRoute />} />
|
||||
<Route path="oidc_cb" element={<OIDCCbRoute />} />
|
||||
<Route path="new-account" element={<NewAccountRoute />} />
|
||||
<Route
|
||||
path="password_forgotten"
|
||||
element={<PasswordForgottenRoute />}
|
||||
/>
|
||||
<Route path="reset_password" element={<ResetPasswordRoute />} />
|
||||
<Route path="*" element={<NotFoundRoute />} />
|
||||
</Route>
|
||||
)}
|
||||
</Routes>
|
||||
</AuthContextK.Provider>
|
||||
</ThemeProvider>
|
||||
<Route path="*" element={<NotFoundRoute />} />
|
||||
</Route>
|
||||
) : (
|
||||
<Route path="*" element={<BaseLoginPage />}>
|
||||
<Route path="" element={<LoginRoute />} />
|
||||
<Route path="oidc_cb" element={<OIDCCbRoute />} />
|
||||
<Route path="new-account" element={<NewAccountRoute />} />
|
||||
<Route
|
||||
path="password_forgotten"
|
||||
element={<PasswordForgottenRoute />}
|
||||
/>
|
||||
<Route path="reset_password" element={<ResetPasswordRoute />} />
|
||||
<Route path="*" element={<NotFoundRoute />} />
|
||||
</Route>
|
||||
)}
|
||||
</Routes>
|
||||
</AuthContextK.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
|
50
geneit_app/src/context_providers/DarkThemeProvider.tsx
Normal file
50
geneit_app/src/context_providers/DarkThemeProvider.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import { ThemeProvider, createTheme } from "@mui/material/styles";
|
||||
import React from "react";
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
const localStorageKey = "dark-theme";
|
||||
|
||||
const darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: "dark",
|
||||
},
|
||||
});
|
||||
|
||||
const lightTheme = createTheme({
|
||||
palette: {
|
||||
mode: "light",
|
||||
},
|
||||
});
|
||||
|
||||
interface DarkThemeContext {
|
||||
enabled: boolean;
|
||||
setEnabled: (enabled: boolean) => void;
|
||||
}
|
||||
|
||||
const DarkThemeContextK = React.createContext<DarkThemeContext | null>(null);
|
||||
|
||||
export function DarkThemeProvider(p: PropsWithChildren): React.ReactElement {
|
||||
const [enabled, setEnabled] = React.useState(
|
||||
localStorage.getItem(localStorageKey) === "true"
|
||||
);
|
||||
|
||||
return (
|
||||
<DarkThemeContextK.Provider
|
||||
value={{
|
||||
enabled: enabled,
|
||||
setEnabled(enabled) {
|
||||
localStorage.setItem(localStorageKey, enabled ? "true" : "false");
|
||||
setEnabled(enabled);
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ThemeProvider theme={enabled ? darkTheme : lightTheme}>
|
||||
{p.children}
|
||||
</ThemeProvider>
|
||||
</DarkThemeContextK.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useDarkTheme(): DarkThemeContext {
|
||||
return React.useContext(DarkThemeContextK)!;
|
||||
}
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import { TextInputDialog } from "./TextInputDialog";
|
||||
import { ServerApi } from "../api/ServerApi";
|
||||
import { FamilyApi } from "../api/FamilyApi";
|
||||
import { useAlert } from "../widgets/AlertDialogProvider";
|
||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
||||
|
||||
export function CreateFamilyDialog(p: {
|
||||
open: boolean;
|
||||
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import { TextInputDialog } from "./TextInputDialog";
|
||||
import { ServerApi } from "../api/ServerApi";
|
||||
import { FamilyApi, JoinFamilyResult } from "../api/FamilyApi";
|
||||
import { useAlert } from "../widgets/AlertDialogProvider";
|
||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
||||
|
||||
export function JoinFamilyDialog(p: {
|
||||
open: boolean;
|
||||
|
@ -11,10 +11,11 @@ import "@fontsource/roboto/400.css";
|
||||
import "@fontsource/roboto/500.css";
|
||||
import "@fontsource/roboto/700.css";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { ConfirmDialogProvider } from "./widgets/ConfirmDialogProvider";
|
||||
import { AlertDialogProvider } from "./widgets/AlertDialogProvider";
|
||||
import { ConfirmDialogProvider } from "./context_providers/ConfirmDialogProvider";
|
||||
import { AlertDialogProvider } from "./context_providers/AlertDialogProvider";
|
||||
import { AsyncWidget } from "./widgets/AsyncWidget";
|
||||
import { SnackbarProvider } from "./widgets/SnackbarProvider";
|
||||
import { SnackbarProvider } from "./context_providers/SnackbarProvider";
|
||||
import { DarkThemeProvider } from "./context_providers/DarkThemeProvider";
|
||||
|
||||
async function init() {
|
||||
try {
|
||||
@ -25,20 +26,22 @@ async function init() {
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<AlertDialogProvider>
|
||||
<ConfirmDialogProvider>
|
||||
<SnackbarProvider>
|
||||
<div style={{ height: "100vh" }}>
|
||||
<AsyncWidget
|
||||
loadKey={1}
|
||||
load={async () => await ServerApi.LoadConfig()}
|
||||
errMsg="Echec de la connexion au serveur pour la récupération de la configuration statique !"
|
||||
build={() => <App />}
|
||||
/>
|
||||
</div>
|
||||
</SnackbarProvider>
|
||||
</ConfirmDialogProvider>
|
||||
</AlertDialogProvider>
|
||||
<DarkThemeProvider>
|
||||
<AlertDialogProvider>
|
||||
<ConfirmDialogProvider>
|
||||
<SnackbarProvider>
|
||||
<div style={{ height: "100vh" }}>
|
||||
<AsyncWidget
|
||||
loadKey={1}
|
||||
load={async () => await ServerApi.LoadConfig()}
|
||||
errMsg="Echec de la connexion au serveur pour la récupération de la configuration statique !"
|
||||
build={() => <App />}
|
||||
/>
|
||||
</div>
|
||||
</SnackbarProvider>
|
||||
</ConfirmDialogProvider>
|
||||
</AlertDialogProvider>
|
||||
</DarkThemeProvider>
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
@ -3,9 +3,9 @@ import React from "react";
|
||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||
import { AuthApi } from "../api/AuthApi";
|
||||
import { DeleteAccountTokenInfo, UserApi } from "../api/UserApi";
|
||||
import { useAlert } from "../widgets/AlertDialogProvider";
|
||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||
import { useConfirm } from "../widgets/ConfirmDialogProvider";
|
||||
import { useConfirm } from "../context_providers/ConfirmDialogProvider";
|
||||
|
||||
export function DeleteAccountRoute(): React.ReactElement {
|
||||
const alert = useAlert();
|
||||
|
@ -14,9 +14,9 @@ import React from "react";
|
||||
import { Family, FamilyApi } from "../api/FamilyApi";
|
||||
import { CreateFamilyDialog } from "../dialogs/CreateFamilyDialog";
|
||||
import { JoinFamilyDialog } from "../dialogs/JoinFamilyDialog";
|
||||
import { useAlert } from "../widgets/AlertDialogProvider";
|
||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||
import { useConfirm } from "../widgets/ConfirmDialogProvider";
|
||||
import { useConfirm } from "../context_providers/ConfirmDialogProvider";
|
||||
import { RouterLink } from "../widgets/RouterLink";
|
||||
import { TimeWidget } from "../widgets/TimeWidget";
|
||||
|
||||
|
@ -13,9 +13,9 @@ import {
|
||||
import React from "react";
|
||||
import { ServerApi } from "../api/ServerApi";
|
||||
import { ReplacePasswordResponse, User, UserApi } from "../api/UserApi";
|
||||
import { useAlert } from "../widgets/AlertDialogProvider";
|
||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
||||
import { useUser } from "../widgets/BaseAuthenticatedPage";
|
||||
import { useConfirm } from "../widgets/ConfirmDialogProvider";
|
||||
import { useConfirm } from "../context_providers/ConfirmDialogProvider";
|
||||
import { PasswordInput } from "../widgets/PasswordInput";
|
||||
import { formatDate } from "../widgets/TimeWidget";
|
||||
|
||||
|
@ -14,6 +14,7 @@ import { AuthApi } from "../api/AuthApi";
|
||||
import { User, UserApi } from "../api/UserApi";
|
||||
import { AsyncWidget } from "./AsyncWidget";
|
||||
import { RouterLink } from "./RouterLink";
|
||||
import { DarkThemeButton } from "./DarkThemeButton";
|
||||
|
||||
interface UserContext {
|
||||
user: User;
|
||||
@ -90,6 +91,8 @@ export function BaseAuthenticatedPage(): React.ReactElement {
|
||||
</Typography>
|
||||
|
||||
<div>
|
||||
<DarkThemeButton />
|
||||
|
||||
<Button size="large" color="inherit">
|
||||
{user!.name}
|
||||
</Button>
|
||||
|
@ -27,9 +27,9 @@ import { Outlet, useLocation, useParams } from "react-router-dom";
|
||||
import { Family, FamilyApi } from "../api/FamilyApi";
|
||||
import { AsyncWidget } from "./AsyncWidget";
|
||||
import { RouterLink } from "./RouterLink";
|
||||
import { useSnackbar } from "./SnackbarProvider";
|
||||
import { useConfirm } from "./ConfirmDialogProvider";
|
||||
import { useAlert } from "./AlertDialogProvider";
|
||||
import { useSnackbar } from "../context_providers/SnackbarProvider";
|
||||
import { useConfirm } from "../context_providers/ConfirmDialogProvider";
|
||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
||||
|
||||
interface FamilyContext {
|
||||
family: Family;
|
||||
|
@ -8,6 +8,7 @@ import Paper from "@mui/material/Paper";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import * as React from "react";
|
||||
import { Link, Outlet } from "react-router-dom";
|
||||
import { DarkThemeButton } from "./DarkThemeButton";
|
||||
|
||||
function Copyright(props: any) {
|
||||
return (
|
||||
@ -64,6 +65,10 @@ export function BaseLoginPage() {
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div style={{ position: "absolute", right: "10px", top: "5px" }}>
|
||||
<DarkThemeButton />
|
||||
</div>
|
||||
|
||||
<Avatar sx={{ m: 1, bgcolor: "secondary.main" }}>
|
||||
<Icon path={mdiFamilyTree} size={1} />
|
||||
</Avatar>
|
||||
|
19
geneit_app/src/widgets/DarkThemeButton.tsx
Normal file
19
geneit_app/src/widgets/DarkThemeButton.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import Brightness7Icon from "@mui/icons-material/Brightness7";
|
||||
import DarkModeIcon from "@mui/icons-material/DarkMode";
|
||||
import { IconButton, Tooltip } from "@mui/material";
|
||||
import { useDarkTheme } from "../context_providers/DarkThemeProvider";
|
||||
|
||||
export function DarkThemeButton(): React.ReactElement {
|
||||
const darkTheme = useDarkTheme();
|
||||
|
||||
return (
|
||||
<Tooltip title="Activer / désactiver le mode sombre">
|
||||
<IconButton
|
||||
onClick={() => darkTheme.setEnabled(!darkTheme.enabled)}
|
||||
style={{ color: "inherit" }}
|
||||
>
|
||||
{!darkTheme.enabled ? <DarkModeIcon /> : <Brightness7Icon />}
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user