Refactor pagespeed page
This commit is contained in:
1 parent
9840999183
commit
74265d524a
14 files changed
+295
-266
No files matched your search
@@ -0,0 +1,33 @@
|
||||
import { Stack, Button } from "@mui/material";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import PropTypes from "prop-types";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
|
||||
const CreateMonitorHeader = ({ isAdmin, shouldRender, path }) => {
|
||||
const navigate = useNavigate();
|
||||
if (!isAdmin) return null;
|
||||
if (!shouldRender) return <SkeletonLayout />;
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="end"
|
||||
alignItems="center"
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
onClick={() => navigate(path)}
|
||||
>
|
||||
Create new
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateMonitorHeader;
|
||||
|
||||
CreateMonitorHeader.propTypes = {
|
||||
isAdmin: PropTypes.bool.isRequired,
|
||||
shouldRender: PropTypes.bool.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Stack, Skeleton } from "@mui/material";
|
||||
|
||||
const SkeletonLayout = () => {
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="end"
|
||||
alignItems="center"
|
||||
>
|
||||
<Skeleton
|
||||
variant="rectangular"
|
||||
width={100}
|
||||
height={36}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SkeletonLayout;
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Stack } from "@mui/material";
|
||||
import { Heading } from "../Heading";
|
||||
import CircularCount from "../CircularCount";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
|
||||
const MonitorCountHeader = ({
|
||||
shouldRender = true,
|
||||
monitorCount,
|
||||
heading,
|
||||
sx,
|
||||
children,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
if (!shouldRender) return <SkeletonLayout />;
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
gap={theme.spacing(2)}
|
||||
sx={{ ...sx }}
|
||||
>
|
||||
<Heading component="h2">{heading}</Heading>
|
||||
<CircularCount count={monitorCount} />
|
||||
{children}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
MonitorCountHeader.propTypes = {
|
||||
shouldRender: PropTypes.bool,
|
||||
monitorCount: PropTypes.number,
|
||||
heading: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
sx: PropTypes.object,
|
||||
};
|
||||
|
||||
export default MonitorCountHeader;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Stack, Skeleton } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
|
||||
const SkeletonLayout = () => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
gap={theme.spacing(2)}
|
||||
>
|
||||
<Skeleton
|
||||
variant="text"
|
||||
width={100}
|
||||
height={32}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="circular"
|
||||
width={40}
|
||||
height={40}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SkeletonLayout;
|
||||
File renamed without changes.
File renamed without changes.
+6
-5
@@ -1,15 +1,16 @@
|
||||
import PropTypes from "prop-types";
|
||||
import PageSpeedIcon from "../../assets/icons/page-speed.svg?react";
|
||||
import { StatusLabel } from "../../Components/Label";
|
||||
// import PageSpeedIcon from "../../../../assets/icons/page-speed.svg?react";
|
||||
import PageSpeedIcon from "../../../../../assets/icons/page-speed.svg?react";
|
||||
import { StatusLabel } from "../../../../../Components/Label";
|
||||
import { Box, Grid, Stack, Typography } from "@mui/material";
|
||||
import { useNavigate } from "react-router";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip } from "recharts";
|
||||
import { useSelector } from "react-redux";
|
||||
import { formatDateWithTz, formatDurationSplit } from "../../Utils/timeUtils";
|
||||
import useUtils from "../Uptime/Home/Hooks/useUtils";
|
||||
import { formatDateWithTz, formatDurationSplit } from "../../../../../Utils/timeUtils";
|
||||
import useUtils from "../../../../Uptime/Home/Hooks/useUtils";
|
||||
import { useState } from "react";
|
||||
import IconBox from "../../Components/IconBox";
|
||||
import IconBox from "../../../../../Components/IconBox";
|
||||
/**
|
||||
* CustomToolTip displays a tooltip with formatted date and score information.
|
||||
* @param {Object} props
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Grid, Grid2 } from "@mui/material";
|
||||
import Card from "../Card";
|
||||
|
||||
const MonitorGrid = ({ shouldRender, monitors }) => {
|
||||
if (!shouldRender) return null;
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
spacing={12}
|
||||
>
|
||||
{monitors?.map((monitor) => (
|
||||
<Card
|
||||
monitor={monitor}
|
||||
key={monitor._id}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export default MonitorGrid;
|
||||
@@ -0,0 +1,43 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../../../../main";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
|
||||
const useMonitorsFetch = ({ authToken, teamId }) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [monitors, setMonitors] = useState([]);
|
||||
const [summary, setSummary] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsByTeamId({
|
||||
authToken: authToken,
|
||||
teamId: teamId,
|
||||
limit: 10,
|
||||
types: ["pagespeed"],
|
||||
page: null,
|
||||
rowsPerPage: null,
|
||||
filter: null,
|
||||
field: null,
|
||||
order: null,
|
||||
});
|
||||
if (res?.data?.data?.filteredMonitors) {
|
||||
setMonitors(res.data.data.filteredMonitors);
|
||||
setSummary(res.data.data.summary);
|
||||
}
|
||||
} catch (error) {
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMonitors();
|
||||
}, [authToken, teamId]);
|
||||
return { isLoading, monitors, summary };
|
||||
};
|
||||
|
||||
export default useMonitorsFetch;
|
||||
@@ -0,0 +1,66 @@
|
||||
// Components
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import { Stack, Box } from "@mui/material";
|
||||
import CreateMonitorHeader from "../../../Components/CreateMonitorHeader";
|
||||
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
||||
import MonitorGrid from "./Components/MonitorGrid";
|
||||
import Fallback from "../../../Components/Fallback";
|
||||
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||
import useMonitorsFetch from "./Hooks/useMonitorsFetch";
|
||||
|
||||
// Constants
|
||||
const BREADCRUMBS = [{ name: `pagespeed`, path: "/pagespeed" }];
|
||||
|
||||
const NewPageSpeed = () => {
|
||||
const theme = useTheme();
|
||||
const isAdmin = useIsAdmin();
|
||||
const { user, authToken } = useSelector((state) => state.auth);
|
||||
|
||||
const { isLoading, monitors, summary } = useMonitorsFetch({
|
||||
authToken: authToken,
|
||||
teamId: user.teamId,
|
||||
});
|
||||
|
||||
if (!isLoading && monitors?.length === 0) {
|
||||
return (
|
||||
<Fallback
|
||||
title="pagespeed monitor"
|
||||
checks={[
|
||||
"Report on the user experience of a page",
|
||||
"Help analyze webpage speed",
|
||||
"Give suggestions on how the page can be improved",
|
||||
]}
|
||||
link="/pagespeed/create"
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack gap={theme.spacing(10)}>
|
||||
<Breadcrumbs list={BREADCRUMBS} />
|
||||
<CreateMonitorHeader
|
||||
isAdmin={isAdmin}
|
||||
shouldRender={!isLoading}
|
||||
path="/pagespeed/create"
|
||||
/>
|
||||
<MonitorCountHeader
|
||||
shouldRender={!isLoading}
|
||||
monitorCount={summary?.totalMonitors}
|
||||
heading="PageSpeed monitors"
|
||||
sx={{ mb: theme.spacing(8) }}
|
||||
/>
|
||||
<MonitorGrid
|
||||
size={6}
|
||||
shouldRender={!isLoading}
|
||||
monitors={monitors}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default NewPageSpeed;
|
||||
@@ -1,8 +0,0 @@
|
||||
.page-speed .label {
|
||||
padding: 7px;
|
||||
height: 24px;
|
||||
font-size: var(--env-var-font-size-small);
|
||||
}
|
||||
.page-speed:not(:has([class*="fallback__"])) button {
|
||||
min-height: 34px;
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
import { Box, Button, Grid, Stack } from "@mui/material";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useSelector } from "react-redux";
|
||||
import Fallback from "../../Components/Fallback";
|
||||
import "./index.css";
|
||||
import { useNavigate } from "react-router";
|
||||
import PropTypes from "prop-types";
|
||||
import Breadcrumbs from "../../Components/Breadcrumbs";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
import Card from "./card";
|
||||
import { networkService } from "../../main";
|
||||
import { Heading } from "../../Components/Heading";
|
||||
import { useIsAdmin } from "../../Hooks/useIsAdmin";
|
||||
const PageSpeed = () => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const isAdmin = useIsAdmin();
|
||||
const { user, authToken } = useSelector((state) => state.auth);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [monitors, setMonitors] = useState([]);
|
||||
const [summary, setSummary] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsByTeamId({
|
||||
authToken: authToken,
|
||||
teamId: user.teamId,
|
||||
limit: 10,
|
||||
types: ["pagespeed"],
|
||||
page: null,
|
||||
rowsPerPage: null,
|
||||
filter: null,
|
||||
field: null,
|
||||
order: null,
|
||||
});
|
||||
if (res?.data?.data?.filteredMonitors) {
|
||||
setMonitors(res.data.data.filteredMonitors);
|
||||
setSummary(res.data.data.summary);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMonitors();
|
||||
}, [authToken, user.teamId]);
|
||||
|
||||
// will show skeletons only on initial load
|
||||
// since monitor state is being added to redux persist, there's no reason to display skeletons on every render
|
||||
let isActuallyLoading = isLoading && monitors?.length === 0;
|
||||
return (
|
||||
<Box
|
||||
className="page-speed"
|
||||
sx={{
|
||||
':has(> [class*="fallback__"])': {
|
||||
position: "relative",
|
||||
border: 1,
|
||||
borderColor: theme.palette.primary.lowContrast,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
borderStyle: "dashed",
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
overflow: "hidden",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{isActuallyLoading ? (
|
||||
<SkeletonLayout />
|
||||
) : monitors?.length !== 0 ? (
|
||||
<Stack gap={theme.spacing(8)}>
|
||||
<Box>
|
||||
<Breadcrumbs list={[{ name: `pagespeed`, path: "/pagespeed" }]} />
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="end"
|
||||
alignItems="center"
|
||||
mt={theme.spacing(5)}
|
||||
>
|
||||
{isAdmin && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
onClick={() => navigate("/pagespeed/create")}
|
||||
sx={{ fontWeight: 500, whiteSpace: "nowrap" }}
|
||||
>
|
||||
Create new
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
gap: ".25rem",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Heading component="h2">PageSpeed monitors</Heading>
|
||||
{/* TODO Correct the class current-monitors-counter, there are some unnecessary things there */}
|
||||
<Box
|
||||
component="span"
|
||||
className="current-monitors-counter"
|
||||
color={theme.palette.primary.contrastText}
|
||||
border={2}
|
||||
borderColor={theme.palette.accent.main}
|
||||
backgroundColor={theme.palette.tertiary.main}
|
||||
sx={{
|
||||
padding: ".25em .75em",
|
||||
borderRadius: "10000px",
|
||||
fontSize: "12px",
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
{summary?.totalMonitors ?? 0}
|
||||
</Box>
|
||||
</Stack>
|
||||
<Grid
|
||||
container
|
||||
spacing={theme.spacing(12)}
|
||||
>
|
||||
{monitors?.map((monitor) => (
|
||||
<Card
|
||||
monitor={monitor}
|
||||
key={monitor._id}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
</Stack>
|
||||
) : (
|
||||
<Fallback
|
||||
title="pagespeed monitor"
|
||||
checks={[
|
||||
"Report on the user experience of a page",
|
||||
"Help analyze webpage speed",
|
||||
"Give suggestions on how the page can be improved",
|
||||
]}
|
||||
link="/pagespeed/create"
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
PageSpeed.propTypes = {
|
||||
isAdmin: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default PageSpeed;
|
||||
@@ -1,73 +0,0 @@
|
||||
import { Box, Skeleton, Stack } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
|
||||
/**
|
||||
* Renders a skeleton layout.
|
||||
*
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
const SkeletonLayout = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Stack gap={theme.spacing(2)}>
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
mb={theme.spacing(12)}
|
||||
>
|
||||
<Box width="80%">
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="25%"
|
||||
height={24}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="50%"
|
||||
height={19.5}
|
||||
sx={{ mt: theme.spacing(2) }}
|
||||
/>
|
||||
</Box>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="20%"
|
||||
height={34}
|
||||
sx={{ alignSelf: "flex-end" }}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack
|
||||
direction="row"
|
||||
flexWrap="wrap"
|
||||
gap={theme.spacing(12)}
|
||||
>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="100%"
|
||||
height={120}
|
||||
sx={{ flex: "35%" }}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="100%"
|
||||
height={120}
|
||||
sx={{ flex: "35%" }}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="100%"
|
||||
height={120}
|
||||
sx={{ flex: "35%" }}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="100%"
|
||||
height={120}
|
||||
sx={{ flex: "35%" }}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SkeletonLayout;
|
||||
+40
-27
@@ -1,36 +1,49 @@
|
||||
import { Navigate, Route, Routes as LibRoutes } from "react-router";
|
||||
import HomeLayout from "../Components/Layouts/HomeLayout";
|
||||
import { Infrastructure } from "../Pages/Infrastructure";
|
||||
import InfrastructureDetails from "../Pages/Infrastructure/Details";
|
||||
import NotFound from "../Pages/NotFound";
|
||||
import Login from "../Pages/Auth/Login/Login";
|
||||
import Register from "../Pages/Auth/Register/Register";
|
||||
import Account from "../Pages/Account";
|
||||
|
||||
// Auth
|
||||
import AuthLogin from "../Pages/Auth/Login/Login";
|
||||
import AuthRegister from "../Pages/Auth/Register/Register";
|
||||
import AuthForgotPassword from "../Pages/Auth/ForgotPassword";
|
||||
import AuthCheckEmail from "../Pages/Auth/CheckEmail";
|
||||
import AuthSetNewPassword from "../Pages/Auth/SetNewPassword";
|
||||
import AuthNewPasswordConfirmed from "../Pages/Auth/NewPasswordConfirmed";
|
||||
|
||||
// Uptime
|
||||
import Uptime from "../Pages/Uptime/Home";
|
||||
import UptimeDetails from "../Pages/Uptime/Details";
|
||||
import UptimeCreate from "../Pages/Uptime/Create";
|
||||
import UptimeConfigure from "../Pages/Uptime/Configure";
|
||||
|
||||
// PageSpeed
|
||||
// import PageSpeed from "../Pages/PageSpeed";
|
||||
import PageSpeed from "../Pages/PageSpeed/Monitors";
|
||||
import PageSpeedCreate from "../Pages/PageSpeed/Create";
|
||||
import PageSpeedDetails from "../Pages/PageSpeed/Details";
|
||||
import PageSpeedConfigure from "../Pages/PageSpeed/Configure";
|
||||
|
||||
// Infrastructure
|
||||
import InfrastructureCreate from "../Pages/Infrastructure/Create";
|
||||
import InfrastructureDetails from "../Pages/Infrastructure/Details";
|
||||
|
||||
import CreateMonitor from "../Pages/Uptime/CreateUptime";
|
||||
import CreateInfrastructureMonitor from "../Pages/Infrastructure/CreateMonitor";
|
||||
import Incidents from "../Pages/Incidents";
|
||||
import Status from "../Pages/Status";
|
||||
import Integrations from "../Pages/Integrations";
|
||||
|
||||
// Settings
|
||||
import Account from "../Pages/Account";
|
||||
import Settings from "../Pages/Settings";
|
||||
import ForgotPassword from "../Pages/Auth/ForgotPassword";
|
||||
import CheckEmail from "../Pages/Auth/CheckEmail";
|
||||
import SetNewPassword from "../Pages/Auth/SetNewPassword";
|
||||
import NewPasswordConfirmed from "../Pages/Auth/NewPasswordConfirmed";
|
||||
import ProtectedRoute from "../Components/ProtectedRoute";
|
||||
|
||||
import Maintenance from "../Pages/Maintenance";
|
||||
import Configure from "../Pages/Uptime/Configure";
|
||||
import PageSpeed from "../Pages/PageSpeed";
|
||||
import CreatePageSpeed from "../Pages/PageSpeed/CreatePageSpeed";
|
||||
|
||||
import ProtectedRoute from "../Components/ProtectedRoute";
|
||||
import CreateNewMaintenanceWindow from "../Pages/Maintenance/CreateMaintenance";
|
||||
import PageSpeedDetails from "../Pages/PageSpeed/Details";
|
||||
import PageSpeedConfigure from "../Pages/PageSpeed/Configure";
|
||||
import withAdminCheck from "../Components/HOC/withAdminCheck";
|
||||
|
||||
const Routes = () => {
|
||||
const AdminCheckedRegister = withAdminCheck(Register);
|
||||
const AdminCheckedRegister = withAdminCheck(AuthRegister);
|
||||
return (
|
||||
<LibRoutes>
|
||||
<Route
|
||||
@@ -52,7 +65,7 @@ const Routes = () => {
|
||||
|
||||
<Route
|
||||
path="/uptime/create/:monitorId?"
|
||||
element={<CreateMonitor />}
|
||||
element={<UptimeCreate />}
|
||||
/>
|
||||
<Route
|
||||
path="/uptime/:monitorId/"
|
||||
@@ -60,7 +73,7 @@ const Routes = () => {
|
||||
/>
|
||||
<Route
|
||||
path="/uptime/configure/:monitorId/"
|
||||
element={<Configure />}
|
||||
element={<UptimeConfigure />}
|
||||
/>
|
||||
<Route
|
||||
path="pagespeed"
|
||||
@@ -68,7 +81,7 @@ const Routes = () => {
|
||||
/>
|
||||
<Route
|
||||
path="pagespeed/create"
|
||||
element={<CreatePageSpeed />}
|
||||
element={<PageSpeedCreate />}
|
||||
/>
|
||||
<Route
|
||||
path="pagespeed/:monitorId"
|
||||
@@ -84,7 +97,7 @@ const Routes = () => {
|
||||
/>
|
||||
<Route
|
||||
path="infrastructure/create"
|
||||
element={<CreateInfrastructureMonitor />}
|
||||
element={<InfrastructureCreate />}
|
||||
/>
|
||||
<Route
|
||||
path="infrastructure/:monitorId"
|
||||
@@ -131,7 +144,7 @@ const Routes = () => {
|
||||
|
||||
<Route
|
||||
path="/login"
|
||||
element={<Login />}
|
||||
element={<AuthLogin />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
@@ -142,24 +155,24 @@ const Routes = () => {
|
||||
<Route
|
||||
exact
|
||||
path="/register/:token"
|
||||
element={<Register />}
|
||||
element={<AuthRegister />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/forgot-password"
|
||||
element={<ForgotPassword />}
|
||||
element={<AuthForgotPassword />}
|
||||
/>
|
||||
<Route
|
||||
path="/check-email"
|
||||
element={<CheckEmail />}
|
||||
element={<AuthCheckEmail />}
|
||||
/>
|
||||
<Route
|
||||
path="/set-new-password/:token"
|
||||
element={<SetNewPassword />}
|
||||
element={<AuthSetNewPassword />}
|
||||
/>
|
||||
<Route
|
||||
path="/new-password-confirmed"
|
||||
element={<NewPasswordConfirmed />}
|
||||
element={<AuthNewPasswordConfirmed />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
|
||||
Reference in new issue
Block a user