Ask user confirmation before leaving an unsaved form
This commit is contained in:
parent
049b9bdd53
commit
1128b5ebd4
@ -1,5 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Route, Routes } from "react-router-dom";
|
import {
|
||||||
|
Route,
|
||||||
|
RouterProvider,
|
||||||
|
Routes,
|
||||||
|
createBrowserRouter,
|
||||||
|
createRoutesFromElements,
|
||||||
|
} from "react-router-dom";
|
||||||
import "./App.css";
|
import "./App.css";
|
||||||
import { AuthApi } from "./api/AuthApi";
|
import { AuthApi } from "./api/AuthApi";
|
||||||
import { DeleteAccountRoute } from "./routes/DeleteAccountRoute";
|
import { DeleteAccountRoute } from "./routes/DeleteAccountRoute";
|
||||||
@ -41,9 +47,9 @@ export function App(): React.ReactElement {
|
|||||||
setSignedIn: (s) => setSignedIn(s),
|
setSignedIn: (s) => setSignedIn(s),
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
const router = createBrowserRouter(
|
||||||
<AuthContextK.Provider value={context}>
|
createRoutesFromElements(
|
||||||
<Routes>
|
<>
|
||||||
<Route path="delete_account" element={<DeleteAccountRoute />} />
|
<Route path="delete_account" element={<DeleteAccountRoute />} />
|
||||||
|
|
||||||
{signedIn ? (
|
{signedIn ? (
|
||||||
@ -80,7 +86,13 @@ export function App(): React.ReactElement {
|
|||||||
<Route path="*" element={<NotFoundRoute />} />
|
<Route path="*" element={<NotFoundRoute />} />
|
||||||
</Route>
|
</Route>
|
||||||
)}
|
)}
|
||||||
</Routes>
|
</>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AuthContextK.Provider value={context}>
|
||||||
|
<RouterProvider router={router} />
|
||||||
</AuthContextK.Provider>
|
</AuthContextK.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import React from "react";
|
|||||||
import { TextInputDialog } from "./TextInputDialog";
|
import { TextInputDialog } from "./TextInputDialog";
|
||||||
import { ServerApi } from "../api/ServerApi";
|
import { ServerApi } from "../api/ServerApi";
|
||||||
import { FamilyApi } from "../api/FamilyApi";
|
import { FamilyApi } from "../api/FamilyApi";
|
||||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
|
||||||
|
|
||||||
export function CreateFamilyDialog(p: {
|
export function CreateFamilyDialog(p: {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
@ -2,7 +2,7 @@ import React from "react";
|
|||||||
import { TextInputDialog } from "./TextInputDialog";
|
import { TextInputDialog } from "./TextInputDialog";
|
||||||
import { ServerApi } from "../api/ServerApi";
|
import { ServerApi } from "../api/ServerApi";
|
||||||
import { FamilyApi, JoinFamilyResult } from "../api/FamilyApi";
|
import { FamilyApi, JoinFamilyResult } from "../api/FamilyApi";
|
||||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
|
||||||
|
|
||||||
export function JoinFamilyDialog(p: {
|
export function JoinFamilyDialog(p: {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
@ -11,11 +11,11 @@ import "@fontsource/roboto/400.css";
|
|||||||
import "@fontsource/roboto/500.css";
|
import "@fontsource/roboto/500.css";
|
||||||
import "@fontsource/roboto/700.css";
|
import "@fontsource/roboto/700.css";
|
||||||
import { BrowserRouter } from "react-router-dom";
|
import { BrowserRouter } from "react-router-dom";
|
||||||
import { ConfirmDialogProvider } from "./context_providers/ConfirmDialogProvider";
|
import { ConfirmDialogProvider } from "./hooks/context_providers/ConfirmDialogProvider";
|
||||||
import { AlertDialogProvider } from "./context_providers/AlertDialogProvider";
|
import { AlertDialogProvider } from "./hooks/context_providers/AlertDialogProvider";
|
||||||
import { AsyncWidget } from "./widgets/AsyncWidget";
|
import { AsyncWidget } from "./widgets/AsyncWidget";
|
||||||
import { SnackbarProvider } from "./context_providers/SnackbarProvider";
|
import { SnackbarProvider } from "./hooks/context_providers/SnackbarProvider";
|
||||||
import { DarkThemeProvider } from "./context_providers/DarkThemeProvider";
|
import { DarkThemeProvider } from "./hooks/context_providers/DarkThemeProvider";
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
try {
|
try {
|
||||||
@ -25,7 +25,6 @@ async function init() {
|
|||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<BrowserRouter>
|
|
||||||
<DarkThemeProvider>
|
<DarkThemeProvider>
|
||||||
<AlertDialogProvider>
|
<AlertDialogProvider>
|
||||||
<ConfirmDialogProvider>
|
<ConfirmDialogProvider>
|
||||||
@ -42,7 +41,6 @@ async function init() {
|
|||||||
</ConfirmDialogProvider>
|
</ConfirmDialogProvider>
|
||||||
</AlertDialogProvider>
|
</AlertDialogProvider>
|
||||||
</DarkThemeProvider>
|
</DarkThemeProvider>
|
||||||
</BrowserRouter>
|
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -3,9 +3,9 @@ import React from "react";
|
|||||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||||
import { AuthApi } from "../api/AuthApi";
|
import { AuthApi } from "../api/AuthApi";
|
||||||
import { DeleteAccountTokenInfo, UserApi } from "../api/UserApi";
|
import { DeleteAccountTokenInfo, UserApi } from "../api/UserApi";
|
||||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
|
||||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||||
import { useConfirm } from "../context_providers/ConfirmDialogProvider";
|
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
|
||||||
|
|
||||||
export function DeleteAccountRoute(): React.ReactElement {
|
export function DeleteAccountRoute(): React.ReactElement {
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
|
@ -14,9 +14,9 @@ import React from "react";
|
|||||||
import { Family, FamilyApi } from "../api/FamilyApi";
|
import { Family, FamilyApi } from "../api/FamilyApi";
|
||||||
import { CreateFamilyDialog } from "../dialogs/CreateFamilyDialog";
|
import { CreateFamilyDialog } from "../dialogs/CreateFamilyDialog";
|
||||||
import { JoinFamilyDialog } from "../dialogs/JoinFamilyDialog";
|
import { JoinFamilyDialog } from "../dialogs/JoinFamilyDialog";
|
||||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
|
||||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||||
import { useConfirm } from "../context_providers/ConfirmDialogProvider";
|
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
|
||||||
import { RouterLink } from "../widgets/RouterLink";
|
import { RouterLink } from "../widgets/RouterLink";
|
||||||
import { TimeWidget } from "../widgets/TimeWidget";
|
import { TimeWidget } from "../widgets/TimeWidget";
|
||||||
|
|
||||||
|
@ -13,9 +13,9 @@ import {
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { ServerApi } from "../api/ServerApi";
|
import { ServerApi } from "../api/ServerApi";
|
||||||
import { ReplacePasswordResponse, User, UserApi } from "../api/UserApi";
|
import { ReplacePasswordResponse, User, UserApi } from "../api/UserApi";
|
||||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
|
||||||
import { useUser } from "../widgets/BaseAuthenticatedPage";
|
import { useUser } from "../widgets/BaseAuthenticatedPage";
|
||||||
import { useConfirm } from "../context_providers/ConfirmDialogProvider";
|
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
|
||||||
import { PasswordInput } from "../widgets/PasswordInput";
|
import { PasswordInput } from "../widgets/PasswordInput";
|
||||||
import { formatDate } from "../widgets/TimeWidget";
|
import { formatDate } from "../widgets/TimeWidget";
|
||||||
|
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
import ClearIcon from "@mui/icons-material/Clear";
|
import ClearIcon from "@mui/icons-material/Clear";
|
||||||
|
import DeleteIcon from "@mui/icons-material/Delete";
|
||||||
|
import EditIcon from "@mui/icons-material/Edit";
|
||||||
import SaveIcon from "@mui/icons-material/Save";
|
import SaveIcon from "@mui/icons-material/Save";
|
||||||
import { Button, Grid, Stack } from "@mui/material";
|
import { Button, Grid, Stack } from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import EditIcon from "@mui/icons-material/Edit";
|
|
||||||
import DeleteIcon from "@mui/icons-material/Delete";
|
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { Member, MemberApi } from "../../api/MemberApi";
|
import { Member, MemberApi } from "../../api/MemberApi";
|
||||||
import { ServerApi } from "../../api/ServerApi";
|
import { ServerApi } from "../../api/ServerApi";
|
||||||
import { useAlert } from "../../context_providers/AlertDialogProvider";
|
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
|
||||||
import { useConfirm } from "../../context_providers/ConfirmDialogProvider";
|
import { useConfirm } from "../../hooks/context_providers/ConfirmDialogProvider";
|
||||||
|
import { useSnackbar } from "../../hooks/context_providers/SnackbarProvider";
|
||||||
|
import { AsyncWidget } from "../../widgets/AsyncWidget";
|
||||||
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
||||||
|
import { ConfirmLeaveWithoutSaveDialog } from "../../widgets/ConfirmLeaveWithoutSaveDialog";
|
||||||
import { FamilyPageTitle } from "../../widgets/FamilyPageTitle";
|
import { FamilyPageTitle } from "../../widgets/FamilyPageTitle";
|
||||||
import { PropEdit } from "../../widgets/PropEdit";
|
import { PropEdit } from "../../widgets/PropEdit";
|
||||||
import { PropertiesBox } from "../../widgets/PropertiesBox";
|
import { PropertiesBox } from "../../widgets/PropertiesBox";
|
||||||
import { SexSelection } from "../../widgets/SexSelection";
|
import { SexSelection } from "../../widgets/SexSelection";
|
||||||
import { useSnackbar } from "../../context_providers/SnackbarProvider";
|
|
||||||
import { AsyncWidget } from "../../widgets/AsyncWidget";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new member route
|
* Create a new member route
|
||||||
@ -24,6 +25,7 @@ export function FamilyCreateMemberRoute(): React.ReactElement {
|
|||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
const snackbar = useSnackbar();
|
const snackbar = useSnackbar();
|
||||||
|
|
||||||
|
const [shouldQuit, setShouldQuit] = React.useState(false);
|
||||||
const n = useNavigate();
|
const n = useNavigate();
|
||||||
const family = useFamily();
|
const family = useFamily();
|
||||||
|
|
||||||
@ -33,6 +35,7 @@ export function FamilyCreateMemberRoute(): React.ReactElement {
|
|||||||
|
|
||||||
// TODO : trigger update
|
// TODO : trigger update
|
||||||
|
|
||||||
|
setShouldQuit(true);
|
||||||
n(family.family.URL(`member/${r.id}`));
|
n(family.family.URL(`member/${r.id}`));
|
||||||
snackbar(`La fiche pour ${r.fullName} a été créée avec succès !`);
|
snackbar(`La fiche pour ${r.fullName} a été créée avec succès !`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -41,13 +44,19 @@ export function FamilyCreateMemberRoute(): React.ReactElement {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
setShouldQuit(true);
|
||||||
|
n(family.family.URL("members"));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MemberPage
|
<MemberPage
|
||||||
member={Member.New(family.family.family_id)}
|
member={Member.New(family.family.family_id)}
|
||||||
creating={true}
|
creating={true}
|
||||||
editing={true}
|
editing={true}
|
||||||
onCancel={() => n(family.family.URL("members"))}
|
onCancel={cancel}
|
||||||
onSave={create}
|
onSave={create}
|
||||||
|
shouldAllowLeaving={shouldQuit}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -118,6 +127,8 @@ export function FamilyEditMemberRoute(): React.ReactElement {
|
|||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
const snackbar = useSnackbar();
|
const snackbar = useSnackbar();
|
||||||
|
|
||||||
|
const [shouldQuit, setShouldQuit] = React.useState(false);
|
||||||
|
|
||||||
const family = useFamily();
|
const family = useFamily();
|
||||||
const { memberId } = useParams();
|
const { memberId } = useParams();
|
||||||
|
|
||||||
@ -126,6 +137,11 @@ export function FamilyEditMemberRoute(): React.ReactElement {
|
|||||||
setMember(await MemberApi.GetSingle(family.familyId, Number(memberId)));
|
setMember(await MemberApi.GetSingle(family.familyId, Number(memberId)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
setShouldQuit(true);
|
||||||
|
n(family.family.URL(`member/${member!.id}`));
|
||||||
|
};
|
||||||
|
|
||||||
const save = async (m: Member) => {
|
const save = async (m: Member) => {
|
||||||
try {
|
try {
|
||||||
await MemberApi.Update(m);
|
await MemberApi.Update(m);
|
||||||
@ -134,6 +150,7 @@ export function FamilyEditMemberRoute(): React.ReactElement {
|
|||||||
|
|
||||||
// TODO : update family hook info
|
// TODO : update family hook info
|
||||||
|
|
||||||
|
setShouldQuit(true);
|
||||||
n(family.family.URL(`member/${member!.id}`));
|
n(family.family.URL(`member/${member!.id}`));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@ -151,8 +168,9 @@ export function FamilyEditMemberRoute(): React.ReactElement {
|
|||||||
member={member!}
|
member={member!}
|
||||||
creating={false}
|
creating={false}
|
||||||
editing={true}
|
editing={true}
|
||||||
onCancel={() => n(family.family.URL(`member/${member!.id}`))}
|
onCancel={cancel}
|
||||||
onSave={save}
|
onSave={save}
|
||||||
|
shouldAllowLeaving={shouldQuit}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -163,6 +181,7 @@ export function MemberPage(p: {
|
|||||||
member: Member;
|
member: Member;
|
||||||
editing: boolean;
|
editing: boolean;
|
||||||
creating: boolean;
|
creating: boolean;
|
||||||
|
shouldAllowLeaving?: boolean;
|
||||||
onCancel?: () => void;
|
onCancel?: () => void;
|
||||||
onSave?: (m: Member) => void;
|
onSave?: (m: Member) => void;
|
||||||
onRequestEdit?: () => void;
|
onRequestEdit?: () => void;
|
||||||
@ -170,7 +189,6 @@ export function MemberPage(p: {
|
|||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
const confirm = useConfirm();
|
const confirm = useConfirm();
|
||||||
|
|
||||||
// TODO : add confirmation when leaving page https://dev.to/bangash1996/detecting-user-leaving-page-with-react-router-dom-v602-33ni
|
|
||||||
const [changed, setChanged] = React.useState(false);
|
const [changed, setChanged] = React.useState(false);
|
||||||
const [member, setMember] = React.useState(structuredClone(p.member));
|
const [member, setMember] = React.useState(structuredClone(p.member));
|
||||||
|
|
||||||
@ -198,6 +216,9 @@ export function MemberPage(p: {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ maxWidth: "2000px", margin: "auto" }}>
|
<div style={{ maxWidth: "2000px", margin: "auto" }}>
|
||||||
|
<ConfirmLeaveWithoutSaveDialog
|
||||||
|
shouldBlock={changed && p.shouldAllowLeaving !== true}
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
@ -12,8 +12,8 @@ import React from "react";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { FamilyApi } from "../../api/FamilyApi";
|
import { FamilyApi } from "../../api/FamilyApi";
|
||||||
import { ServerApi } from "../../api/ServerApi";
|
import { ServerApi } from "../../api/ServerApi";
|
||||||
import { useAlert } from "../../context_providers/AlertDialogProvider";
|
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
|
||||||
import { useConfirm } from "../../context_providers/ConfirmDialogProvider";
|
import { useConfirm } from "../../hooks/context_providers/ConfirmDialogProvider";
|
||||||
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
||||||
import { formatDate } from "../../widgets/TimeWidget";
|
import { formatDate } from "../../widgets/TimeWidget";
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ import {
|
|||||||
} from "@mui/x-data-grid";
|
} from "@mui/x-data-grid";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FamilyApi, FamilyUser } from "../../api/FamilyApi";
|
import { FamilyApi, FamilyUser } from "../../api/FamilyApi";
|
||||||
import { useAlert } from "../../context_providers/AlertDialogProvider";
|
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
|
||||||
import { useConfirm } from "../../context_providers/ConfirmDialogProvider";
|
import { useConfirm } from "../../hooks/context_providers/ConfirmDialogProvider";
|
||||||
import { AsyncWidget } from "../../widgets/AsyncWidget";
|
import { AsyncWidget } from "../../widgets/AsyncWidget";
|
||||||
import { useUser } from "../../widgets/BaseAuthenticatedPage";
|
import { useUser } from "../../widgets/BaseAuthenticatedPage";
|
||||||
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
import { useFamily } from "../../widgets/BaseFamilyRoute";
|
||||||
|
@ -27,9 +27,9 @@ import { Outlet, useLocation, useParams } from "react-router-dom";
|
|||||||
import { Family, FamilyApi } from "../api/FamilyApi";
|
import { Family, FamilyApi } from "../api/FamilyApi";
|
||||||
import { AsyncWidget } from "./AsyncWidget";
|
import { AsyncWidget } from "./AsyncWidget";
|
||||||
import { RouterLink } from "./RouterLink";
|
import { RouterLink } from "./RouterLink";
|
||||||
import { useSnackbar } from "../context_providers/SnackbarProvider";
|
import { useSnackbar } from "../hooks/context_providers/SnackbarProvider";
|
||||||
import { useConfirm } from "../context_providers/ConfirmDialogProvider";
|
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
|
||||||
import { useAlert } from "../context_providers/AlertDialogProvider";
|
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
|
||||||
|
|
||||||
interface FamilyContext {
|
interface FamilyContext {
|
||||||
family: Family;
|
family: Family;
|
||||||
|
59
geneit_app/src/widgets/ConfirmLeaveWithoutSaveDialog.tsx
Normal file
59
geneit_app/src/widgets/ConfirmLeaveWithoutSaveDialog.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// https://github.com/remix-run/react-router/blob/main/examples/navigation-blocking/src/app.tsx
|
||||||
|
// https://stackoverflow.com/questions/75135147/react-router-dom-v6-useblocker
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@mui/material";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { unstable_useBlocker as useBlocker } from "react-router-dom";
|
||||||
|
|
||||||
|
export function ConfirmLeaveWithoutSaveDialog(p: {
|
||||||
|
shouldBlock: boolean;
|
||||||
|
}): React.ReactElement {
|
||||||
|
let blocker = useBlocker(p.shouldBlock);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (blocker.state === "blocked" && !p.shouldBlock) {
|
||||||
|
blocker.proceed();
|
||||||
|
}
|
||||||
|
}, [blocker, p.shouldBlock]);
|
||||||
|
|
||||||
|
const cancelNavigation = () => {
|
||||||
|
blocker.reset?.();
|
||||||
|
};
|
||||||
|
|
||||||
|
const confirmNavigation = () => {
|
||||||
|
blocker.proceed?.();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open={blocker.state === "blocked"}
|
||||||
|
onClose={cancelNavigation}
|
||||||
|
aria-labelledby="alert-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
>
|
||||||
|
<DialogTitle id="alert-dialog-title">
|
||||||
|
Quitter sans enregistrer ?
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="alert-dialog-description">
|
||||||
|
Voulez-vous vraiment quitter cette page sans enregistrer vos
|
||||||
|
modifications ?
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={confirmNavigation as any}>Quitter la page</Button>
|
||||||
|
<Button onClick={cancelNavigation as any} autoFocus>
|
||||||
|
Rester sur la page
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import Brightness7Icon from "@mui/icons-material/Brightness7";
|
import Brightness7Icon from "@mui/icons-material/Brightness7";
|
||||||
import DarkModeIcon from "@mui/icons-material/DarkMode";
|
import DarkModeIcon from "@mui/icons-material/DarkMode";
|
||||||
import { IconButton, Tooltip } from "@mui/material";
|
import { IconButton, Tooltip } from "@mui/material";
|
||||||
import { useDarkTheme } from "../context_providers/DarkThemeProvider";
|
import { useDarkTheme } from "../hooks/context_providers/DarkThemeProvider";
|
||||||
|
|
||||||
export function DarkThemeButton(): React.ReactElement {
|
export function DarkThemeButton(): React.ReactElement {
|
||||||
const darkTheme = useDarkTheme();
|
const darkTheme = useDarkTheme();
|
||||||
|
Loading…
Reference in New Issue
Block a user