Separate Client Portal & Dashboard
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
// @mui
|
||||
import { alpha, styled } from '@mui/material/styles';
|
||||
import { Box, Grid, RadioGroup, CardActionArea } from '@mui/material';
|
||||
// hooks
|
||||
import useSettings from '../../hooks/useSettings';
|
||||
//
|
||||
import { BoxMask } from '.';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const BoxStyle = styled(CardActionArea)(({ theme }) => ({
|
||||
height: 48,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: theme.palette.text.disabled,
|
||||
border: `solid 1px ${theme.palette.grey[500_12]}`,
|
||||
borderRadius: Number(theme.shape.borderRadius) * 1.25,
|
||||
}));
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function SettingColorPresets() {
|
||||
const { themeColorPresets, onChangeColor, colorOption } = useSettings();
|
||||
|
||||
return (
|
||||
<RadioGroup name="themeColorPresets" value={themeColorPresets} onChange={onChangeColor}>
|
||||
<Grid dir="ltr" container spacing={1.5}>
|
||||
{colorOption.map((color) => {
|
||||
const colorName = color.name;
|
||||
const colorValue = color.value;
|
||||
const isSelected = themeColorPresets === colorName;
|
||||
|
||||
return (
|
||||
<Grid key={colorName} item xs={4}>
|
||||
<BoxStyle
|
||||
sx={{
|
||||
...(isSelected && {
|
||||
bgcolor: alpha(colorValue, 0.08),
|
||||
border: `solid 2px ${colorValue}`,
|
||||
boxShadow: `inset 0 4px 8px 0 ${alpha(colorValue, 0.24)}`,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: 24,
|
||||
height: 14,
|
||||
borderRadius: '50%',
|
||||
bgcolor: colorValue,
|
||||
transform: 'rotate(-45deg)',
|
||||
transition: (theme) =>
|
||||
theme.transitions.create('all', {
|
||||
easing: theme.transitions.easing.easeInOut,
|
||||
duration: theme.transitions.duration.shorter,
|
||||
}),
|
||||
...(isSelected && { transform: 'none' }),
|
||||
}}
|
||||
/>
|
||||
|
||||
<BoxMask value={colorName} />
|
||||
</BoxStyle>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
</RadioGroup>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// @mui
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { Grid, RadioGroup, CardActionArea } from '@mui/material';
|
||||
// hooks
|
||||
import useSettings from '../../hooks/useSettings';
|
||||
//
|
||||
import Iconify from '../Iconify';
|
||||
import { BoxMask } from '.';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const BoxStyle = styled(CardActionArea)(({ theme }) => ({
|
||||
height: 72,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: theme.palette.text.disabled,
|
||||
border: `solid 1px ${theme.palette.grey[500_12]}`,
|
||||
borderRadius: Number(theme.shape.borderRadius) * 1.25,
|
||||
}));
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function SettingDirection() {
|
||||
const { themeDirection, onChangeDirection } = useSettings();
|
||||
|
||||
return (
|
||||
<RadioGroup name="themeDirection" value={themeDirection} onChange={onChangeDirection}>
|
||||
<Grid dir="ltr" container spacing={2.5}>
|
||||
{['ltr', 'rtl'].map((direction, index) => {
|
||||
const isSelected = themeDirection === direction;
|
||||
|
||||
return (
|
||||
<Grid key={direction} item xs={6}>
|
||||
<BoxStyle
|
||||
sx={{
|
||||
...(isSelected && {
|
||||
color: 'primary.main',
|
||||
boxShadow: (theme) => theme.customShadows.z20,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Iconify
|
||||
icon={index === 0 ? 'ph:align-left-duotone' : 'ph:align-right-duotone'}
|
||||
width={28}
|
||||
height={28}
|
||||
/>
|
||||
<BoxMask value={direction} />
|
||||
</BoxStyle>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
</RadioGroup>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { useState } from 'react';
|
||||
// @mui
|
||||
import { alpha } from '@mui/material/styles';
|
||||
import { Button } from '@mui/material';
|
||||
// components
|
||||
import Iconify from '../Iconify';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function SettingFullscreen() {
|
||||
const [fullscreen, setFullscreen] = useState(false);
|
||||
|
||||
const toggleFullScreen = () => {
|
||||
if (!document.fullscreenElement) {
|
||||
document.documentElement.requestFullscreen();
|
||||
setFullscreen(true);
|
||||
} else if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
setFullscreen(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
fullWidth
|
||||
size="large"
|
||||
variant="outlined"
|
||||
color={fullscreen ? 'primary' : 'inherit'}
|
||||
startIcon={<Iconify icon={fullscreen ? 'ic:round-fullscreen-exit' : 'ic:round-fullscreen'} />}
|
||||
onClick={toggleFullScreen}
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
...(fullscreen && {
|
||||
bgcolor: (theme) =>
|
||||
alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{fullscreen ? 'Exit Fullscreen' : 'Fullscreen'}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
138
frontend/dashboard/src/components/settings/SettingLayout.tsx
Normal file
138
frontend/dashboard/src/components/settings/SettingLayout.tsx
Normal file
@@ -0,0 +1,138 @@
|
||||
// @mui
|
||||
import { styled, alpha } from '@mui/material/styles';
|
||||
import { Grid, RadioGroup, CardActionArea, Box, Stack } from '@mui/material';
|
||||
// hooks
|
||||
import useSettings from '../../hooks/useSettings';
|
||||
//
|
||||
import { BoxMask } from '.';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const BoxStyle = styled(CardActionArea)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
padding: theme.spacing(1.5),
|
||||
color: theme.palette.text.disabled,
|
||||
border: `solid 1px ${theme.palette.grey[500_12]}`,
|
||||
borderRadius: Number(theme.shape.borderRadius) * 1.25,
|
||||
}));
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function SettingLayout() {
|
||||
const { themeLayout, onChangeLayout } = useSettings();
|
||||
|
||||
return (
|
||||
<RadioGroup name="themeLayout" value={themeLayout} onChange={onChangeLayout}>
|
||||
<Grid dir="ltr" container spacing={2.5}>
|
||||
{['horizontal', 'vertical'].map((layout) => {
|
||||
const isSelected = themeLayout === layout;
|
||||
const isVertical = layout === 'vertical';
|
||||
|
||||
return (
|
||||
<Grid key={layout} item xs={6}>
|
||||
<BoxStyle
|
||||
sx={{
|
||||
...(isSelected && {
|
||||
color: 'primary.main',
|
||||
boxShadow: (theme) => theme.customShadows.z20,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{isVertical ? (
|
||||
<VerticalBox isSelected={isSelected} />
|
||||
) : (
|
||||
<HorizontalBox isSelected={isSelected} />
|
||||
)}
|
||||
<BoxMask value={layout} />
|
||||
</BoxStyle>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
</RadioGroup>
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type LayoutBoxProps = {
|
||||
isSelected: boolean;
|
||||
};
|
||||
|
||||
const style = {
|
||||
width: 1,
|
||||
height: 32,
|
||||
borderRadius: 0.5,
|
||||
};
|
||||
|
||||
function VerticalBox({ isSelected }: LayoutBoxProps) {
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
...style,
|
||||
mb: 0.75,
|
||||
height: 12,
|
||||
bgcolor: (theme) => alpha(theme.palette.text.disabled, 0.72),
|
||||
...(isSelected && {
|
||||
bgcolor: (theme) => alpha(theme.palette.primary.main, 0.72),
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
...style,
|
||||
border: (theme) => `dashed 1px ${theme.palette.divider}`,
|
||||
bgcolor: (theme) => alpha(theme.palette.text.disabled, 0.08),
|
||||
...(isSelected && {
|
||||
border: (theme) => `dashed 1px ${theme.palette.primary.main}`,
|
||||
bgcolor: (theme) => alpha(theme.palette.primary.main, 0.16),
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function HorizontalBox({ isSelected }: LayoutBoxProps) {
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
...style,
|
||||
mb: 0.75,
|
||||
height: 12,
|
||||
bgcolor: (theme) => alpha(theme.palette.text.disabled, 0.72),
|
||||
...(isSelected && {
|
||||
bgcolor: (theme) => alpha(theme.palette.primary.main, 0.72),
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
<Stack width={1} direction="row" justifyContent="space-between">
|
||||
<Box
|
||||
sx={{
|
||||
...style,
|
||||
width: 20,
|
||||
bgcolor: (theme) => alpha(theme.palette.text.disabled, 0.32),
|
||||
...(isSelected && {
|
||||
bgcolor: (theme) => alpha(theme.palette.primary.main, 0.32),
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
...style,
|
||||
width: `calc(100% - 26px)`,
|
||||
border: (theme) => `dashed 1px ${theme.palette.divider}`,
|
||||
bgcolor: (theme) => alpha(theme.palette.text.disabled, 0.08),
|
||||
...(isSelected && {
|
||||
border: (theme) => `dashed 1px ${theme.palette.primary.main}`,
|
||||
bgcolor: (theme) => alpha(theme.palette.primary.main, 0.16),
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
57
frontend/dashboard/src/components/settings/SettingMode.tsx
Normal file
57
frontend/dashboard/src/components/settings/SettingMode.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
// @mui
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { Grid, RadioGroup, CardActionArea } from '@mui/material';
|
||||
// hooks
|
||||
import useSettings from '../../hooks/useSettings';
|
||||
//
|
||||
import Iconify from '../Iconify';
|
||||
import { BoxMask } from '.';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const BoxStyle = styled(CardActionArea)(({ theme }) => ({
|
||||
height: 72,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: theme.palette.text.disabled,
|
||||
border: `solid 1px ${theme.palette.grey[500_12]}`,
|
||||
borderRadius: Number(theme.shape.borderRadius) * 1.25,
|
||||
}));
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function SettingMode() {
|
||||
const { themeMode, onChangeMode } = useSettings();
|
||||
|
||||
return (
|
||||
<RadioGroup name="themeMode" value={themeMode} onChange={onChangeMode}>
|
||||
<Grid dir="ltr" container spacing={2.5}>
|
||||
{['light', 'dark'].map((mode, index) => {
|
||||
const isSelected = themeMode === mode;
|
||||
|
||||
return (
|
||||
<Grid key={mode} item xs={6}>
|
||||
<BoxStyle
|
||||
sx={{
|
||||
bgcolor: mode === 'light' ? 'common.white' : 'grey.800',
|
||||
...(isSelected && {
|
||||
color: 'primary.main',
|
||||
boxShadow: (theme) => theme.customShadows.z20,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Iconify
|
||||
icon={index === 0 ? 'ph:sun-duotone' : 'ph:moon-duotone'}
|
||||
width={28}
|
||||
height={28}
|
||||
/>
|
||||
<BoxMask value={mode} />
|
||||
</BoxStyle>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
</RadioGroup>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// @mui
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { CardActionArea, Stack } from '@mui/material';
|
||||
// hooks
|
||||
import useSettings from '../../hooks/useSettings';
|
||||
//
|
||||
import Iconify from '../Iconify';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const BoxStyle = styled(CardActionArea)(({ theme }) => ({
|
||||
padding: theme.spacing(2),
|
||||
color: theme.palette.text.disabled,
|
||||
border: `solid 1px ${theme.palette.grey[500_12]}`,
|
||||
backgroundColor: theme.palette.background.neutral,
|
||||
borderRadius: Number(theme.shape.borderRadius) * 1.25,
|
||||
}));
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function SettingStretch() {
|
||||
const { themeStretch, onToggleStretch } = useSettings();
|
||||
|
||||
const ICON_SIZE = {
|
||||
width: themeStretch ? 24 : 18,
|
||||
height: themeStretch ? 24 : 18,
|
||||
};
|
||||
|
||||
return (
|
||||
<BoxStyle
|
||||
onClick={onToggleStretch}
|
||||
sx={{
|
||||
...(themeStretch && {
|
||||
color: (theme) => theme.palette.primary.main,
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
sx={{
|
||||
px: 1,
|
||||
mx: 'auto',
|
||||
width: 0.5,
|
||||
height: 40,
|
||||
borderRadius: 1,
|
||||
color: 'action.active',
|
||||
bgcolor: 'background.default',
|
||||
boxShadow: (theme) => theme.customShadows.z12,
|
||||
transition: (theme) => theme.transitions.create('width'),
|
||||
...(themeStretch && {
|
||||
width: 1,
|
||||
color: 'primary.main',
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Iconify
|
||||
icon={themeStretch ? 'eva:arrow-ios-back-fill' : 'eva:arrow-ios-forward-fill'}
|
||||
{...ICON_SIZE}
|
||||
/>
|
||||
<Iconify
|
||||
icon={themeStretch ? 'eva:arrow-ios-forward-fill' : 'eva:arrow-ios-back-fill'}
|
||||
{...ICON_SIZE}
|
||||
/>
|
||||
</Stack>
|
||||
</BoxStyle>
|
||||
);
|
||||
}
|
||||
69
frontend/dashboard/src/components/settings/ToggleButton.tsx
Normal file
69
frontend/dashboard/src/components/settings/ToggleButton.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
// @mui
|
||||
import { alpha, styled } from '@mui/material/styles';
|
||||
import { Tooltip } from '@mui/material';
|
||||
// utils
|
||||
import cssStyles from '../../utils/cssStyles';
|
||||
//
|
||||
import Iconify from '../Iconify';
|
||||
import { IconButtonAnimate } from '../animate';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const RootStyle = styled('span')(({ theme }) => ({
|
||||
...cssStyles(theme).bgBlur({ opacity: 0.64 }),
|
||||
right: 0,
|
||||
top: '50%',
|
||||
position: 'fixed',
|
||||
marginTop: theme.spacing(-3),
|
||||
padding: theme.spacing(0.5),
|
||||
zIndex: theme.zIndex.drawer + 2,
|
||||
borderRadius: '24px 0 20px 24px',
|
||||
boxShadow: `-12px 12px 32px -4px ${alpha(
|
||||
theme.palette.mode === 'light' ? theme.palette.grey[600] : theme.palette.common.black,
|
||||
0.36
|
||||
)}`,
|
||||
}));
|
||||
|
||||
const DotStyle = styled('span')(({ theme }) => ({
|
||||
top: 8,
|
||||
width: 8,
|
||||
height: 8,
|
||||
right: 10,
|
||||
borderRadius: '50%',
|
||||
position: 'absolute',
|
||||
backgroundColor: theme.palette.error.main,
|
||||
}));
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type Props = {
|
||||
open: boolean;
|
||||
notDefault: boolean;
|
||||
onToggle: VoidFunction;
|
||||
};
|
||||
|
||||
export default function ToggleButton({ notDefault, open, onToggle }: Props) {
|
||||
return (
|
||||
<RootStyle>
|
||||
{notDefault && !open && <DotStyle />}
|
||||
|
||||
<Tooltip title="Settings" placement="left">
|
||||
<IconButtonAnimate
|
||||
color="inherit"
|
||||
onClick={onToggle}
|
||||
sx={{
|
||||
p: 1.25,
|
||||
transition: (theme) => theme.transitions.create('all'),
|
||||
'&:hover': {
|
||||
color: 'primary.main',
|
||||
bgcolor: (theme) =>
|
||||
alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity),
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Iconify icon="eva:options-2-fill" width={20} height={20} />
|
||||
</IconButtonAnimate>
|
||||
</Tooltip>
|
||||
</RootStyle>
|
||||
);
|
||||
}
|
||||
189
frontend/dashboard/src/components/settings/index.tsx
Normal file
189
frontend/dashboard/src/components/settings/index.tsx
Normal file
@@ -0,0 +1,189 @@
|
||||
import { AnimatePresence, m } from 'framer-motion';
|
||||
import { useState, useEffect } from 'react';
|
||||
// @mui
|
||||
import { alpha, styled } from '@mui/material/styles';
|
||||
import { Backdrop, Divider, Typography, Stack, FormControlLabel, Radio } from '@mui/material';
|
||||
// hooks
|
||||
import useSettings from '../../hooks/useSettings';
|
||||
// utils
|
||||
import cssStyles from '../../utils/cssStyles';
|
||||
// config
|
||||
import { NAVBAR, defaultSettings } from '../../config';
|
||||
//
|
||||
import Iconify from '../Iconify';
|
||||
import Scrollbar from '../Scrollbar';
|
||||
import { IconButtonAnimate, varFade } from '../animate';
|
||||
//
|
||||
import ToggleButton from './ToggleButton';
|
||||
import SettingMode from './SettingMode';
|
||||
import SettingLayout from './SettingLayout';
|
||||
import SettingStretch from './SettingStretch';
|
||||
import SettingDirection from './SettingDirection';
|
||||
import SettingFullscreen from './SettingFullscreen';
|
||||
import SettingColorPresets from './SettingColorPresets';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const RootStyle = styled(m.div)(({ theme }) => ({
|
||||
...cssStyles(theme).bgBlur({ color: theme.palette.background.paper, opacity: 0.92 }),
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
display: 'flex',
|
||||
position: 'fixed',
|
||||
overflow: 'hidden',
|
||||
width: NAVBAR.BASE_WIDTH,
|
||||
flexDirection: 'column',
|
||||
margin: theme.spacing(2),
|
||||
paddingBottom: theme.spacing(3),
|
||||
zIndex: theme.zIndex.drawer + 3,
|
||||
borderRadius: Number(theme.shape.borderRadius) * 1.5,
|
||||
boxShadow: `-24px 12px 32px -4px ${alpha(
|
||||
theme.palette.mode === 'light' ? theme.palette.grey[500] : theme.palette.common.black,
|
||||
0.16
|
||||
)}`,
|
||||
}));
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function Settings() {
|
||||
const {
|
||||
themeMode,
|
||||
themeDirection,
|
||||
themeColorPresets,
|
||||
themeStretch,
|
||||
themeLayout,
|
||||
onResetSetting,
|
||||
} = useSettings();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const notDefault =
|
||||
themeMode !== defaultSettings.themeMode ||
|
||||
themeDirection !== defaultSettings.themeDirection ||
|
||||
themeColorPresets !== defaultSettings.themeColorPresets ||
|
||||
themeLayout !== defaultSettings.themeLayout ||
|
||||
themeStretch !== defaultSettings.themeStretch;
|
||||
|
||||
const varSidebar =
|
||||
themeDirection !== 'rtl'
|
||||
? varFade({
|
||||
distance: NAVBAR.BASE_WIDTH,
|
||||
durationIn: 0.32,
|
||||
durationOut: 0.32,
|
||||
}).inRight
|
||||
: varFade({
|
||||
distance: NAVBAR.BASE_WIDTH,
|
||||
durationIn: 0.32,
|
||||
durationOut: 0.32,
|
||||
}).inLeft;
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
document.body.style.overflow = 'hidden';
|
||||
} else {
|
||||
document.body.style.overflow = 'unset';
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const handleToggle = () => {
|
||||
setOpen((prev) => !prev);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Backdrop
|
||||
open={open}
|
||||
onClick={handleClose}
|
||||
sx={{ background: 'transparent', zIndex: (theme) => theme.zIndex.drawer + 1 }}
|
||||
/>
|
||||
|
||||
{!open && <ToggleButton open={open} notDefault={notDefault} onToggle={handleToggle} />}
|
||||
|
||||
<AnimatePresence>
|
||||
{open && (
|
||||
<>
|
||||
<RootStyle {...varSidebar}>
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
sx={{ py: 2, pr: 1, pl: 2.5 }}
|
||||
>
|
||||
<Typography variant="subtitle1">Settings</Typography>
|
||||
<div>
|
||||
<IconButtonAnimate onClick={onResetSetting}>
|
||||
<Iconify icon={'ic:round-refresh'} width={20} height={20} />
|
||||
</IconButtonAnimate>
|
||||
<IconButtonAnimate onClick={handleClose}>
|
||||
<Iconify icon={'eva:close-fill'} width={20} height={20} />
|
||||
</IconButtonAnimate>
|
||||
</div>
|
||||
</Stack>
|
||||
|
||||
<Divider sx={{ borderStyle: 'dashed' }} />
|
||||
|
||||
<Scrollbar sx={{ flexGrow: 1 }}>
|
||||
<Stack spacing={3} sx={{ p: 3 }}>
|
||||
<Stack spacing={1.5}>
|
||||
<Typography variant="subtitle2">Mode</Typography>
|
||||
<SettingMode />
|
||||
</Stack>
|
||||
|
||||
<Stack spacing={1.5}>
|
||||
<Typography variant="subtitle2">Direction</Typography>
|
||||
<SettingDirection />
|
||||
</Stack>
|
||||
|
||||
<Stack spacing={1.5}>
|
||||
<Typography variant="subtitle2">Layout</Typography>
|
||||
<SettingLayout />
|
||||
</Stack>
|
||||
|
||||
<Stack spacing={1.5}>
|
||||
<Typography variant="subtitle2">Presets</Typography>
|
||||
<SettingColorPresets />
|
||||
</Stack>
|
||||
|
||||
<Stack spacing={1.5}>
|
||||
<Typography variant="subtitle2">Stretch</Typography>
|
||||
<SettingStretch />
|
||||
</Stack>
|
||||
|
||||
<SettingFullscreen />
|
||||
</Stack>
|
||||
</Scrollbar>
|
||||
</RootStyle>
|
||||
</>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type Props = {
|
||||
value: string;
|
||||
};
|
||||
|
||||
export function BoxMask({ value }: Props) {
|
||||
return (
|
||||
<FormControlLabel
|
||||
label=""
|
||||
value={value}
|
||||
control={<Radio sx={{ display: 'none' }} />}
|
||||
sx={{
|
||||
m: 0,
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
position: 'absolute',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
45
frontend/dashboard/src/components/settings/type.ts
Normal file
45
frontend/dashboard/src/components/settings/type.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export type ThemeMode = 'light' | 'dark';
|
||||
export type ThemeDirection = 'rtl' | 'ltr';
|
||||
export type ThemeColorPresets = 'default' | 'purple' | 'cyan' | 'blue' | 'orange' | 'red';
|
||||
export type ThemeLayout = 'vertical' | 'horizontal';
|
||||
export type ThemeStretch = boolean;
|
||||
|
||||
type ColorVariants = {
|
||||
name: string;
|
||||
lighter: string;
|
||||
light: string;
|
||||
main: string;
|
||||
dark: string;
|
||||
darker: string;
|
||||
contrastText: string;
|
||||
};
|
||||
|
||||
export type SettingsValueProps = {
|
||||
themeMode: ThemeMode;
|
||||
themeDirection: ThemeDirection;
|
||||
themeColorPresets: ThemeColorPresets;
|
||||
themeStretch: ThemeStretch;
|
||||
themeLayout: ThemeLayout;
|
||||
};
|
||||
|
||||
export type SettingsContextProps = {
|
||||
themeMode: ThemeMode;
|
||||
themeDirection: ThemeDirection;
|
||||
themeColorPresets: ThemeColorPresets;
|
||||
themeLayout: ThemeLayout;
|
||||
themeStretch: boolean;
|
||||
setColor: ColorVariants;
|
||||
colorOption: {
|
||||
name: string;
|
||||
value: string;
|
||||
}[];
|
||||
onToggleMode: VoidFunction;
|
||||
onToggleStretch: VoidFunction;
|
||||
onResetSetting: VoidFunction;
|
||||
onChangeMode: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
onChangeDirection: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
onChangeColor: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
onChangeLayout: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
};
|
||||
Reference in New Issue
Block a user