Merge branch 'dev_environment' of gitlab.com:brandx/bxt-app into dev_environment
This commit is contained in:
commit
51d37720ec
19 changed files with 307 additions and 442 deletions
6
package-lock.json
generated
6
package-lock.json
generated
|
|
@ -13689,9 +13689,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.2.5",
|
"version": "6.2.6",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.6.tgz",
|
||||||
"integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==",
|
"integrity": "sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ html, body, #root {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* styles.css or a CSS module */
|
/* styles.css or a CSS module */
|
||||||
/* .MuiDialog-root {
|
.MuiDialog-root {
|
||||||
z-index: 1500 !important;
|
z-index: 1500 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,4 +35,4 @@ html, body, #root {
|
||||||
|
|
||||||
.MuiMenu-root {
|
.MuiMenu-root {
|
||||||
z-index: 1400 !important;
|
z-index: 1400 !important;
|
||||||
} */
|
}
|
||||||
|
|
@ -5,14 +5,13 @@ import HTTPProvider from 'providers/http'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import LoadingScreen from './LoadingScreen'
|
import LoadingScreen from './LoadingScreen'
|
||||||
import UserWrapper from './UserWrapper'
|
import UserWrapper from './UserWrapper'
|
||||||
import { CssBaseline, Theme, ThemeProvider } from '@mui/material'
|
import { CssBaseline } from '@mui/material'
|
||||||
import { CreateTheme } from '../theme/theme'
|
|
||||||
import { getThemeType, setThemeType } from '../theme/themeType'
|
|
||||||
import { getWhitelabel } from 'services/whiteLabel'
|
import { getWhitelabel } from 'services/whiteLabel'
|
||||||
|
import { AppThemeProvider } from 'theme/AppThemeProvider'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [token, setToken] = useState<string | undefined>(undefined)
|
const [token, setToken] = useState<string | undefined>(undefined)
|
||||||
const [palette, setPalette] = useState<Theme>(CreateTheme(getThemeType()));
|
// const [palette, setPalette] = useState<Theme>(CreateTheme(getThemeType()));
|
||||||
|
|
||||||
const whiteLabel = getWhitelabel()
|
const whiteLabel = getWhitelabel()
|
||||||
const manifestPath = "/" + whiteLabel.name.replace(/\s/g, "") + "/manifest.json"
|
const manifestPath = "/" + whiteLabel.name.replace(/\s/g, "") + "/manifest.json"
|
||||||
|
|
@ -45,33 +44,23 @@ function App() {
|
||||||
|
|
||||||
let client_id = import.meta.env.VITE_AUTH0_DEV_CLIENT_ID;
|
let client_id = import.meta.env.VITE_AUTH0_DEV_CLIENT_ID;
|
||||||
|
|
||||||
const toggleTheme = () => {
|
|
||||||
if (getThemeType() === "light") {
|
|
||||||
setPalette(CreateTheme("dark"));
|
|
||||||
setThemeType("dark");
|
|
||||||
} else {
|
|
||||||
setPalette(CreateTheme("light"));
|
|
||||||
setThemeType("light");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Auth0Provider
|
<AppThemeProvider>
|
||||||
domain={or(url, "")}
|
<Auth0Provider
|
||||||
clientId={or(client_id, "")}
|
domain={or(url, "")}
|
||||||
authorizationParams={{
|
clientId={or(client_id, "")}
|
||||||
audience: or(audience, ""),
|
authorizationParams={{
|
||||||
redirect_uri: window.location.origin + "/callback"
|
audience: or(audience, ""),
|
||||||
}}
|
redirect_uri: window.location.origin + "/callback"
|
||||||
useRefreshTokens={true}
|
}}
|
||||||
cacheLocation='localstorage'
|
useRefreshTokens={true}
|
||||||
>
|
cacheLocation='localstorage'
|
||||||
<ThemeProvider theme={palette}>
|
>
|
||||||
<CssBaseline />
|
{/* <CssBaseline /> */}
|
||||||
<AuthWrapper setToken={setToken}>
|
<AuthWrapper setToken={setToken}>
|
||||||
{ token ?
|
{ token ?
|
||||||
<HTTPProvider token={token}>
|
<HTTPProvider token={token}>
|
||||||
<UserWrapper toggleTheme={toggleTheme}/>
|
<UserWrapper />
|
||||||
</HTTPProvider>
|
</HTTPProvider>
|
||||||
:
|
:
|
||||||
<LoadingScreen
|
<LoadingScreen
|
||||||
|
|
@ -79,8 +68,8 @@ function App() {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</AuthWrapper>
|
</AuthWrapper>
|
||||||
</ThemeProvider>
|
</Auth0Provider>
|
||||||
</Auth0Provider>
|
</AppThemeProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ const useStyles = makeStyles((theme: Theme) => ({
|
||||||
appBar: {
|
appBar: {
|
||||||
zIndex: theme.zIndex.drawer + 1,
|
zIndex: theme.zIndex.drawer + 1,
|
||||||
backgroundImage: "none", // This prevents de-saturation of header in dark mode
|
backgroundImage: "none", // This prevents de-saturation of header in dark mode
|
||||||
// backgroundColor: "#272727"
|
backgroundColor: "#272727"
|
||||||
},
|
},
|
||||||
toolbar: {
|
toolbar: {
|
||||||
marginLeft: theme.spacing(0.5),
|
marginLeft: theme.spacing(0.5),
|
||||||
|
|
@ -77,16 +77,8 @@ const useStyles = makeStyles((theme: Theme) => ({
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
interface Props {
|
export default function Header() {
|
||||||
toggleTheme: () => void;
|
|
||||||
// teams: Team[];
|
|
||||||
// setTeams: React.Dispatch<React.SetStateAction<Team[]>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Header(props: Props) {
|
|
||||||
|
|
||||||
// const { sideIsOpen, openSide, toggleTheme } = props;
|
|
||||||
const { toggleTheme } = props;
|
|
||||||
const themeType = useThemeType();
|
const themeType = useThemeType();
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const isMobile = useMobile();
|
const isMobile = useMobile();
|
||||||
|
|
@ -125,7 +117,7 @@ export default function Header(props: Props) {
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box className={classes.appBarRight}>
|
<Box className={classes.appBarRight}>
|
||||||
<UserMenu toggleTheme={toggleTheme} />
|
<UserMenu />
|
||||||
<HeaderButtons hasTeams={hasTeams} team={team} user={user} />
|
<HeaderButtons hasTeams={hasTeams} team={team} user={user} />
|
||||||
</Box>
|
</Box>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ import { GlobalState, GlobalStateAction, StateProvider } from '../providers/Stat
|
||||||
import { User } from '../models/user'
|
import { User } from '../models/user'
|
||||||
import { Team } from '../models/team'
|
import { Team } from '../models/team'
|
||||||
import { makeStyles } from '@mui/styles'
|
import { makeStyles } from '@mui/styles'
|
||||||
import { Theme } from '@mui/material'
|
import { CssBaseline, Theme } from '@mui/material'
|
||||||
|
import { AppThemeProvider } from 'theme/AppThemeProvider'
|
||||||
// import FirmwareLoader from './FirmwareLoader'
|
// import FirmwareLoader from './FirmwareLoader'
|
||||||
|
|
||||||
const reducer = (state: GlobalState, action: GlobalStateAction): GlobalState => {
|
const reducer = (state: GlobalState, action: GlobalStateAction): GlobalState => {
|
||||||
|
|
@ -50,12 +51,7 @@ const globalDefault = {
|
||||||
firmware: new Map()
|
firmware: new Map()
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
export default function UserWrapper() {
|
||||||
toggleTheme: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function UserWrapper(props: Props) {
|
|
||||||
const { toggleTheme } = props;
|
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const userAPI = useUserAPI();
|
const userAPI = useUserAPI();
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
@ -99,10 +95,14 @@ export default function UserWrapper(props: Props) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StateProvider state={global} reducer={reducer}>
|
<StateProvider state={global} reducer={reducer}>
|
||||||
{/* <FirmwareLoader> */}
|
<AppThemeProvider >
|
||||||
|
<CssBaseline/>
|
||||||
<main className={classes.appContent}>
|
<main className={classes.appContent}>
|
||||||
<NavigationContainer toggleTheme={toggleTheme} />
|
<NavigationContainer />
|
||||||
</main>
|
</main>
|
||||||
|
</AppThemeProvider>
|
||||||
|
{/* <FirmwareLoader> */}
|
||||||
|
|
||||||
{/* </FirmwareLoader> */}
|
{/* </FirmwareLoader> */}
|
||||||
</StateProvider>
|
</StateProvider>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
:root {
|
|
||||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
color-scheme: light dark;
|
|
||||||
color: rgba(255, 255, 255, 0.87);
|
|
||||||
background-color: #242424;
|
|
||||||
|
|
||||||
font-synthesis: none;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
/* Gives declaration dropped warning */
|
|
||||||
/* -moz-osx-font-smoothing: grayscale; */
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-weight: 500;
|
|
||||||
color: #646cff;
|
|
||||||
text-decoration: inherit;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #535bf2;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
min-width: 320px;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 3.2em;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 0.6em 1.2em;
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: 500;
|
|
||||||
font-family: inherit;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: border-color 0.25s;
|
|
||||||
}
|
|
||||||
button:hover {
|
|
||||||
border-color: #646cff;
|
|
||||||
}
|
|
||||||
button:focus,
|
|
||||||
button:focus-visible {
|
|
||||||
/* Gives a warning: declaration dropped */
|
|
||||||
/* outline: 4px auto -webkit-focus-ring-color; */
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
|
||||||
:root {
|
|
||||||
color: #213547;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #747bff;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { StrictMode } from 'react'
|
import { StrictMode } from 'react'
|
||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client'
|
||||||
import './index.css'
|
|
||||||
import App from './App'
|
import App from './App'
|
||||||
|
|
||||||
// I don't consider providing a disabled button to a Tooltip an error.
|
// I don't consider providing a disabled button to a Tooltip an error.
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,10 @@ const useStyles = makeStyles((theme: Theme) => {
|
||||||
},
|
},
|
||||||
rowHover: {
|
rowHover: {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
// "&:hover": {
|
"&:hover": {
|
||||||
// backgroundColor: !isMobile && "rgba(150, 150, 150, 0.15)",
|
backgroundColor: "rgba(150, 150, 150, 0.15)",
|
||||||
// }
|
}
|
||||||
}
|
},
|
||||||
})},
|
})},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -314,7 +314,7 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
||||||
</Box>
|
</Box>
|
||||||
{rows.map((row, index) => {
|
{rows.map((row, index) => {
|
||||||
return (
|
return (
|
||||||
<Card className={classNames(classes.card, onRowClick&&classes.rowHover)} key={"mobile-card-"+index} onClick={() => onRowClick&&onRowClick(row)}>
|
<Card className={classNames(classes.card)} key={"mobile-card-"+index} onClick={() => onRowClick&&onRowClick(row)}>
|
||||||
{renderMobileRow(row)}
|
{renderMobileRow(row)}
|
||||||
{renderGutter &&
|
{renderGutter &&
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import {
|
||||||
import { usePrevious } from "hooks";
|
import { usePrevious } from "hooks";
|
||||||
import BindaptIcon from "products/Bindapt/BindaptIcon";
|
import BindaptIcon from "products/Bindapt/BindaptIcon";
|
||||||
import BinsIcon from "products/Bindapt/BinsIcon";
|
import BinsIcon from "products/Bindapt/BinsIcon";
|
||||||
import VentilationIcon from "products/ventilation/VentilationIcon";
|
|
||||||
import { useGlobalState } from "providers";
|
import { useGlobalState } from "providers";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useNavigate, useLocation } from "react-router-dom";
|
import { useNavigate, useLocation } from "react-router-dom";
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,12 @@
|
||||||
import React, { PropsWithChildren } from "react";
|
import React, { PropsWithChildren } from "react";
|
||||||
import Router from "./Router";
|
import Router from "./Router";
|
||||||
|
|
||||||
interface Props extends PropsWithChildren {
|
export default function NavigationContainer() {
|
||||||
toggleTheme: () => void;
|
|
||||||
// teams: Team[];
|
|
||||||
// setTeams: React.Dispatch<React.SetStateAction<Team[]>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function NavigationContainer(props: Props) {
|
|
||||||
// const { toggleTheme, teams, setTeams } = props;
|
|
||||||
const { toggleTheme } = props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{/* <NotificationBanner /> */}
|
{/* <NotificationBanner /> */}
|
||||||
<Router
|
<Router />
|
||||||
toggleTheme={toggleTheme}
|
|
||||||
/>
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,18 +40,13 @@ const Marketplace = lazy(() => import("userFeatures/UserFeatures"))
|
||||||
const Logs = lazy(() => import("pages/Logs"))
|
const Logs = lazy(() => import("pages/Logs"))
|
||||||
const Firmware = lazy(() => import("pages/Firmware"));
|
const Firmware = lazy(() => import("pages/Firmware"));
|
||||||
|
|
||||||
interface Props {
|
|
||||||
toggleTheme: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const appendToUrl = (appendage: number | string) => {
|
export const appendToUrl = (appendage: number | string) => {
|
||||||
const basePath = location.pathname.replace(/\/$/, "");
|
const basePath = location.pathname.replace(/\/$/, "");
|
||||||
return(`${basePath}/${appendage}`);
|
return(`${basePath}/${appendage}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Router(props: Props) {
|
export default function Router() {
|
||||||
|
|
||||||
const { toggleTheme } = props;
|
|
||||||
const { isAuthenticated, loginWithRedirect, isLoading } = useAuth0();
|
const { isAuthenticated, loginWithRedirect, isLoading } = useAuth0();
|
||||||
const whiteLabel = getWhitelabel();
|
const whiteLabel = getWhitelabel();
|
||||||
const [{ user }] = useGlobalState();
|
const [{ user }] = useGlobalState();
|
||||||
|
|
@ -292,11 +287,7 @@ export default function Router(props: Props) {
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={<LoadingScreen />}>
|
<Suspense fallback={<LoadingScreen />}>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Header
|
<Header />
|
||||||
toggleTheme={toggleTheme}
|
|
||||||
// teams={teams}
|
|
||||||
// setTeams={setTeams}
|
|
||||||
/>
|
|
||||||
<Routes>
|
<Routes>
|
||||||
|
|
||||||
{/* Redirects */}
|
{/* Redirects */}
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,9 @@ const STAGING_WHITELABEL: WhiteLabel = {
|
||||||
const BXT_WHITE_LABEL: WhiteLabel = {
|
const BXT_WHITE_LABEL: WhiteLabel = {
|
||||||
name: "Brand X Technologies",
|
name: "Brand X Technologies",
|
||||||
primaryColour: "blue",
|
primaryColour: "blue",
|
||||||
|
// primaryColour: "#0000FF",
|
||||||
secondaryColour: "yellow",
|
secondaryColour: "yellow",
|
||||||
|
// secondaryColour: "#FFFF00",
|
||||||
signatureColour: "#272727",
|
signatureColour: "#272727",
|
||||||
// signatureColour: "#005bb0",
|
// signatureColour: "#005bb0",
|
||||||
signatureAccentColour: "#fff",
|
signatureAccentColour: "#fff",
|
||||||
|
|
@ -116,7 +118,9 @@ export function isBXT(): boolean {
|
||||||
const ADAPTIVE_AGRICULTURE_WHITE_LABEL: WhiteLabel = {
|
const ADAPTIVE_AGRICULTURE_WHITE_LABEL: WhiteLabel = {
|
||||||
name: "Adaptive Agriculture",
|
name: "Adaptive Agriculture",
|
||||||
primaryColour: "green",
|
primaryColour: "green",
|
||||||
|
// primaryColour: "#008000",
|
||||||
secondaryColour: "yellow",
|
secondaryColour: "yellow",
|
||||||
|
// secondaryColour: "#FFFF00",
|
||||||
signatureColour: "#272727",
|
signatureColour: "#272727",
|
||||||
signatureAccentColour: "#fff",
|
signatureAccentColour: "#fff",
|
||||||
auth0ClientId: import.meta.env.REACT_APP_AUTH0_ADAPTIVE_AGRICULTURE_CLIENT_ID,
|
auth0ClientId: import.meta.env.REACT_APP_AUTH0_ADAPTIVE_AGRICULTURE_CLIENT_ID,
|
||||||
|
|
|
||||||
62
src/theme/AppThemeProvider.tsx
Normal file
62
src/theme/AppThemeProvider.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import React, { createContext, useContext, useMemo, useState, useEffect } from "react";
|
||||||
|
import { ThemeProvider, createTheme, PaletteMode } from "@mui/material/styles";
|
||||||
|
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||||
|
|
||||||
|
// --- You can import your own makePaletteColor() here if needed ---
|
||||||
|
|
||||||
|
type ThemeMode = "light" | "dark" | "system";
|
||||||
|
|
||||||
|
interface ThemeModeContextType {
|
||||||
|
mode: ThemeMode;
|
||||||
|
resolvedMode: PaletteMode; // actual value used
|
||||||
|
toggleMode: () => void;
|
||||||
|
setMode: (mode: ThemeMode) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ThemeModeContext = createContext<ThemeModeContextType | undefined>(undefined);
|
||||||
|
|
||||||
|
export const useThemeMode = () => {
|
||||||
|
const context = useContext(ThemeModeContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useThemeMode must be used within ThemeModeProvider");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AppThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||||
|
const [mode, setMode] = useState<ThemeMode>("system");
|
||||||
|
|
||||||
|
const prefersDark = useMediaQuery("(prefers-color-scheme: dark)");
|
||||||
|
const resolvedMode: PaletteMode = mode === "system" ? (prefersDark ? "dark" : "light") : mode;
|
||||||
|
|
||||||
|
const theme = useMemo(() => createTheme({
|
||||||
|
palette: {
|
||||||
|
mode: resolvedMode,
|
||||||
|
primary: { main: "#1976d2" }, // Or use makePaletteColor()
|
||||||
|
secondary: { main: "#e91e63" },
|
||||||
|
},
|
||||||
|
}), [resolvedMode]);
|
||||||
|
|
||||||
|
const toggleMode = () => {
|
||||||
|
setMode(prev =>
|
||||||
|
prev === "light" ? "dark" :
|
||||||
|
prev === "dark" ? "system" :
|
||||||
|
"light"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextValue = useMemo(() => ({
|
||||||
|
mode,
|
||||||
|
resolvedMode,
|
||||||
|
toggleMode,
|
||||||
|
setMode,
|
||||||
|
}), [mode, resolvedMode]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeModeContext.Provider value={contextValue}>
|
||||||
|
<ThemeProvider theme={theme}>
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
</ThemeModeContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
export * from "./text";
|
export * from "./text";
|
||||||
export { CreateTheme } from "./theme";
|
// export { CreateTheme } from "./theme";
|
||||||
export * from "./themeType";
|
export * from "./themeType";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
// src/theme.ts
|
||||||
import * as Colours from "@mui/material/colors"
|
import * as Colours from "@mui/material/colors"
|
||||||
import { createTheme, responsiveFontSizes, Theme, ThemeOptions } from '@mui/material/styles';
|
import { createTheme, ThemeOptions } from '@mui/material/styles';
|
||||||
import {
|
import {
|
||||||
getPrimaryColour,
|
getPrimaryColour,
|
||||||
getSecondaryColour,
|
getSecondaryColour,
|
||||||
|
|
@ -7,283 +8,55 @@ import {
|
||||||
getSignatureColour
|
getSignatureColour
|
||||||
} from "../services/whiteLabel";
|
} from "../services/whiteLabel";
|
||||||
|
|
||||||
export function CreateTheme(themeType: "light" | "dark"): Theme {
|
const baseTheme: ThemeOptions = {
|
||||||
return responsiveFontSizes(createTheme(options(themeType)));
|
palette: {
|
||||||
}
|
mode: 'light', // default mode; will be overridden by system if needed
|
||||||
|
primary: {
|
||||||
function generateBackgroundShades(themeType: "light" | "dark") {
|
main: '#1976d2',
|
||||||
if(themeType==="light") return ({
|
},
|
||||||
default: "#e9e9e9",
|
background: {
|
||||||
paper: "#fafafa",
|
default: '#ffffff',
|
||||||
})
|
paper: '#f5f5f5',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Add other options if needed
|
||||||
|
};
|
||||||
|
|
||||||
|
function makePaletteColor(name: keyof typeof Colours) {
|
||||||
|
if (name.startsWith("#")) {
|
||||||
|
return { main: name };
|
||||||
|
}
|
||||||
|
const ramp = Colours[name] as Record<number, string>; // e.g., blue[500], blue[300], etc.
|
||||||
|
// if (!ramp) {
|
||||||
|
|
||||||
|
// }
|
||||||
return {
|
return {
|
||||||
default: "#303030",
|
main: ramp[500],
|
||||||
paper: "#373737",
|
light: ramp[300],
|
||||||
|
dark: ramp[700],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function options(themeType: "light" | "dark"): ThemeOptions {
|
export const getTheme = (mode: 'light' | 'dark') =>
|
||||||
|
createTheme({
|
||||||
const signature = getSignatureColour();
|
...baseTheme,
|
||||||
const accent = getSignatureAccentColour();
|
|
||||||
const highlight = themeType === "light" ? "black" : "white";
|
|
||||||
const bg = generateBackgroundShades(themeType);
|
|
||||||
return {
|
|
||||||
cssVariables: true,
|
|
||||||
zIndex: {
|
|
||||||
modal: 1300,
|
|
||||||
popover: 1350
|
|
||||||
},
|
|
||||||
palette: {
|
palette: {
|
||||||
primary: Colours[getPrimaryColour() as keyof typeof Colours],
|
...baseTheme.palette,
|
||||||
secondary: Colours[getSecondaryColour() as keyof typeof Colours],
|
primary: makePaletteColor(getPrimaryColour()),
|
||||||
background: bg,
|
secondary: makePaletteColor(getSecondaryColour()),
|
||||||
mode: themeType,
|
mode,
|
||||||
bxt: {
|
...(mode === 'dark'
|
||||||
primaryBlue: "#005bb0",
|
? {
|
||||||
lightBlue: "#1a86ec",
|
background: {
|
||||||
darkBlue: "#081d55",
|
default: '#121212',
|
||||||
rubberDuckYellow: "#ffd45c"
|
paper: '#1e1e1e',
|
||||||
},
|
},
|
||||||
status: {
|
}
|
||||||
succes: "#4caf50",
|
: {
|
||||||
unknown: "0288d1",
|
background: {
|
||||||
unstable: "rgb(189, 200, 33)",
|
default: "#e9e9e9",
|
||||||
risk: "#ffd642",
|
paper: "#fafafa",
|
||||||
warning: "#ffb74d",
|
},
|
||||||
alert: "#f44336"
|
}),
|
||||||
}
|
|
||||||
},
|
},
|
||||||
typography: {
|
});
|
||||||
fontFamily: [
|
|
||||||
"Open Sans",
|
|
||||||
"-apple-system",
|
|
||||||
"BlinkMacSystemFont",
|
|
||||||
'"Segoe UI"',
|
|
||||||
'"Helvetica Neue"',
|
|
||||||
"Arial",
|
|
||||||
"sans-serif",
|
|
||||||
'"Apple Color Emoji"',
|
|
||||||
'"Segoe UI Emoji"',
|
|
||||||
'"Segoe UI Symbol"'
|
|
||||||
].join(",")
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
MuiAppBar: {
|
|
||||||
styleOverrides: {
|
|
||||||
colorPrimary: {
|
|
||||||
backgroundColor: signature,
|
|
||||||
color: accent,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiBottomNavigation: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
backgroundColor: signature
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
MuiBottomNavigationAction: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
backgroundColor: signature,
|
|
||||||
color: Colours["grey"][500],
|
|
||||||
"&$selected": {
|
|
||||||
color: accent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiCard: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
borderRadius: "5px",
|
|
||||||
"@media (min-width: 600px)": {
|
|
||||||
borderRadius: "7px"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
MuiChip: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
"@media (max-width: 600px)": {
|
|
||||||
height: "24px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
avatar: {
|
|
||||||
"@media (max-width: 600px)": {
|
|
||||||
height: "24px",
|
|
||||||
width: "24px"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiDialog: {
|
|
||||||
styleOverrides: {
|
|
||||||
paperFullScreen: {
|
|
||||||
overflowX: "hidden"
|
|
||||||
},
|
|
||||||
root: {
|
|
||||||
// zIndex: 1500
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiDrawer: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
zIndex: 1300
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiSlider: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
height: 5
|
|
||||||
},
|
|
||||||
thumb: {
|
|
||||||
height: 18,
|
|
||||||
width: 18,
|
|
||||||
marginTop: -6,
|
|
||||||
marginLeft: -9,
|
|
||||||
"&:focus,&:hover,&$active": {
|
|
||||||
boxShadow: "inherit"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
active: {},
|
|
||||||
valueLabel: {
|
|
||||||
left: "calc(-50% + 2px)"
|
|
||||||
},
|
|
||||||
track: {
|
|
||||||
height: 7,
|
|
||||||
borderRadius: 4
|
|
||||||
},
|
|
||||||
rail: {
|
|
||||||
height: 7,
|
|
||||||
borderRadius: 4
|
|
||||||
},
|
|
||||||
vertical: {
|
|
||||||
"& .MuiSlider-thumb": {
|
|
||||||
marginLeft: "-8px !important"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiStepper: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
background: "transparent"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiSwitch: {
|
|
||||||
styleOverrides: {
|
|
||||||
switchBase: {
|
|
||||||
color: Colours.grey[400],
|
|
||||||
"&$checked": {
|
|
||||||
color: Colours.grey[100]
|
|
||||||
},
|
|
||||||
"&$checked + $track": {
|
|
||||||
color: Colours.grey[100]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
checked: {},
|
|
||||||
track: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
MuiButton: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
'& .MuiTouchRipple-root': {
|
|
||||||
color: accent, // Customize ripple color here
|
|
||||||
// color: "white"
|
|
||||||
},
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: "rgba(125, 125, 125, 0.2)",
|
|
||||||
color: accent,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiListItemButton: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
'& .MuiTouchRipple-root': {
|
|
||||||
color: highlight,
|
|
||||||
},
|
|
||||||
'&:hover': {
|
|
||||||
color: highlight
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiCssBaseline: {
|
|
||||||
styleOverrides: {
|
|
||||||
body: {
|
|
||||||
backgroundColor: bg, // Set your desired background color
|
|
||||||
// color: '#333', // Optionally, you can also set the default text color
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiSvgIcon: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
// Set the default icon color for light mode
|
|
||||||
// color: "black", // Dark color for icons in light mode
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiLink: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
color: 'inherit', // Default link color
|
|
||||||
textDecoration: 'none', // Remove underline if desired
|
|
||||||
'&:hover': {
|
|
||||||
// color: 'red !important', // Your hover color
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
MuiToggleButtonGroup: {
|
|
||||||
styleOverrides: {
|
|
||||||
root: {
|
|
||||||
borderRadius: 25
|
|
||||||
},
|
|
||||||
middleButton: {
|
|
||||||
borderRadius: 24,
|
|
||||||
marginRight: 5,
|
|
||||||
marginLeft: 5,
|
|
||||||
},
|
|
||||||
lastButton: {
|
|
||||||
borderRadius: 24,
|
|
||||||
},
|
|
||||||
firstButton: {
|
|
||||||
borderRadius: 24,
|
|
||||||
},
|
|
||||||
grouped: {
|
|
||||||
border: "none",
|
|
||||||
color: "gray"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// MuiToggleButton: {
|
|
||||||
// styleOverrides: {
|
|
||||||
// root: {
|
|
||||||
// "&:hover": {
|
|
||||||
// backgroundColor: getPrimaryColour(),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// MuiDataGrid: {
|
|
||||||
// styleOverrides: {
|
|
||||||
// root: {
|
|
||||||
// backgroundColor: "black"
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
}
|
|
||||||
} as unknown as ThemeOptions;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,25 @@
|
||||||
export type ThemeType = "light" | "dark";
|
export type ThemeType = "light" | "dark" | "system";
|
||||||
|
|
||||||
export function getThemeType(): ThemeType {
|
export function getThemeType(): ThemeType {
|
||||||
let theme = localStorage.getItem("theme");
|
let mode = localStorage.getItem("theme")
|
||||||
return theme === "light" ? "light" : "dark";
|
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
|
if (mode === "system") {
|
||||||
|
if (prefersDark) return "dark"
|
||||||
|
if (!prefersDark) return "light"
|
||||||
|
}
|
||||||
|
return mode !== "light" ? "dark" : "light"
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setThemeType(theme: ThemeType) {
|
export function setThemeType(theme: ThemeType) {
|
||||||
localStorage.setItem("theme", theme);
|
localStorage.setItem("theme", theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getThemeMode(): ThemeType {
|
||||||
|
let mode = localStorage.getItem("theme")
|
||||||
|
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||||
|
if (mode === "system") {
|
||||||
|
if (prefersDark) return "dark"
|
||||||
|
if (!prefersDark) return "light"
|
||||||
|
}
|
||||||
|
return mode !== "light" ? "dark" : "light"
|
||||||
|
}
|
||||||
80
src/theme/theme_old.ts
Normal file
80
src/theme/theme_old.ts
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
import { createTheme, responsiveFontSizes, ThemeOptions } from "@mui/material";
|
||||||
|
|
||||||
|
export const options = (themeType: "light" | "dark"): ThemeOptions => ({
|
||||||
|
palette: {
|
||||||
|
mode: themeType,
|
||||||
|
...(themeType === "light"
|
||||||
|
? {
|
||||||
|
background: {
|
||||||
|
default: "#f5f5f5",
|
||||||
|
paper: "#fff"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
background: {
|
||||||
|
default: "#0c101b",
|
||||||
|
paper: "#1c1f26"
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
primary: {
|
||||||
|
main: "#00AEEF"
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#F39200"
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
main: "#e53935"
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
main: "#fdd835"
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
main: "#29b6f6"
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
main: "#43a047"
|
||||||
|
},
|
||||||
|
divider: "rgba(0, 0, 0, 0.12)"
|
||||||
|
},
|
||||||
|
typography: {
|
||||||
|
fontFamily: `"Roboto", "Helvetica", "Arial", sans-serif`,
|
||||||
|
fontSize: 14,
|
||||||
|
h1: {
|
||||||
|
fontSize: "2.5rem"
|
||||||
|
},
|
||||||
|
h2: {
|
||||||
|
fontSize: "2rem"
|
||||||
|
},
|
||||||
|
h3: {
|
||||||
|
fontSize: "1.75rem"
|
||||||
|
},
|
||||||
|
h4: {
|
||||||
|
fontSize: "1.5rem"
|
||||||
|
},
|
||||||
|
h5: {
|
||||||
|
fontSize: "1.25rem"
|
||||||
|
},
|
||||||
|
h6: {
|
||||||
|
fontSize: "1rem"
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
textTransform: "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
MuiCssBaseline: {
|
||||||
|
styleOverrides: {
|
||||||
|
body: {
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cssVarPrefix: "mui", // optional prefix for CSS vars
|
||||||
|
cssVariables: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create both themes once for reuse
|
||||||
|
export const lightTheme = responsiveFontSizes(createTheme(options("light")));
|
||||||
|
export const darkTheme = responsiveFontSizes(createTheme(options("dark")));
|
||||||
|
|
@ -14,6 +14,7 @@ import { useNavigate } from "react-router-dom";
|
||||||
import TeamDialog from "teams/TeamDialog";
|
import TeamDialog from "teams/TeamDialog";
|
||||||
import AccessObject from "./AccessObject";
|
import AccessObject from "./AccessObject";
|
||||||
import { useSnackbar, useUserAPI } from "hooks";
|
import { useSnackbar, useUserAPI } from "hooks";
|
||||||
|
import { useThemeMode } from "theme/AppThemeProvider";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => ({
|
const useStyles = makeStyles((theme: Theme) => ({
|
||||||
accessIcon: {
|
accessIcon: {
|
||||||
|
|
@ -72,14 +73,10 @@ const useStyles = makeStyles((theme: Theme) => ({
|
||||||
borderColor: getSignatureAccentColour()
|
borderColor: getSignatureAccentColour()
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
interface Props {
|
|
||||||
toggleTheme: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function UserMenu(props: Props) {
|
export default function UserMenu() {
|
||||||
|
|
||||||
const { toggleTheme } = props;
|
const { toggleMode } = useThemeMode()
|
||||||
const [{ user, team, as }, dispatch] = useGlobalState();
|
const [{ user, team, as }, dispatch] = useGlobalState();
|
||||||
const { loginWithRedirect } = useAuth0();
|
const { loginWithRedirect } = useAuth0();
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
@ -167,7 +164,7 @@ export default function UserMenu(props: Props) {
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<IconButton onClick={toggleTheme} className={classes.rightIcon} aria-label="Toggle Theme">
|
<IconButton onClick={/*toggleMode*/ () => {}} className={classes.rightIcon} aria-label="Toggle Theme">
|
||||||
<ThemeIcon />
|
<ThemeIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</>
|
</>
|
||||||
|
|
@ -229,12 +226,12 @@ export default function UserMenu(props: Props) {
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary="User Settings" />
|
<ListItemText primary="User Settings" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem onClick={toggleTheme} aria-label="Toggle Theme" dense>
|
{/* <MenuItem onClick={toggleMode} aria-label="Toggle Theme" dense>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<ThemeIcon />
|
<ThemeIcon />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary="Toggle Theme" />
|
<ListItemText primary="Toggle Theme" />
|
||||||
</MenuItem>
|
</MenuItem> */}
|
||||||
{hasTeams && (
|
{hasTeams && (
|
||||||
<MenuItem onClick={openTeamDialog} aria-label="Open Team Menu" dense>
|
<MenuItem onClick={openTeamDialog} aria-label="Open Team Menu" dense>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,9 @@ import {
|
||||||
Notifications as NotificationsIcon,
|
Notifications as NotificationsIcon,
|
||||||
Email as EmailIcon,
|
Email as EmailIcon,
|
||||||
Textsms as TextIcon,
|
Textsms as TextIcon,
|
||||||
|
Contrast,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import { AppBar, Box, Button, Checkbox, CircularProgress, Collapse, Divider, FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel, Grid2, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Radio, RadioGroup, TextField, Theme, Toolbar, Tooltip, Typography } from "@mui/material";
|
import { AppBar, Box, Button, Checkbox, CircularProgress, Collapse, Divider, FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel, Grid2, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Radio, RadioGroup, TextField, Theme, ToggleButton, ToggleButtonGroup, Toolbar, Tooltip, Typography } from "@mui/material";
|
||||||
import ResponsiveDialog from "common/ResponsiveDialog";
|
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||||
import UserAvatar from "./UserAvatar";
|
import UserAvatar from "./UserAvatar";
|
||||||
import { useGlobalState, useUserAPI } from "providers";
|
import { useGlobalState, useUserAPI } from "providers";
|
||||||
|
|
@ -24,6 +25,9 @@ import {Option as OptionType} from "common/SearchSelect";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { IconPicker } from "common/IconPicker";
|
import { IconPicker } from "common/IconPicker";
|
||||||
import { MuiTelInput } from "mui-tel-input";
|
import { MuiTelInput } from "mui-tel-input";
|
||||||
|
import { useThemeMode } from "theme/AppThemeProvider";
|
||||||
|
import ContractsIcon from "products/CommonIcons/contractIcon";
|
||||||
|
import { setThemeType } from "theme";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => {
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
return ({
|
return ({
|
||||||
|
|
@ -61,6 +65,7 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function UserSettings(props: Props) {
|
export default function UserSettings(props: Props) {
|
||||||
|
const themeMode = useThemeMode()
|
||||||
const { isOpen, closeDialogCallback } = props;
|
const { isOpen, closeDialogCallback } = props;
|
||||||
const [globalState, dispatch] = useGlobalState()
|
const [globalState, dispatch] = useGlobalState()
|
||||||
const [sharing, setSharing] = useState(false)
|
const [sharing, setSharing] = useState(false)
|
||||||
|
|
@ -73,6 +78,7 @@ export default function UserSettings(props: Props) {
|
||||||
const [avatarExpanded, setAvatarExpanded] = useState<boolean>(false);
|
const [avatarExpanded, setAvatarExpanded] = useState<boolean>(false);
|
||||||
const [notificationsExpanded, setNotificationsExpanded] = useState<boolean>(false);
|
const [notificationsExpanded, setNotificationsExpanded] = useState<boolean>(false);
|
||||||
const [avatarUrl, setAvatarUrl] = useState<string>("");
|
const [avatarUrl, setAvatarUrl] = useState<string>("");
|
||||||
|
const [themeValue, setThemeValue] = useState<"light" | "dark" | "system">(themeMode.mode)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function changeIcon(icon: string | undefined) {
|
function changeIcon(icon: string | undefined) {
|
||||||
|
|
@ -350,9 +356,47 @@ export default function UserSettings(props: Props) {
|
||||||
return <IconPicker url={user.settings.avatar} setUrl={setAvatarUrl} id={user.settings.id} />;
|
return <IconPicker url={user.settings.avatar} setUrl={setAvatarUrl} id={user.settings.id} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleChange = (event: React.MouseEvent<HTMLElement>, theme: "light" | "dark" | "system") => {
|
||||||
|
event.preventDefault()
|
||||||
|
themeMode.setMode(theme)
|
||||||
|
setThemeType(theme)
|
||||||
|
};
|
||||||
|
|
||||||
|
const themeToggle = () => {
|
||||||
|
return (
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={themeMode.mode}
|
||||||
|
exclusive
|
||||||
|
onChange={handleChange}
|
||||||
|
size="small"
|
||||||
|
sx={{margin:-1}}
|
||||||
|
>
|
||||||
|
<ToggleButton value="light">
|
||||||
|
light
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton value="system">
|
||||||
|
system
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton value="dark">
|
||||||
|
dark
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const settingsList = () => {
|
const settingsList = () => {
|
||||||
return (
|
return (
|
||||||
<List disablePadding>
|
<List disablePadding>
|
||||||
|
<ListItem >
|
||||||
|
<ListItemIcon>
|
||||||
|
<Contrast />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={"Theme"} />
|
||||||
|
{themeToggle()}
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
<ListItemButton onClick={() => setProfileExpanded(!profileExpanded)}>
|
<ListItemButton onClick={() => setProfileExpanded(!profileExpanded)}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<AccountBox />
|
<AccountBox />
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue