Add public mode

This commit is contained in:
Pierre HUBERT 2025-05-02 12:23:49 +02:00
parent 56370ec936
commit f16eeb6e45
8 changed files with 117 additions and 18 deletions

View File

@ -0,0 +1,34 @@
import React, { PropsWithChildren } from "react";
const localStorageKey = "public-mode";
interface PublicModeContext {
enabled: boolean;
setEnabled: (enabled: boolean) => void;
}
const PublicModeContextK = React.createContext<PublicModeContext | null>(null);
export function PublicModeProvider(p: PropsWithChildren): React.ReactElement {
const [enabled, setEnabled] = React.useState(
localStorage.getItem(localStorageKey) !== "false"
);
return (
<PublicModeContextK
value={{
enabled: enabled,
setEnabled(enabled) {
localStorage.setItem(localStorageKey, enabled ? "true" : "false");
setEnabled(enabled);
},
}}
>
{p.children}
</PublicModeContextK>
);
}
export function usePublicMode(): PublicModeContext {
return React.use(PublicModeContextK)!;
}

View File

@ -15,6 +15,7 @@ import { LoadingMessageProvider } from "./hooks/context_providers/LoadingMessage
import { SnackbarProvider } from "./hooks/context_providers/SnackbarProvider.tsx";
import "./index.css";
import { AsyncWidget } from "./widgets/AsyncWidget.tsx";
import { PublicModeProvider } from "./hooks/context_providers/PublicModeProvider.tsx";
createRoot(document.getElementById("root")!).render(
<StrictMode>
@ -24,12 +25,16 @@ createRoot(document.getElementById("root")!).render(
<ConfirmDialogProvider>
<SnackbarProvider>
<LoadingMessageProvider>
<PublicModeProvider>
<AsyncWidget
loadKey={1}
load={async () => { await ServerApi.LoadConfig(); }}
load={async () => {
await ServerApi.LoadConfig();
}}
errMsg="Failed to load static server configuration!"
build={() => <App />}
/>
</PublicModeProvider>
</LoadingMessageProvider>
</SnackbarProvider>
</ConfirmDialogProvider>

View File

@ -13,8 +13,10 @@ import { fmtDateFromTime, time } from "../utils/DateUtils";
import { AmountWidget } from "../widgets/AmountWidget";
import { AsyncWidget } from "../widgets/AsyncWidget";
import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer";
import { usePublicMode } from "../hooks/context_providers/PublicModeProvider";
export function HomeRoute(): React.ReactElement {
const publicMode = usePublicMode().enabled;
const account = useAccounts();
const loadKey = React.useRef(1);
@ -62,6 +64,20 @@ export function HomeRoute(): React.ReactElement {
</Tooltip>
}
>
{publicMode ? (
<Typography
variant="body1"
style={{
textAlign: "center",
flex: 1,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
Dasbhoard is hidden when public mode is enabled.
</Typography>
) : (
<AsyncWidget
ready={global !== undefined}
loadKey={loadKey.current}
@ -69,6 +85,7 @@ export function HomeRoute(): React.ReactElement {
errMsg="Failed to load statistics!"
build={() => <StatsDashboard global={global!} lastYear={lastYear!} />}
/>
)}
</MoneyMgrWebRouteContainer>
);
}

View File

@ -8,6 +8,8 @@ import Paper from "@mui/material/Paper";
import Typography from "@mui/material/Typography";
import { Link, Outlet } from "react-router-dom";
import loginSplashImage from "./mufid-majnun-LVcjYwuHQlg-unsplash.jpg";
import { PublicModeButton } from "./PublicModeButtonWidget";
import { DarkThemeButton } from "./DarkThemeButtonWidget";
function Copyright(props: any): React.ReactElement {
return (
@ -87,6 +89,18 @@ export function BaseLoginPage() {
<Outlet />
<Copyright sx={{ mt: 5 }} style={{ margin: "40px 0px" }} />
<div
style={{
display: "flex",
justifyContent: "center",
width: "100%",
marginTop: "50px",
}}
>
<PublicModeButton />
<DarkThemeButton />
</div>
</Box>
</Grid>
</Grid>

View File

@ -7,9 +7,11 @@ export function DarkThemeButton(): React.ReactElement {
const darkTheme = useDarkTheme();
return (
<Tooltip title="Activer / désactiver le mode sombre">
<Tooltip title="Enable / Disable dark theme">
<IconButton
onClick={() => { darkTheme.setEnabled(!darkTheme.enabled); }}
onClick={() => {
darkTheme.setEnabled(!darkTheme.enabled);
}}
style={{ color: "inherit" }}
>
{!darkTheme.enabled ? <DarkModeIcon /> : <Brightness7Icon />}

View File

@ -14,8 +14,10 @@ import { useAccounts } from "../hooks/AccountsListProvider";
import { AccountWidget } from "./AccountWidget";
import { RouterLink } from "./RouterLink";
import { AmountWidget } from "./AmountWidget";
import { usePublicMode } from "../hooks/context_providers/PublicModeProvider";
export function MoneyNavList(): React.ReactElement {
const publicMode = usePublicMode();
const accounts = useAccounts();
return (
<List
@ -62,7 +64,9 @@ export function MoneyNavList(): React.ReactElement {
<NavLink
key={a.id}
label={a.name}
secondaryLabel={<AmountWidget amount={a.balance} />}
secondaryLabel={
publicMode.enabled ? <></> : <AmountWidget amount={a.balance} />
}
uri={`/account/${a.id}`}
icon={<AccountWidget account={a} />}
/>

View File

@ -9,8 +9,9 @@ import Toolbar from "@mui/material/Toolbar";
import Typography from "@mui/material/Typography";
import * as React from "react";
import { useAuthInfo } from "./BaseAuthenticatedPage";
import { DarkThemeButton } from "./DarkThemeButton";
import { DarkThemeButton } from "./DarkThemeButtonWidget";
import { RouterLink } from "./RouterLink";
import { PublicModeButton } from "./PublicModeButtonWidget";
export function MoneyWebAppBar(p: {
onSignOut: () => void;
@ -41,6 +42,7 @@ export function MoneyWebAppBar(p: {
</Typography>
<div>
<PublicModeButton />
<DarkThemeButton />
<Button size="large" color="inherit">

View File

@ -0,0 +1,21 @@
import PublicIcon from "@mui/icons-material/Public";
import PublicOffIcon from "@mui/icons-material/PublicOff";
import { IconButton, Tooltip } from "@mui/material";
import { usePublicMode } from "../hooks/context_providers/PublicModeProvider";
export function PublicModeButton(): React.ReactElement {
const publicMode = usePublicMode();
return (
<Tooltip title={`${publicMode.enabled ? "Disable" : "Enable"} public mode`}>
<IconButton
onClick={() => {
publicMode.setEnabled(!publicMode.enabled);
}}
style={{ color: "inherit" }}
>
{!publicMode.enabled ? <PublicOffIcon /> : <PublicIcon />}
</IconButton>
</Tooltip>
);
}