mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-05-24 11:59:39 -05:00
Merge branch 'develop' into feat-allow-admin-change-passwords
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import LeftArrow from "@/assets/icons/left-arrow.svg?react";
|
||||
import LeftArrowDouble from "@/assets/icons/left-arrow-double.svg?react";
|
||||
import LeftArrowLong from "@/assets/icons/left-arrow-long.svg?react";
|
||||
|
||||
export const ArrowLeft = ({
|
||||
type,
|
||||
color = "#667085",
|
||||
...props
|
||||
}: {
|
||||
type?: string;
|
||||
color?: string | undefined;
|
||||
[key: string]: any;
|
||||
}) => {
|
||||
if (type === "double") {
|
||||
return (
|
||||
<LeftArrowDouble
|
||||
style={{ color }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
} else if (type === "long") {
|
||||
return (
|
||||
<LeftArrowLong
|
||||
style={{ color }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<LeftArrow
|
||||
style={{ color }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
import RightArrow from "@/assets/icons/right-arrow.svg?react";
|
||||
import RightArrowDouble from "@/assets/icons/right-arrow-double.svg?react";
|
||||
|
||||
export const ArrowRight = ({
|
||||
type,
|
||||
color = "#667085",
|
||||
...props
|
||||
}: {
|
||||
type?: string;
|
||||
color?: string | undefined;
|
||||
[key: string]: any;
|
||||
}) => {
|
||||
if (type === "double") {
|
||||
return (
|
||||
<RightArrowDouble
|
||||
style={{ color }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<RightArrow
|
||||
style={{ color }}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -1,39 +1,6 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
|
||||
import { Outlet } from "react-router";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Box from "@mui/material/Box";
|
||||
|
||||
const COLLAPSED_WIDTH = 50;
|
||||
const EXPANDED_WIDTH = 250;
|
||||
|
||||
const SideBar = () => {
|
||||
const theme = useTheme();
|
||||
const isSmall = useMediaQuery(theme.breakpoints.down("md"));
|
||||
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
useEffect(() => {
|
||||
setCollapsed(isSmall);
|
||||
}, [isSmall]);
|
||||
return (
|
||||
<Stack
|
||||
border="1px solid red"
|
||||
width={collapsed ? COLLAPSED_WIDTH : EXPANDED_WIDTH}
|
||||
sx={{
|
||||
transition: "width 0.3s ease",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
border="1px solid blue"
|
||||
onClick={() => setCollapsed(!collapsed)}
|
||||
>
|
||||
Sidebar Content
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
import { SideBar } from "@/Components/v2/Layouts/Sidebar";
|
||||
|
||||
const RootLayout = () => {
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
|
||||
import Stack from "@mui/material/Stack";
|
||||
|
||||
export const BottomControls = ({}) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
height={50}
|
||||
py={theme.spacing(4)}
|
||||
px={theme.spacing(8)}
|
||||
gap={theme.spacing(2)}
|
||||
></Stack>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import { ArrowRight } from "@/Components/v2/Arrows/ArrowRight";
|
||||
import { ArrowLeft } from "@/Components/v2/Arrows/ArrowLeft";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { toggleSidebar } from "../../../../Features/UI/uiSlice.js";
|
||||
|
||||
export const CollapseButton = ({ collapsed }: { collapsed: boolean }) => {
|
||||
const theme = useTheme();
|
||||
const dispatch = useDispatch();
|
||||
const arrowIcon = collapsed ? (
|
||||
<ArrowRight
|
||||
height={theme.spacing(8)}
|
||||
width={theme.spacing(8)}
|
||||
color={theme.palette.primary.contrastTextSecondary}
|
||||
/>
|
||||
) : (
|
||||
<ArrowLeft
|
||||
height={theme.spacing(8)}
|
||||
width={theme.spacing(8)}
|
||||
color={theme.palette.primary.contrastTextSecondary}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
sx={{
|
||||
position: "absolute",
|
||||
/* TODO 60 is a magic number. if logo chnges size this might break */
|
||||
top: 60,
|
||||
right: 0,
|
||||
transform: `translate(50%, 0)`,
|
||||
backgroundColor: theme.palette.tertiary.main,
|
||||
border: `1px solid ${theme.palette.primary.lowContrast}`,
|
||||
p: theme.spacing(2.5),
|
||||
|
||||
"&:focus": { outline: "none" },
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.primary.lowContrast,
|
||||
borderColor: theme.palette.primary.lowContrast,
|
||||
},
|
||||
}}
|
||||
onClick={() => {
|
||||
dispatch(toggleSidebar());
|
||||
}}
|
||||
>
|
||||
{arrowIcon}
|
||||
</IconButton>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useNavigate } from "react-router";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export const Logo = ({ collapsed }: { collapsed: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Stack
|
||||
pt={theme.spacing(6)}
|
||||
pb={theme.spacing(12)}
|
||||
pl={theme.spacing(8)}
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
gap={theme.spacing(4)}
|
||||
onClick={() => navigate("/")}
|
||||
sx={{ cursor: "pointer" }}
|
||||
>
|
||||
<Typography
|
||||
pl={theme.spacing("1px")}
|
||||
minWidth={theme.spacing(16)}
|
||||
minHeight={theme.spacing(16)}
|
||||
display={"flex"}
|
||||
justifyContent={"center"}
|
||||
alignItems={"center"}
|
||||
bgcolor={theme.palette.accent.main}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
color={theme.palette.accent.contrastText}
|
||||
fontSize={18}
|
||||
>
|
||||
C
|
||||
</Typography>
|
||||
<Box
|
||||
overflow={"hidden"}
|
||||
sx={{
|
||||
transition: "opacity 900ms ease, width 900ms ease",
|
||||
opacity: collapsed ? 0 : 1,
|
||||
whiteSpace: "nowrap",
|
||||
width: collapsed ? 0 : "100%",
|
||||
}}
|
||||
>
|
||||
{" "}
|
||||
<Typography
|
||||
lineHeight={1}
|
||||
mt={theme.spacing(2)}
|
||||
color={theme.palette.primary.contrastText}
|
||||
variant="h2"
|
||||
>
|
||||
{t("common.appName")}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
import Notifications from "@/assets/icons/notifications.svg?react";
|
||||
import Monitors from "@/assets/icons/monitors.svg?react";
|
||||
import PageSpeed from "@/assets/icons/page-speed.svg?react";
|
||||
import Integrations from "@/assets/icons/integrations.svg?react";
|
||||
import Incidents from "@/assets/icons/incidents.svg?react";
|
||||
import StatusPages from "@/assets/icons/status-pages.svg?react";
|
||||
import Maintenance from "@/assets/icons/maintenance.svg?react";
|
||||
import Logs from "@/assets/icons/logs.svg?react";
|
||||
import Settings from "@/assets/icons/settings.svg?react";
|
||||
import Support from "@/assets/icons/support.svg?react";
|
||||
import Discussions from "@/assets/icons/discussions.svg?react";
|
||||
import Docs from "@/assets/icons/docs.svg?react";
|
||||
import ChangeLog from "@/assets/icons/changeLog.svg?react";
|
||||
|
||||
export const getMenu = (t: Function) => [
|
||||
{ name: t("menu.uptime"), path: "v2/uptime", icon: <Monitors /> },
|
||||
{ name: t("menu.pagespeed"), path: "pagespeed", icon: <PageSpeed /> },
|
||||
|
||||
{ name: t("menu.infrastructure"), path: "infrastructure", icon: <Integrations /> },
|
||||
{
|
||||
name: t("menu.notifications"),
|
||||
path: "notifications",
|
||||
icon: <Notifications />,
|
||||
},
|
||||
{ name: t("menu.incidents"), path: "incidents", icon: <Incidents /> },
|
||||
|
||||
{ name: t("menu.statusPages"), path: "status", icon: <StatusPages /> },
|
||||
{ name: t("menu.maintenance"), path: "maintenance", icon: <Maintenance /> },
|
||||
{ name: t("menu.logs"), path: "logs", icon: <Logs /> },
|
||||
|
||||
{
|
||||
name: t("menu.settings"),
|
||||
icon: <Settings />,
|
||||
path: "settings",
|
||||
},
|
||||
];
|
||||
|
||||
export const getBottomMenu = (t: Function) => [
|
||||
{ name: t("menu.support"), path: "support", icon: <Support />, url: "invite" },
|
||||
{
|
||||
name: t("menu.discussions"),
|
||||
path: "discussions",
|
||||
icon: <Discussions />,
|
||||
url: "https://github.com/bluewave-labs/checkmate/discussions",
|
||||
},
|
||||
{
|
||||
name: t("menu.docs"),
|
||||
path: "docs",
|
||||
icon: <Docs />,
|
||||
url: "https://bluewavelabs.gitbook.io/checkmate",
|
||||
},
|
||||
{
|
||||
name: t("menu.changelog"),
|
||||
path: "changelog",
|
||||
icon: <ChangeLog />,
|
||||
url: "https://github.com/bluewave-labs/checkmate/releases",
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,103 @@
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import ListItemButton from "@mui/material/ListItemButton";
|
||||
import ListItemIcon from "@mui/material/ListItemIcon";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
|
||||
export interface NavData {
|
||||
name: string;
|
||||
icon: JSX.Element;
|
||||
}
|
||||
|
||||
export const NavItem = ({
|
||||
item,
|
||||
collapsed,
|
||||
selected,
|
||||
onClick,
|
||||
}: {
|
||||
item: NavData;
|
||||
collapsed: boolean;
|
||||
selected: boolean;
|
||||
onClick: (event: React.MouseEvent) => void;
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const iconStroke = selected
|
||||
? theme.palette.primary.contrastText
|
||||
: theme.palette.primary.contrastTextTertiary;
|
||||
|
||||
const buttonBgColor = selected ? theme.palette.secondary.main : "transparent";
|
||||
const buttonBgHoverColor = selected
|
||||
? theme.palette.secondary.main
|
||||
: theme.palette.tertiary.main;
|
||||
const fontWeight = selected ? 600 : 400;
|
||||
return (
|
||||
<Tooltip
|
||||
placement="right"
|
||||
title={collapsed ? item.name : ""}
|
||||
slotProps={{
|
||||
popper: {
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset: [0, -16],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}}
|
||||
disableInteractive
|
||||
>
|
||||
<ListItemButton
|
||||
sx={{
|
||||
backgroundColor: buttonBgColor,
|
||||
"&:hover": {
|
||||
backgroundColor: buttonBgHoverColor,
|
||||
},
|
||||
height: 37,
|
||||
gap: theme.spacing(4),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
px: theme.spacing(4),
|
||||
pl: theme.spacing(5),
|
||||
}}
|
||||
onClick={onClick}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
"& svg": {
|
||||
height: 20,
|
||||
width: 20,
|
||||
opacity: 0.81,
|
||||
},
|
||||
"& svg path": {
|
||||
stroke: iconStroke,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{item.icon}
|
||||
</ListItemIcon>
|
||||
<Box
|
||||
sx={{
|
||||
overflow: "hidden",
|
||||
transition: "opacity 900ms ease",
|
||||
opacity: collapsed ? 0 : 1,
|
||||
whiteSpace: "nowrap",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body1"
|
||||
color={theme.palette.primary.contrastText}
|
||||
sx={{
|
||||
fontWeight: fontWeight,
|
||||
opacity: 0.9,
|
||||
}}
|
||||
>
|
||||
{item.name}
|
||||
</Typography>
|
||||
</Box>
|
||||
</ListItemButton>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,103 @@
|
||||
import { useEffect } from "react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { setCollapsed } from "@/Features/UI/uiSlice";
|
||||
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
|
||||
import { CollapseButton } from "@/Components/v2/Layouts/Sidebar/CollapseButton";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import List from "@mui/material/List";
|
||||
import Divider from "@mui/material/Divider";
|
||||
import { Logo } from "@/Components/v2/Layouts/Sidebar/Logo";
|
||||
import { getMenu, getBottomMenu } from "@/Components/v2/Layouts/Sidebar/Menu";
|
||||
import { NavItem } from "@/Components/v2/Layouts/Sidebar/NavItem";
|
||||
import { BottomControls } from "@/Components/v2/Layouts/Sidebar/BottomControls";
|
||||
|
||||
export const COLLAPSED_WIDTH = 64;
|
||||
export const EXPANDED_WIDTH = 250;
|
||||
|
||||
export const SideBar = () => {
|
||||
const theme = useTheme();
|
||||
const isSmall = useMediaQuery(theme.breakpoints.down("md"));
|
||||
const dispatch = useDispatch();
|
||||
const collapsed = useSelector((state: any) => state.ui.sidebar.collapsed);
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const menu = getMenu(t);
|
||||
const bottomMenu = getBottomMenu(t);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(setCollapsed({ collapsed: isSmall }));
|
||||
}, [isSmall]);
|
||||
|
||||
return (
|
||||
<Stack
|
||||
component="aside"
|
||||
position="sticky"
|
||||
paddingTop={theme.spacing(6)}
|
||||
paddingBottom={theme.spacing(6)}
|
||||
gap={theme.spacing(6)}
|
||||
borderRight={`1px solid ${theme.palette.primary.lowContrast}`}
|
||||
width={collapsed ? COLLAPSED_WIDTH : EXPANDED_WIDTH}
|
||||
sx={{
|
||||
transition: "width 650ms cubic-bezier(0.36, -0.01, 0, 0.77)",
|
||||
}}
|
||||
>
|
||||
<CollapseButton collapsed={collapsed} />
|
||||
<Logo collapsed={collapsed} />
|
||||
<List
|
||||
component="nav"
|
||||
disablePadding
|
||||
sx={{
|
||||
px: theme.spacing(6),
|
||||
height: "100%",
|
||||
}}
|
||||
>
|
||||
{menu.map((item) => {
|
||||
const selected = location.pathname.startsWith(`/${item.path}`);
|
||||
return (
|
||||
<NavItem
|
||||
key={item.path}
|
||||
item={item}
|
||||
collapsed={collapsed}
|
||||
selected={selected}
|
||||
onClick={() => navigate(`/${item.path}`)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
<List
|
||||
component="nav"
|
||||
disablePadding
|
||||
sx={{
|
||||
px: theme.spacing(6),
|
||||
}}
|
||||
>
|
||||
{bottomMenu.map((item) => {
|
||||
const selected = location.pathname.startsWith(`/${item.path}`);
|
||||
|
||||
return (
|
||||
<NavItem
|
||||
key={item.path}
|
||||
item={item}
|
||||
collapsed={collapsed}
|
||||
selected={selected}
|
||||
onClick={() => {
|
||||
if (item.url) {
|
||||
window.open(item.url, "_blank", "noreferrer");
|
||||
} else {
|
||||
navigate(`/${item.path}`);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
<Divider sx={{ mt: "auto", borderColor: theme.palette.primary.lowContrast }} />
|
||||
<BottomControls />
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
isAuthenticated: false,
|
||||
};
|
||||
|
||||
const v2AuthSlice = createSlice({
|
||||
name: "v2Auth",
|
||||
initialState,
|
||||
reducers: {
|
||||
setIsAuthenticated: (state, action) => {
|
||||
const { authenticated } = action.payload;
|
||||
state.isAuthenticated = authenticated;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default v2AuthSlice.reducer;
|
||||
export const { setIsAuthenticated } = v2AuthSlice.actions;
|
||||
@@ -47,6 +47,10 @@ const uiSlice = createSlice({
|
||||
toggleSidebar: (state) => {
|
||||
state.sidebar.collapsed = !state.sidebar.collapsed;
|
||||
},
|
||||
setCollapsed: (state, action) => {
|
||||
const { collapsed } = action.payload;
|
||||
state.sidebar.collapsed = collapsed;
|
||||
},
|
||||
setMode: (state, action) => {
|
||||
state.mode = action.payload;
|
||||
},
|
||||
@@ -73,6 +77,7 @@ export default uiSlice.reducer;
|
||||
export const {
|
||||
setRowsPerPage,
|
||||
toggleSidebar,
|
||||
setCollapsed,
|
||||
setMode,
|
||||
setShowURL,
|
||||
setGreeting,
|
||||
|
||||
@@ -3,7 +3,9 @@ import { z } from "zod";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
|
||||
import { useDispatch } from "react-redux";
|
||||
import { setIsAuthenticated } from "@/Features/Auth/v2AuthSlice";
|
||||
import { useNavigate } from "react-router";
|
||||
import { TextInput } from "@/Components/v2/Inputs/TextInput";
|
||||
import Button from "@mui/material/Button";
|
||||
import Stack from "@mui/material/Stack";
|
||||
@@ -19,8 +21,10 @@ type FormData = z.infer<typeof schema>;
|
||||
|
||||
const Login = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const theme = useTheme();
|
||||
const { post, loading, error } = usePost<FormData, ApiResponse>("/auth/login");
|
||||
const { post, loading } = usePost<FormData, ApiResponse>("/auth/login");
|
||||
const navigate = useNavigate();
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
@@ -37,9 +41,10 @@ const Login = () => {
|
||||
const onSubmit = async (data: FormData) => {
|
||||
const result = await post(data);
|
||||
if (result) {
|
||||
console.log(result.message);
|
||||
dispatch(setIsAuthenticated({ authenticated: true }));
|
||||
navigate("/v2/uptime");
|
||||
} else {
|
||||
console.error("Login failed:", error);
|
||||
dispatch(setIsAuthenticated({ authenticated: false }));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -25,7 +25,11 @@ const V2Routes = ({ mode = "light" }) => {
|
||||
element={<RootLayout />}
|
||||
>
|
||||
<Route
|
||||
path="test"
|
||||
index
|
||||
element={<h1>Uptime</h1>}
|
||||
/>
|
||||
<Route
|
||||
path="uptime"
|
||||
element={<h1>Test Page</h1>}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
@@ -54,12 +54,18 @@ export const lightPalette = {
|
||||
main: colors.offWhite,
|
||||
contrastText: colors.blueGray800,
|
||||
contrastTextSecondary: colors.blueGray600,
|
||||
contrastTextTertiary: colors.blueGray500,
|
||||
lowContrast: colors.gray250,
|
||||
},
|
||||
secondary: {
|
||||
main: colors.gray200,
|
||||
light: colors.lightBlueWave,
|
||||
contrastText: colors.blueGray600,
|
||||
},
|
||||
tertiary: {
|
||||
main: colors.gray100,
|
||||
contrastText: colors.blueGray800,
|
||||
},
|
||||
};
|
||||
|
||||
export const darkPalette = {
|
||||
@@ -73,10 +79,16 @@ export const darkPalette = {
|
||||
main: colors.offBlack,
|
||||
contrastText: colors.blueGray50,
|
||||
contrastTextSecondary: colors.gray200,
|
||||
contrastTextTertiary: colors.gray500,
|
||||
lowContrast: colors.blueGray600,
|
||||
},
|
||||
secondary: {
|
||||
main: "#313131",
|
||||
light: colors.lightBlueWave,
|
||||
contrastText: colors.gray200,
|
||||
},
|
||||
tertiary: {
|
||||
main: colors.blueGray800,
|
||||
contrastText: colors.gray100,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -67,6 +67,9 @@ export const theme = (mode: string, palette: any) =>
|
||||
},
|
||||
},
|
||||
},
|
||||
shape: {
|
||||
borderRadius: 2,
|
||||
},
|
||||
});
|
||||
|
||||
export const lightTheme = createTheme(theme("light", lightPalette));
|
||||
|
||||
+3
-1
@@ -1,6 +1,7 @@
|
||||
import { configureStore, combineReducers } from "@reduxjs/toolkit";
|
||||
|
||||
import authReducer from "./Features/Auth/authSlice";
|
||||
import v2AuthReducer from "./Features/Auth/v2AuthSlice";
|
||||
import uiReducer from "./Features/UI/uiSlice";
|
||||
import storage from "redux-persist/lib/storage";
|
||||
import { persistReducer, persistStore, createTransform } from "redux-persist";
|
||||
@@ -19,12 +20,13 @@ const authTransform = createTransform(
|
||||
const persistConfig = {
|
||||
key: "root",
|
||||
storage,
|
||||
whitelist: ["auth", "ui"],
|
||||
whitelist: ["auth", "v2Auth", "ui"],
|
||||
transforms: [authTransform],
|
||||
};
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
auth: authReducer,
|
||||
v2Auth: v2AuthReducer,
|
||||
ui: uiReducer,
|
||||
});
|
||||
|
||||
|
||||
Vendored
+8
@@ -7,3 +7,11 @@ interface ImportMetaEnv {
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
|
||||
declare module "*.svg?react" {
|
||||
import * as React from "react";
|
||||
const ReactComponent: React.FunctionComponent<
|
||||
React.SVGProps<SVGSVGElement> & { title?: string }
|
||||
>;
|
||||
export default ReactComponent;
|
||||
}
|
||||
|
||||
Vendored
+4
@@ -3,13 +3,17 @@ import "@mui/material/Button";
|
||||
declare module "@mui/material/styles" {
|
||||
interface Palette {
|
||||
accent: Palette["primary"];
|
||||
tertiary: Palette["primary"];
|
||||
}
|
||||
interface PaletteOptions {
|
||||
accent?: PaletteOptions["primary"];
|
||||
tertiary?: PaletteOptions["primary"];
|
||||
}
|
||||
|
||||
interface PaletteColor {
|
||||
contrastTextSecondary?: string;
|
||||
contrastTextTertiary?: string;
|
||||
lowContrast?: string;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user