This commit is contained in:
koh 2024-02-19 09:20:54 +07:00
commit 56f925190d
183 changed files with 19479 additions and 0 deletions

15
.editorconfig Normal file
View File

@ -0,0 +1,15 @@
# Editor configuration, see http://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false
[*.yml]
[*.{yml,yaml}]
indent_size = 2

58
.eslintrc.js Normal file
View File

@ -0,0 +1,58 @@
module.exports = {
env: {
node: true,
es6: true,
browser: true
},
parser: 'babel-eslint',
extends: ['next/core-web-vitals', 'prettier'],
parserOptions: {
ecmaVersion: 11,
sourceType: 'module',
project: './jsconfig.json',
ecmaFeatures: {
jsx: true,
modules: true,
experimentalObjectRestSpread: true
}
},
rules: {
'react/react-in-jsx-scope': 'off',
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
'react/display-name': 'off',
'@next/next/no-img-element': 'off',
'react/no-unescaped-entities': 'off',
'import/no-anonymous-default-export': 'off',
// add new line above comment
'lines-around-comment': [
'error',
{
beforeLineComment: true,
beforeBlockComment: true,
allowBlockStart: true,
allowClassStart: true,
allowObjectStart: true,
allowArrayStart: true
}
],
// add new line above return
'newline-before-return': 'error',
// add new line below import
'import/newline-after-import': [
'error',
{
count: 1
}
],
// add new line after each var, const, let declaration
'padding-line-between-statements': [
'error',
{ blankLine: 'always', prev: ['export'], next: ['*'] },
{ blankLine: 'always', prev: ['*'], next: ['multiline-const', 'multiline-let', 'multiline-var', 'export'] }
]
}
}

37
.gitignore vendored Normal file
View File

@ -0,0 +1,37 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# vercel
.vercel
# typescript
*.tsbuildinfo

17
.prettierrc.js Normal file
View File

@ -0,0 +1,17 @@
module.exports = {
arrowParens: 'avoid',
bracketSpacing: true,
htmlWhitespaceSensitivity: 'css',
insertPragma: false,
bracketSameLine: false,
jsxSingleQuote: true,
printWidth: 120,
proseWrap: 'preserve',
quoteProps: 'as-needed',
requirePragma: false,
semi: false,
singleQuote: true,
tabWidth: 2,
trailingComma: 'none',
useTabs: false
}

8
jsconfig.json Normal file
View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"baseUrl": "."
},
"include": [
"src"
]
}

6
next-env.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

18
next.config.js Normal file
View File

@ -0,0 +1,18 @@
const path = require('path')
module.exports = {
trailingSlash: true,
reactStrictMode: false,
experimental: {
esmExternals: false,
jsconfigPaths: true // enables it for both jsconfig.json and tsconfig.json
},
webpack: config => {
config.resolve.alias = {
...config.resolve.alias,
apexcharts: path.resolve(__dirname, './node_modules/apexcharts-clevision')
}
return config
}
}

6430
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

76
package.json Normal file
View File

@ -0,0 +1,76 @@
{
"name": "materio-mui-react-nextjs-admin-template-free",
"description": "Most Powerful & Comprehensive Free MUI React NextJS Admin Dashboard Template built for developers! 🚀",
"license": "MIT",
"version": "1.0.0",
"author": {
"name": "ThemeSelection",
"url": "https://themeselection.com/"
},
"bugs": {
"url": "https://github.com/themeselection/materio-mui-react-nextjs-admin-template-free/issues"
},
"private": false,
"repository": {
"type": "git",
"url": "https://github.com/themeselection/materio-mui-react-nextjs-admin-template-free.git"
},
"homepage": "https://themeselection.com/products/materio-free-mui-react-nextjs-admin-template/",
"keywords": [
"react",
"javascript",
"admin",
"dashboard",
"material-design",
"nextjs",
"material-ui",
"admin-dashboard",
"free",
"mui",
"admin-template",
"admin-panel",
"freebies",
"nextjs-template",
"react-dashboard",
"themeselection"
],
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"export": "next export",
"lint": "eslint --fix \"src/**/*.{js,jsx}\"",
"format": "prettier --write \"src/**/*.{js,jsx}\""
},
"dependencies": {
"@emotion/cache": "^11.6.0",
"@emotion/react": "^11.7.0",
"@emotion/server": "^11.4.0",
"@emotion/styled": "^11.6.0",
"@mui/lab": "^5.0.0-alpha.70",
"@mui/material": "^5.4.3",
"@popperjs/core": "^2.11.2",
"apexcharts-clevision": "3.28.5",
"babel-eslint": "^10.1.0",
"clsx": "^1.1.1",
"mdi-material-ui": "^7.1.0",
"next": "12.0.4",
"nprogress": "^0.2.0",
"react": "17.0.2",
"react-apexcharts": "^1.3.9",
"react-datepicker": "^4.5.0",
"react-dom": "17.0.2",
"react-perfect-scrollbar": "^1.5.8",
"react-popper": "^2.2.5"
},
"devDependencies": {
"eslint": "^7.32.0",
"eslint-config-next": "12.0.4",
"eslint-config-prettier": "^8.3.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-import-resolver-typescript": "^2.5.0",
"eslint-plugin-import": "^2.25.4",
"next-transpile-modules": "^9.0.0",
"prettier": "2.5.1"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
public/images/avatars/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/images/avatars/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
public/images/avatars/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
public/images/avatars/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
public/images/avatars/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
public/images/avatars/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
public/images/avatars/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
public/images/avatars/8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
public/images/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
public/images/logos/aws.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 934 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
public/images/pages/401.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

BIN
public/images/pages/404.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

BIN
public/images/pages/500.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

4
public/vercel.svg Normal file
View File

@ -0,0 +1,4 @@
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,51 @@
// ** MUI Imports
import Box from '@mui/material/Box'
import Card from '@mui/material/Card'
import Avatar from '@mui/material/Avatar'
import IconButton from '@mui/material/IconButton'
import Typography from '@mui/material/Typography'
import CardContent from '@mui/material/CardContent'
// ** Icons Imports
import DotsVertical from 'mdi-material-ui/DotsVertical'
const CardStatsVertical = props => {
// ** Props
const { title, subtitle, color, icon, stats, trend, trendNumber } = props
return (
<Card>
<CardContent>
<Box sx={{ display: 'flex', marginBottom: 5.5, alignItems: 'flex-start', justifyContent: 'space-between' }}>
<Avatar sx={{ boxShadow: 3, marginRight: 4, color: 'common.white', backgroundColor: `${color}.main` }}>
{icon}
</Avatar>
<IconButton size='small' aria-label='settings' className='card-more-options' sx={{ color: 'text.secondary' }}>
<DotsVertical />
</IconButton>
</Box>
<Typography sx={{ fontWeight: 600, fontSize: '0.875rem' }}>{title}</Typography>
<Box sx={{ marginTop: 1.5, display: 'flex', flexWrap: 'wrap', marginBottom: 1.5, alignItems: 'flex-start' }}>
<Typography variant='h6' sx={{ mr: 2 }}>
{stats}
</Typography>
<Typography
component='sup'
variant='caption'
sx={{ color: trend === 'positive' ? 'success.main' : 'error.main' }}
>
{trendNumber}
</Typography>
</Box>
<Typography variant='caption'>{subtitle}</Typography>
</CardContent>
</Card>
)
}
export default CardStatsVertical
CardStatsVertical.defaultProps = {
color: 'primary',
trend: 'positive'
}

View File

@ -0,0 +1,7 @@
// ** Next Import
import dynamic from 'next/dynamic'
// ! To avoid 'Window is not defined' error
const ReactApexcharts = dynamic(() => import('react-apexcharts'), { ssr: false })
export default ReactApexcharts

View File

@ -0,0 +1,39 @@
// ** MUI Imports
import Zoom from '@mui/material/Zoom'
import { styled } from '@mui/material/styles'
import useScrollTrigger from '@mui/material/useScrollTrigger'
const ScrollToTopStyled = styled('div')(({ theme }) => ({
zIndex: 11,
position: 'fixed',
right: theme.spacing(6),
bottom: theme.spacing(10)
}))
const ScrollToTop = props => {
// ** Props
const { children, className } = props
// ** init trigger
const trigger = useScrollTrigger({
threshold: 400,
disableHysteresis: true
})
const handleClick = () => {
const anchor = document.querySelector('body')
if (anchor) {
anchor.scrollIntoView({ behavior: 'smooth' })
}
}
return (
<Zoom in={trigger}>
<ScrollToTopStyled className={className} onClick={handleClick} role='presentation'>
{children}
</ScrollToTopStyled>
</Zoom>
)
}
export default ScrollToTop

View File

@ -0,0 +1,30 @@
// ** React Imports
import { createContext, useState } from 'react'
// ** ThemeConfig Import
import themeConfig from 'src/configs/themeConfig'
const initialSettings = {
themeColor: 'primary',
mode: themeConfig.mode,
contentWidth: themeConfig.contentWidth
}
// ** Create Context
export const SettingsContext = createContext({
saveSettings: () => null,
settings: initialSettings
})
export const SettingsProvider = ({ children }) => {
// ** State
const [settings, setSettings] = useState({ ...initialSettings })
const saveSettings = updatedSettings => {
setSettings(updatedSettings)
}
return <SettingsContext.Provider value={{ settings, saveSettings }}>{children}</SettingsContext.Provider>
}
export const SettingsConsumer = SettingsContext.Consumer

View File

@ -0,0 +1,4 @@
import { useContext } from 'react'
import { SettingsContext } from 'src/@core/context/settingsContext'
export const useSettings = () => useContext(SettingsContext)

View File

@ -0,0 +1,37 @@
// ** MUI Imports
import { styled } from '@mui/material/styles'
import Box from '@mui/material/Box'
// Styled component for Blank Layout component
const BlankLayoutWrapper = styled(Box)(({ theme }) => ({
height: '100vh',
// For V1 Blank layout pages
'& .content-center': {
display: 'flex',
minHeight: '100vh',
alignItems: 'center',
justifyContent: 'center',
padding: theme.spacing(5)
},
// For V2 Blank layout pages
'& .content-right': {
display: 'flex',
minHeight: '100vh',
overflowX: 'hidden',
position: 'relative'
}
}))
const BlankLayout = ({ children }) => {
return (
<BlankLayoutWrapper className='layout-wrapper'>
<Box className='app-content' sx={{ minHeight: '100vh', overflowX: 'hidden', position: 'relative' }}>
{children}
</Box>
</BlankLayoutWrapper>
)
}
export default BlankLayout

View File

@ -0,0 +1,109 @@
// ** React Imports
import { useState } from 'react'
// ** MUI Imports
import Fab from '@mui/material/Fab'
import { styled } from '@mui/material/styles'
import Box from '@mui/material/Box'
// ** Icons Imports
import ArrowUp from 'mdi-material-ui/ArrowUp'
// ** Theme Config Import
import themeConfig from 'src/configs/themeConfig'
// ** Components
import AppBar from './components/vertical/appBar'
import Navigation from './components/vertical/navigation'
import Footer from './components/shared-components/footer'
import ScrollToTop from 'src/@core/components/scroll-to-top'
// ** Styled Component
import DatePickerWrapper from 'src/@core/styles/libs/react-datepicker'
const VerticalLayoutWrapper = styled('div')({
height: '100%',
display: 'flex'
})
const MainContentWrapper = styled(Box)({
flexGrow: 1,
minWidth: 0,
display: 'flex',
minHeight: '100vh',
flexDirection: 'column'
})
const ContentWrapper = styled('main')(({ theme }) => ({
flexGrow: 1,
width: '100%',
padding: theme.spacing(6),
transition: 'padding .25s ease-in-out',
[theme.breakpoints.down('sm')]: {
paddingLeft: theme.spacing(4),
paddingRight: theme.spacing(4)
}
}))
const VerticalLayout = props => {
// ** Props
const { settings, children, scrollToTop } = props
// ** Vars
const { contentWidth } = settings
const navWidth = themeConfig.navigationSize
// ** States
const [navVisible, setNavVisible] = useState(false)
// ** Toggle Functions
const toggleNavVisibility = () => setNavVisible(!navVisible)
return (
<>
<VerticalLayoutWrapper className='layout-wrapper'>
<Navigation
navWidth={navWidth}
navVisible={navVisible}
setNavVisible={setNavVisible}
toggleNavVisibility={toggleNavVisibility}
{...props}
/>
<MainContentWrapper className='layout-content-wrapper'>
<AppBar toggleNavVisibility={toggleNavVisibility} {...props} />
<ContentWrapper
className='layout-page-content'
sx={{
...(contentWidth === 'boxed' && {
mx: 'auto',
'@media (min-width:1440px)': { maxWidth: 1440 },
'@media (min-width:1200px)': { maxWidth: '100%' }
})
}}
>
{children}
</ContentWrapper>
<Footer {...props} />
<DatePickerWrapper sx={{ zIndex: 11 }}>
<Box id='react-datepicker-portal'></Box>
</DatePickerWrapper>
</MainContentWrapper>
</VerticalLayoutWrapper>
{scrollToTop ? (
scrollToTop(props)
) : (
<ScrollToTop className='mui-fixed'>
<Fab color='primary' size='small' aria-label='scroll back to top'>
<ArrowUp />
</Fab>
</ScrollToTop>
)}
</>
)
}
export default VerticalLayout

View File

@ -0,0 +1,30 @@
import IconButton from '@mui/material/IconButton'
// ** Icons Imports
import WeatherNight from 'mdi-material-ui/WeatherNight'
import WeatherSunny from 'mdi-material-ui/WeatherSunny'
const ModeToggler = props => {
// ** Props
const { settings, saveSettings } = props
const handleModeChange = mode => {
saveSettings({ ...settings, mode })
}
const handleModeToggle = () => {
if (settings.mode === 'light') {
handleModeChange('dark')
} else {
handleModeChange('light')
}
}
return (
<IconButton color='inherit' aria-haspopup='true' onClick={handleModeToggle}>
{settings.mode === 'dark' ? <WeatherSunny /> : <WeatherNight />}
</IconButton>
)
}
export default ModeToggler

View File

@ -0,0 +1,217 @@
// ** React Imports
import { useState, Fragment } from 'react'
// ** MUI Imports
import Box from '@mui/material/Box'
import Chip from '@mui/material/Chip'
import Button from '@mui/material/Button'
import IconButton from '@mui/material/IconButton'
import { styled } from '@mui/material/styles'
import useMediaQuery from '@mui/material/useMediaQuery'
import MuiMenu from '@mui/material/Menu'
import MuiAvatar from '@mui/material/Avatar'
import MuiMenuItem from '@mui/material/MenuItem'
import Typography from '@mui/material/Typography'
// ** Icons Imports
import BellOutline from 'mdi-material-ui/BellOutline'
// ** Third Party Components
import PerfectScrollbarComponent from 'react-perfect-scrollbar'
// ** Styled Menu component
const Menu = styled(MuiMenu)(({ theme }) => ({
'& .MuiMenu-paper': {
width: 380,
overflow: 'hidden',
marginTop: theme.spacing(4),
[theme.breakpoints.down('sm')]: {
width: '100%'
}
},
'& .MuiMenu-list': {
padding: 0
}
}))
// ** Styled MenuItem component
const MenuItem = styled(MuiMenuItem)(({ theme }) => ({
paddingTop: theme.spacing(3),
paddingBottom: theme.spacing(3),
borderBottom: `1px solid ${theme.palette.divider}`
}))
const styles = {
maxHeight: 349,
'& .MuiMenuItem-root:last-of-type': {
border: 0
}
}
// ** Styled PerfectScrollbar component
const PerfectScrollbar = styled(PerfectScrollbarComponent)({
...styles
})
// ** Styled Avatar component
const Avatar = styled(MuiAvatar)({
width: '2.375rem',
height: '2.375rem',
fontSize: '1.125rem'
})
// ** Styled component for the title in MenuItems
const MenuItemTitle = styled(Typography)(({ theme }) => ({
fontWeight: 600,
flex: '1 1 100%',
overflow: 'hidden',
fontSize: '0.875rem',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
marginBottom: theme.spacing(0.75)
}))
// ** Styled component for the subtitle in MenuItems
const MenuItemSubtitle = styled(Typography)({
flex: '1 1 100%',
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis'
})
const NotificationDropdown = () => {
// ** States
const [anchorEl, setAnchorEl] = useState(null)
// ** Hook
const hidden = useMediaQuery(theme => theme.breakpoints.down('lg'))
const handleDropdownOpen = event => {
setAnchorEl(event.currentTarget)
}
const handleDropdownClose = () => {
setAnchorEl(null)
}
const ScrollWrapper = ({ children }) => {
if (hidden) {
return <Box sx={{ ...styles, overflowY: 'auto', overflowX: 'hidden' }}>{children}</Box>
} else {
return (
<PerfectScrollbar options={{ wheelPropagation: false, suppressScrollX: true }}>{children}</PerfectScrollbar>
)
}
}
return (
<Fragment>
<IconButton color='inherit' aria-haspopup='true' onClick={handleDropdownOpen} aria-controls='customized-menu'>
<BellOutline />
</IconButton>
<Menu
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleDropdownClose}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
>
<MenuItem disableRipple>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' }}>
<Typography sx={{ fontWeight: 600 }}>Notifications</Typography>
<Chip
size='small'
label='8 New'
color='primary'
sx={{ height: 20, fontSize: '0.75rem', fontWeight: 500, borderRadius: '10px' }}
/>
</Box>
</MenuItem>
<ScrollWrapper>
<MenuItem onClick={handleDropdownClose}>
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
<Avatar alt='Flora' src='/images/avatars/4.png' />
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
<MenuItemTitle>Congratulation Flora! 🎉</MenuItemTitle>
<MenuItemSubtitle variant='body2'>Won the monthly best seller badge</MenuItemSubtitle>
</Box>
<Typography variant='caption' sx={{ color: 'text.disabled' }}>
Today
</Typography>
</Box>
</MenuItem>
<MenuItem onClick={handleDropdownClose}>
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
<Avatar sx={{ color: 'common.white', backgroundColor: 'primary.main' }}>VU</Avatar>
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
<MenuItemTitle>New user registered.</MenuItemTitle>
<MenuItemSubtitle variant='body2'>5 hours ago</MenuItemSubtitle>
</Box>
<Typography variant='caption' sx={{ color: 'text.disabled' }}>
Yesterday
</Typography>
</Box>
</MenuItem>
<MenuItem onClick={handleDropdownClose}>
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
<Avatar alt='message' src='/images/avatars/5.png' />
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
<MenuItemTitle>New message received 👋🏻</MenuItemTitle>
<MenuItemSubtitle variant='body2'>You have 10 unread messages</MenuItemSubtitle>
</Box>
<Typography variant='caption' sx={{ color: 'text.disabled' }}>
11 Aug
</Typography>
</Box>
</MenuItem>
<MenuItem onClick={handleDropdownClose}>
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
<img width={38} height={38} alt='paypal' src='/images/misc/paypal.png' />
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
<MenuItemTitle>Paypal</MenuItemTitle>
<MenuItemSubtitle variant='body2'>Received Payment</MenuItemSubtitle>
</Box>
<Typography variant='caption' sx={{ color: 'text.disabled' }}>
25 May
</Typography>
</Box>
</MenuItem>
<MenuItem onClick={handleDropdownClose}>
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
<Avatar alt='order' src='/images/avatars/3.png' />
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
<MenuItemTitle>Revised Order 📦</MenuItemTitle>
<MenuItemSubtitle variant='body2'>New order revised from john</MenuItemSubtitle>
</Box>
<Typography variant='caption' sx={{ color: 'text.disabled' }}>
19 Mar
</Typography>
</Box>
</MenuItem>
<MenuItem onClick={handleDropdownClose}>
<Box sx={{ width: '100%', display: 'flex', alignItems: 'center' }}>
<img width={38} height={38} alt='chart' src='/images/misc/chart.png' />
<Box sx={{ mx: 4, flex: '1 1', display: 'flex', overflow: 'hidden', flexDirection: 'column' }}>
<MenuItemTitle>Finance report has been generated</MenuItemTitle>
<MenuItemSubtitle variant='body2'>25 hrs ago</MenuItemSubtitle>
</Box>
<Typography variant='caption' sx={{ color: 'text.disabled' }}>
27 Dec
</Typography>
</Box>
</MenuItem>
</ScrollWrapper>
<MenuItem
disableRipple
sx={{ py: 3.5, borderBottom: 0, borderTop: theme => `1px solid ${theme.palette.divider}` }}
>
<Button fullWidth variant='contained' onClick={handleDropdownClose}>
Read All Notifications
</Button>
</MenuItem>
</Menu>
</Fragment>
)
}
export default NotificationDropdown

View File

@ -0,0 +1,156 @@
// ** React Imports
import { useState, Fragment } from 'react'
// ** Next Import
import { useRouter } from 'next/router'
// ** MUI Imports
import Box from '@mui/material/Box'
import Menu from '@mui/material/Menu'
import Badge from '@mui/material/Badge'
import Avatar from '@mui/material/Avatar'
import Divider from '@mui/material/Divider'
import MenuItem from '@mui/material/MenuItem'
import { styled } from '@mui/material/styles'
import Typography from '@mui/material/Typography'
// ** Icons Imports
import CogOutline from 'mdi-material-ui/CogOutline'
import CurrencyUsd from 'mdi-material-ui/CurrencyUsd'
import EmailOutline from 'mdi-material-ui/EmailOutline'
import LogoutVariant from 'mdi-material-ui/LogoutVariant'
import AccountOutline from 'mdi-material-ui/AccountOutline'
import MessageOutline from 'mdi-material-ui/MessageOutline'
import HelpCircleOutline from 'mdi-material-ui/HelpCircleOutline'
// ** Styled Components
const BadgeContentSpan = styled('span')(({ theme }) => ({
width: 8,
height: 8,
borderRadius: '50%',
backgroundColor: theme.palette.success.main,
boxShadow: `0 0 0 2px ${theme.palette.background.paper}`
}))
const UserDropdown = () => {
// ** States
const [anchorEl, setAnchorEl] = useState(null)
// ** Hooks
const router = useRouter()
const handleDropdownOpen = event => {
setAnchorEl(event.currentTarget)
}
const handleDropdownClose = url => {
if (url) {
router.push(url)
}
setAnchorEl(null)
}
const styles = {
py: 2,
px: 4,
width: '100%',
display: 'flex',
alignItems: 'center',
color: 'text.primary',
textDecoration: 'none',
'& svg': {
fontSize: '1.375rem',
color: 'text.secondary'
}
}
return (
<Fragment>
<Badge
overlap='circular'
onClick={handleDropdownOpen}
sx={{ ml: 2, cursor: 'pointer' }}
badgeContent={<BadgeContentSpan />}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
>
<Avatar
alt='John Doe'
onClick={handleDropdownOpen}
sx={{ width: 40, height: 40 }}
src='/images/avatars/1.png'
/>
</Badge>
<Menu
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={() => handleDropdownClose()}
sx={{ '& .MuiMenu-paper': { width: 230, marginTop: 4 } }}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
>
<Box sx={{ pt: 2, pb: 3, px: 4 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Badge
overlap='circular'
badgeContent={<BadgeContentSpan />}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
>
<Avatar alt='John Doe' src='/images/avatars/1.png' sx={{ width: '2.5rem', height: '2.5rem' }} />
</Badge>
<Box sx={{ display: 'flex', marginLeft: 3, alignItems: 'flex-start', flexDirection: 'column' }}>
<Typography sx={{ fontWeight: 600 }}>John Doe</Typography>
<Typography variant='body2' sx={{ fontSize: '0.8rem', color: 'text.disabled' }}>
Admin
</Typography>
</Box>
</Box>
</Box>
<Divider sx={{ mt: 0, mb: 1 }} />
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
<Box sx={styles}>
<AccountOutline sx={{ marginRight: 2 }} />
Profile
</Box>
</MenuItem>
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
<Box sx={styles}>
<EmailOutline sx={{ marginRight: 2 }} />
Inbox
</Box>
</MenuItem>
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
<Box sx={styles}>
<MessageOutline sx={{ marginRight: 2 }} />
Chat
</Box>
</MenuItem>
<Divider />
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
<Box sx={styles}>
<CogOutline sx={{ marginRight: 2 }} />
Settings
</Box>
</MenuItem>
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
<Box sx={styles}>
<CurrencyUsd sx={{ marginRight: 2 }} />
Pricing
</Box>
</MenuItem>
<MenuItem sx={{ p: 0 }} onClick={() => handleDropdownClose()}>
<Box sx={styles}>
<HelpCircleOutline sx={{ marginRight: 2 }} />
FAQ
</Box>
</MenuItem>
<Divider />
<MenuItem sx={{ py: 2 }} onClick={() => handleDropdownClose('/pages/login')}>
<LogoutVariant sx={{ marginRight: 2, fontSize: '1.375rem', color: 'text.secondary' }} />
Logout
</MenuItem>
</Menu>
</Fragment>
)
}
export default UserDropdown

View File

@ -0,0 +1,52 @@
// ** MUI Imports
import Box from '@mui/material/Box'
import Link from '@mui/material/Link'
import Typography from '@mui/material/Typography'
import useMediaQuery from '@mui/material/useMediaQuery'
const FooterContent = () => {
// ** Var
const hidden = useMediaQuery(theme => theme.breakpoints.down('md'))
return (
<Box sx={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'space-between' }}>
<Typography sx={{ mr: 2 }}>
{`© ${new Date().getFullYear()}, Made with `}
<Box component='span' sx={{ color: 'error.main' }}>
</Box>
{` by `}
<Link target='_blank' href='https://themeselection.com/'>
ThemeSelection
</Link>
</Typography>
{hidden ? null : (
<Box sx={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', '& :not(:last-child)': { mr: 4 } }}>
<Link
target='_blank'
href='https://github.com/themeselection/materio-mui-react-nextjs-admin-template-free/blob/main/LICENSE'
>
MIT License
</Link>
<Link target='_blank' href='https://themeselection.com/'>
More Themes
</Link>
<Link
target='_blank'
href='https://github.com/themeselection/materio-mui-react-nextjs-admin-template-free/blob/main/README.md'
>
Documentation
</Link>
<Link
target='_blank'
href='https://github.com/themeselection/materio-mui-react-nextjs-admin-template-free/issues'
>
Support
</Link>
</Box>
)}
</Box>
)
}
export default FooterContent

View File

@ -0,0 +1,45 @@
// ** MUI Imports
import Box from '@mui/material/Box'
import { useTheme } from '@mui/material/styles'
// ** Footer Content Component
import FooterContent from './FooterContent'
const Footer = props => {
// ** Props
const { settings, footerContent: userFooterContent } = props
// ** Hook
const theme = useTheme()
// ** Vars
const { contentWidth } = settings
return (
<Box
component='footer'
className='layout-footer'
sx={{
zIndex: 10,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
>
<Box
className='footer-content-container'
sx={{
width: '100%',
borderTopLeftRadius: 14,
borderTopRightRadius: 14,
padding: theme.spacing(4, 6),
...(contentWidth === 'boxed' && { '@media (min-width:1440px)': { maxWidth: 1440 } })
}}
>
{userFooterContent ? userFooterContent(props) : <FooterContent />}
</Box>
</Box>
)
}
export default Footer

View File

@ -0,0 +1,56 @@
// ** MUI Imports
import { styled, useTheme } from '@mui/material/styles'
import MuiAppBar from '@mui/material/AppBar'
import MuiToolbar from '@mui/material/Toolbar'
const AppBar = styled(MuiAppBar)(({ theme }) => ({
transition: 'none',
alignItems: 'center',
justifyContent: 'center',
padding: theme.spacing(0, 6),
backgroundColor: 'transparent',
color: theme.palette.text.primary,
minHeight: theme.mixins.toolbar.minHeight,
[theme.breakpoints.down('sm')]: {
paddingLeft: theme.spacing(4),
paddingRight: theme.spacing(4)
}
}))
const Toolbar = styled(MuiToolbar)(({ theme }) => ({
width: '100%',
borderBottomLeftRadius: 10,
borderBottomRightRadius: 10,
padding: `${theme.spacing(0)} !important`,
minHeight: `${theme.mixins.toolbar.minHeight}px !important`,
transition:
'padding .25s ease-in-out, box-shadow .25s ease-in-out, backdrop-filter .25s ease-in-out, background-color .25s ease-in-out'
}))
const LayoutAppBar = props => {
// ** Props
const { settings, verticalAppBarContent: userVerticalAppBarContent } = props
// ** Hooks
const theme = useTheme()
// ** Vars
const { contentWidth } = settings
return (
<AppBar elevation={0} color='default' className='layout-navbar' position='static'>
<Toolbar
className='navbar-content-container'
sx={{
...(contentWidth === 'boxed' && {
'@media (min-width:1440px)': { maxWidth: `calc(1440px - ${theme.spacing(6)} * 2)` }
})
}}
>
{(userVerticalAppBarContent && userVerticalAppBarContent(props)) || null}
</Toolbar>
</AppBar>
)
}
export default LayoutAppBar

View File

@ -0,0 +1,66 @@
// ** MUI Imports
import { styled, useTheme } from '@mui/material/styles'
import MuiSwipeableDrawer from '@mui/material/SwipeableDrawer'
const SwipeableDrawer = styled(MuiSwipeableDrawer)({
overflowX: 'hidden',
transition: 'width .25s ease-in-out',
'& ul': {
listStyle: 'none'
},
'& .MuiListItem-gutters': {
paddingLeft: 4,
paddingRight: 4
},
'& .MuiDrawer-paper': {
left: 'unset',
right: 'unset',
overflowX: 'hidden',
transition: 'width .25s ease-in-out, box-shadow .25s ease-in-out'
}
})
const Drawer = props => {
// ** Props
const { hidden, children, navWidth, navVisible, setNavVisible } = props
// ** Hook
const theme = useTheme()
// Drawer Props for Mobile & Tablet screens
const MobileDrawerProps = {
open: navVisible,
onOpen: () => setNavVisible(true),
onClose: () => setNavVisible(false),
ModalProps: {
keepMounted: true // Better open performance on mobile.
}
}
// Drawer Props for Desktop screens
const DesktopDrawerProps = {
open: true,
onOpen: () => null,
onClose: () => null
}
return (
<SwipeableDrawer
className='layout-vertical-nav'
variant={hidden ? 'temporary' : 'permanent'}
{...(hidden ? { ...MobileDrawerProps } : { ...DesktopDrawerProps })}
PaperProps={{ sx: { width: navWidth } }}
sx={{
width: navWidth,
'& .MuiDrawer-paper': {
borderRight: 0,
backgroundColor: theme.palette.background.default
}
}}
>
{children}
</SwipeableDrawer>
)
}
export default Drawer

View File

@ -0,0 +1,119 @@
// ** Next Import
import Link from 'next/link'
// ** MUI Imports
import Box from '@mui/material/Box'
import { styled, useTheme } from '@mui/material/styles'
import Typography from '@mui/material/Typography'
// ** Configs
import themeConfig from 'src/configs/themeConfig'
// ** Styled Components
const MenuHeaderWrapper = styled(Box)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
paddingRight: theme.spacing(4.5),
transition: 'padding .25s ease-in-out',
minHeight: theme.mixins.toolbar.minHeight
}))
const HeaderTitle = styled(Typography)(({ theme }) => ({
fontWeight: 600,
lineHeight: 'normal',
textTransform: 'uppercase',
color: theme.palette.text.primary,
transition: 'opacity .25s ease-in-out, margin .25s ease-in-out'
}))
const StyledLink = styled('a')({
display: 'flex',
alignItems: 'center',
textDecoration: 'none'
})
const VerticalNavHeader = props => {
// ** Props
const { verticalNavMenuBranding: userVerticalNavMenuBranding } = props
// ** Hooks
const theme = useTheme()
return (
<MenuHeaderWrapper className='nav-header' sx={{ pl: 6 }}>
{userVerticalNavMenuBranding ? (
userVerticalNavMenuBranding(props)
) : (
<Link href='/' passHref>
<StyledLink>
<svg
width={30}
height={25}
version='1.1'
viewBox='0 0 30 23'
xmlns='http://www.w3.org/2000/svg'
xmlnsXlink='http://www.w3.org/1999/xlink'
>
<g stroke='none' strokeWidth='1' fill='none' fillRule='evenodd'>
<g id='Artboard' transform='translate(-95.000000, -51.000000)'>
<g id='logo' transform='translate(95.000000, 50.000000)'>
<path
id='Combined-Shape'
fill={theme.palette.primary.main}
d='M30,21.3918362 C30,21.7535219 29.9019196,22.1084381 29.7162004,22.4188007 C29.1490236,23.366632 27.9208668,23.6752135 26.9730355,23.1080366 L26.9730355,23.1080366 L23.714971,21.1584295 C23.1114106,20.7972624 22.7419355,20.1455972 22.7419355,19.4422291 L22.7419355,19.4422291 L22.741,12.7425689 L15,17.1774194 L7.258,12.7425689 L7.25806452,19.4422291 C7.25806452,20.1455972 6.88858935,20.7972624 6.28502902,21.1584295 L3.0269645,23.1080366 C2.07913318,23.6752135 0.850976404,23.366632 0.283799571,22.4188007 C0.0980803893,22.1084381 2.0190442e-15,21.7535219 0,21.3918362 L0,3.58469444 L0.00548573643,3.43543209 L0.00548573643,3.43543209 L0,3.5715689 C3.0881846e-16,2.4669994 0.8954305,1.5715689 2,1.5715689 C2.36889529,1.5715689 2.73060353,1.67359571 3.04512412,1.86636639 L15,9.19354839 L26.9548759,1.86636639 C27.2693965,1.67359571 27.6311047,1.5715689 28,1.5715689 C29.1045695,1.5715689 30,2.4669994 30,3.5715689 L30,3.5715689 Z'
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='0 8.58870968 7.25806452 12.7505183 7.25806452 16.8305646'
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='0 8.58870968 7.25806452 12.6445567 7.25806452 15.1370162'
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='22.7419355 8.58870968 30 12.7417372 30 16.9537453'
transform='translate(26.370968, 12.771227) scale(-1, 1) translate(-26.370968, -12.771227) '
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='22.7419355 8.58870968 30 12.6409734 30 15.2601969'
transform='translate(26.370968, 11.924453) scale(-1, 1) translate(-26.370968, -11.924453) '
/>
<path
id='Rectangle'
fillOpacity='0.15'
fill={theme.palette.common.white}
d='M3.04512412,1.86636639 L15,9.19354839 L15,9.19354839 L15,17.1774194 L0,8.58649679 L0,3.5715689 C3.0881846e-16,2.4669994 0.8954305,1.5715689 2,1.5715689 C2.36889529,1.5715689 2.73060353,1.67359571 3.04512412,1.86636639 Z'
/>
<path
id='Rectangle'
fillOpacity='0.35'
fill={theme.palette.common.white}
transform='translate(22.500000, 8.588710) scale(-1, 1) translate(-22.500000, -8.588710) '
d='M18.0451241,1.86636639 L30,9.19354839 L30,9.19354839 L30,17.1774194 L15,8.58649679 L15,3.5715689 C15,2.4669994 15.8954305,1.5715689 17,1.5715689 C17.3688953,1.5715689 17.7306035,1.67359571 18.0451241,1.86636639 Z'
/>
</g>
</g>
</g>
</svg>
<HeaderTitle variant='h6' sx={{ ml: 3 }}>
{themeConfig.templateName}
</HeaderTitle>
</StyledLink>
</Link>
)}
</MenuHeaderWrapper>
)
}
export default VerticalNavHeader

View File

@ -0,0 +1,24 @@
// ** Custom Menu Components
import VerticalNavLink from './VerticalNavLink'
import VerticalNavSectionTitle from './VerticalNavSectionTitle'
const resolveNavItemComponent = item => {
if (item.sectionTitle) return VerticalNavSectionTitle
return VerticalNavLink
}
const VerticalNavItems = props => {
// ** Props
const { verticalNavItems } = props
const RenderMenuItems = verticalNavItems?.map((item, index) => {
const TagName = resolveNavItemComponent(item)
return <TagName {...props} key={index} item={item} />
})
return <>{RenderMenuItems}</>
}
export default VerticalNavItems

View File

@ -0,0 +1,119 @@
// ** Next Imports
import Link from 'next/link'
import { useRouter } from 'next/router'
// ** MUI Imports
import Chip from '@mui/material/Chip'
import ListItem from '@mui/material/ListItem'
import { styled } from '@mui/material/styles'
import Typography from '@mui/material/Typography'
import Box from '@mui/material/Box'
import ListItemIcon from '@mui/material/ListItemIcon'
import ListItemButton from '@mui/material/ListItemButton'
// ** Configs Import
import themeConfig from 'src/configs/themeConfig'
// ** Custom Components Imports
import UserIcon from 'src/layouts/components/UserIcon'
// ** Utils
import { handleURLQueries } from 'src/@core/layouts/utils'
// ** Styled Components
const MenuNavLink = styled(ListItemButton)(({ theme }) => ({
width: '100%',
borderTopRightRadius: 100,
borderBottomRightRadius: 100,
color: theme.palette.text.primary,
padding: theme.spacing(2.25, 3.5),
transition: 'opacity .25s ease-in-out',
'&.active, &.active:hover': {
boxShadow: theme.shadows[3],
backgroundImage: `linear-gradient(98deg, ${theme.palette.customColors.primaryGradient}, ${theme.palette.primary.main} 94%)`
},
'&.active .MuiTypography-root, &.active .MuiSvgIcon-root': {
color: `${theme.palette.common.white} !important`
}
}))
const MenuItemTextMetaWrapper = styled(Box)({
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
transition: 'opacity .25s ease-in-out',
...(themeConfig.menuTextTruncate && { overflow: 'hidden' })
})
const VerticalNavLink = ({ item, navVisible, toggleNavVisibility }) => {
// ** Hooks
const router = useRouter()
const IconTag = item.icon
const isNavLinkActive = () => {
if (router.pathname === item.path || handleURLQueries(router, item.path)) {
return true
} else {
return false
}
}
return (
<ListItem
disablePadding
className='nav-link'
disabled={item.disabled || false}
sx={{ mt: 1.5, px: '0 !important' }}
>
<Link passHref href={item.path === undefined ? '/' : `${item.path}`}>
<MenuNavLink
component={'a'}
className={isNavLinkActive() ? 'active' : ''}
{...(item.openInNewTab ? { target: '_blank' } : null)}
onClick={e => {
if (item.path === undefined) {
e.preventDefault()
e.stopPropagation()
}
if (navVisible) {
toggleNavVisibility()
}
}}
sx={{
pl: 5.5,
...(item.disabled ? { pointerEvents: 'none' } : { cursor: 'pointer' })
}}
>
<ListItemIcon
sx={{
mr: 2.5,
color: 'text.primary',
transition: 'margin .25s ease-in-out'
}}
>
<UserIcon icon={IconTag} />
</ListItemIcon>
<MenuItemTextMetaWrapper>
<Typography {...(themeConfig.menuTextTruncate && { noWrap: true })}>{item.title}</Typography>
{item.badgeContent ? (
<Chip
label={item.badgeContent}
color={item.badgeColor || 'primary'}
sx={{
height: 20,
fontWeight: 500,
marginLeft: 1.25,
'& .MuiChip-label': { px: 1.5, textTransform: 'capitalize' }
}}
/>
) : null}
</MenuItemTextMetaWrapper>
</MenuNavLink>
</Link>
</ListItem>
)
}
export default VerticalNavLink

View File

@ -0,0 +1,63 @@
// ** MUI Imports
import Divider from '@mui/material/Divider'
import { styled, useTheme } from '@mui/material/styles'
import Typography from '@mui/material/Typography'
import MuiListSubheader from '@mui/material/ListSubheader'
// ** Styled Components
const ListSubheader = styled(props => <MuiListSubheader component='li' {...props} />)(({ theme }) => ({
lineHeight: 1,
display: 'flex',
position: 'relative',
marginTop: theme.spacing(7),
marginBottom: theme.spacing(2),
backgroundColor: 'transparent',
transition: 'padding-left .25s ease-in-out'
}))
const TypographyHeaderText = styled(Typography)(({ theme }) => ({
fontSize: '0.75rem',
lineHeight: 'normal',
letterSpacing: '0.21px',
textTransform: 'uppercase',
color: theme.palette.text.disabled,
fontWeight: theme.typography.fontWeightMedium
}))
const VerticalNavSectionTitle = props => {
// ** Props
const { item } = props
// ** Hook
const theme = useTheme()
return (
<ListSubheader
className='nav-section-title'
sx={{
px: 0,
py: 1.75,
color: theme.palette.text.disabled,
'& .MuiDivider-root:before, & .MuiDivider-root:after, & hr': {
borderColor: `rgba(${theme.palette.customColors.main}, 0.12)`
}
}}
>
<Divider
textAlign='left'
sx={{
m: 0,
width: '100%',
lineHeight: 'normal',
textTransform: 'uppercase',
'&:before, &:after': { top: 7, transform: 'none' },
'& .MuiDivider-wrapper': { px: 2.5, fontSize: '0.75rem', letterSpacing: '0.21px' }
}}
>
<TypographyHeaderText noWrap>{item.sectionTitle}</TypographyHeaderText>
</Divider>
</ListSubheader>
)
}
export default VerticalNavSectionTitle

View File

@ -0,0 +1,131 @@
// ** React Import
import { useRef, useState } from 'react'
// ** MUI Import
import List from '@mui/material/List'
import Box from '@mui/material/Box'
import { styled, useTheme } from '@mui/material/styles'
// ** Third Party Components
import PerfectScrollbar from 'react-perfect-scrollbar'
// ** Component Imports
import Drawer from './Drawer'
import VerticalNavItems from './VerticalNavItems'
import VerticalNavHeader from './VerticalNavHeader'
// ** Util Import
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba'
const StyledBoxForShadow = styled(Box)({
top: 50,
left: -8,
zIndex: 2,
height: 75,
display: 'none',
position: 'absolute',
pointerEvents: 'none',
width: 'calc(100% + 15px)',
'&.d-block': {
display: 'block'
}
})
const Navigation = props => {
// ** Props
const {
hidden,
afterVerticalNavMenuContent,
beforeVerticalNavMenuContent,
verticalNavMenuContent: userVerticalNavMenuContent
} = props
// ** States
const [groupActive, setGroupActive] = useState([])
const [currentActiveGroup, setCurrentActiveGroup] = useState([])
// ** Ref
const shadowRef = useRef(null)
// ** Hooks
const theme = useTheme()
// ** Fixes Navigation InfiniteScroll
const handleInfiniteScroll = ref => {
if (ref) {
// @ts-ignore
ref._getBoundingClientRect = ref.getBoundingClientRect
ref.getBoundingClientRect = () => {
// @ts-ignore
const original = ref._getBoundingClientRect()
return { ...original, height: Math.floor(original.height) }
}
}
}
// ** Scroll Menu
const scrollMenu = container => {
container = hidden ? container.target : container
if (shadowRef && container.scrollTop > 0) {
// @ts-ignore
if (!shadowRef.current.classList.contains('d-block')) {
// @ts-ignore
shadowRef.current.classList.add('d-block')
}
} else {
// @ts-ignore
shadowRef.current.classList.remove('d-block')
}
}
const ScrollWrapper = hidden ? Box : PerfectScrollbar
return (
<Drawer {...props}>
<VerticalNavHeader {...props} />
<StyledBoxForShadow
ref={shadowRef}
sx={{
background: `linear-gradient(${theme.palette.background.default} 40%,${hexToRGBA(
theme.palette.background.default,
0.1
)} 95%,${hexToRGBA(theme.palette.background.default, 0.05)})`
}}
/>
<Box sx={{ height: '100%', position: 'relative', overflow: 'hidden' }}>
<ScrollWrapper
{...(hidden
? {
onScroll: container => scrollMenu(container),
sx: { height: '100%', overflowY: 'auto', overflowX: 'hidden' }
}
: {
options: { wheelPropagation: false },
onScrollY: container => scrollMenu(container),
containerRef: ref => handleInfiniteScroll(ref)
})}
>
{beforeVerticalNavMenuContent ? beforeVerticalNavMenuContent(props) : null}
<Box sx={{ height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
{userVerticalNavMenuContent ? (
userVerticalNavMenuContent(props)
) : (
<List className='nav-items' sx={{ transition: 'padding .25s ease', pr: 4.5 }}>
<VerticalNavItems
groupActive={groupActive}
setGroupActive={setGroupActive}
currentActiveGroup={currentActiveGroup}
setCurrentActiveGroup={setCurrentActiveGroup}
{...props}
/>
</List>
)}
</Box>
</ScrollWrapper>
</Box>
{afterVerticalNavMenuContent ? afterVerticalNavMenuContent(props) : null}
</Drawer>
)
}
export default Navigation

View File

@ -0,0 +1,16 @@
/**
* Check for URL queries as well for matching
* Current URL & Item Path
*
* @param item
* @param activeItem
*/
export const handleURLQueries = (router, path) => {
if (Object.keys(router.query).length && path) {
const arr = Object.keys(router.query)
return router.asPath.includes(path) && router.asPath.includes(router.query[arr[0]]) && path !== '/'
}
return false
}

View File

@ -0,0 +1,103 @@
// ** MUI imports
import { styled } from '@mui/material/styles'
const ApexChartWrapper = styled('div')(({ theme }) => ({
'& .apexcharts-canvas': {
"& line[stroke='transparent']": {
display: 'none'
},
'& .apexcharts-xaxis > line, & .apexcharts-yaxis > line': {
stroke: theme.palette.divider
},
'& .apexcharts-xaxis-tick, & .apexcharts-yaxis-tick': {
stroke: theme.palette.divider
},
'& .apexcharts-tooltip': {
boxShadow: theme.shadows[3],
borderColor: theme.palette.divider,
background: theme.palette.background.paper,
'& .apexcharts-tooltip-title': {
fontWeight: 600,
borderColor: theme.palette.divider,
background: theme.palette.background.paper
},
'&.apexcharts-theme-dark': {
'& .apexcharts-tooltip-text-label, & .apexcharts-tooltip-text-value': {
color: theme.palette.common.white
}
},
'& .bar-chart': {
padding: theme.spacing(2, 2.5)
}
},
'& .apexcharts-xaxistooltip': {
borderColor: theme.palette.divider,
background: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default,
'& .apexcharts-xaxistooltip-text': {
color: theme.palette.text.primary
},
'&:after': {
borderBottomColor: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default
},
'&:before': {
borderBottomColor: theme.palette.divider
}
},
'& .apexcharts-yaxistooltip': {
borderColor: theme.palette.divider,
background: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default,
'& .apexcharts-yaxistooltip-text': {
color: theme.palette.text.primary
},
'&:after': {
borderLeftColor: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default
},
'&:before': {
borderLeftColor: theme.palette.divider
}
},
'& .apexcharts-text, & .apexcharts-tooltip-text, & .apexcharts-datalabel-label, & .apexcharts-datalabel': {
filter: 'none',
fontWeight: 400,
fill: theme.palette.text.primary,
fontFamily: `${theme.typography.fontFamily} !important`
},
'& .apexcharts-pie-label': {
filter: 'none',
fill: theme.palette.common.white
},
'& .apexcharts-pie': {
'& .apexcharts-datalabel-label, .apexcharts-datalabel-value': {
fontSize: '1.5rem'
}
},
'& .apexcharts-marker': {
boxShadow: 'none'
},
'& .apexcharts-legend-series': {
margin: `${theme.spacing(0.75, 2)} !important`,
'& .apexcharts-legend-text': {
marginLeft: theme.spacing(0.75),
color: `${theme.palette.text.primary} !important`
}
},
'& .apexcharts-xcrosshairs, & .apexcharts-ycrosshairs, & .apexcharts-gridline': {
stroke: theme.palette.divider
},
'& .apexcharts-heatmap-rect': {
stroke: theme.palette.mode === 'light' ? theme.palette.background.paper : theme.palette.background.default
},
'& .apexcharts-radialbar > g > g:first-of-type .apexcharts-radialbar-area': {
stroke: theme.palette.background.default
},
'& .apexcharts-radar-series polygon': {
stroke: theme.palette.divider,
fill: theme.palette.background.paper
},
'& .apexcharts-radar-series line': {
stroke: theme.palette.divider
}
}
}))
export default ApexChartWrapper

View File

@ -0,0 +1,358 @@
// ** MUI imports
import { styled } from '@mui/material/styles'
import Box from '@mui/material/Box'
// ** Util Import
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba'
const DatePickerWrapper = styled(Box)(({ theme }) => {
return {
'& .react-datepicker-popper': {
zIndex: 5
},
'& .react-datepicker-wrapper': {
width: '100%'
},
'& .react-datepicker': {
border: 'none',
boxShadow: theme.shadows[7],
padding: theme.spacing(2, 0),
color: theme.palette.text.primary,
borderRadius: theme.shape.borderRadius,
fontFamily: theme.typography.fontFamily,
backgroundColor: theme.palette.background.paper,
'& .react-datepicker__header': {
padding: 0,
border: 'none',
fontWeight: 'normal',
backgroundColor: theme.palette.background.paper,
'& .react-datepicker__day-name': {
margin: 0
}
},
'& .react-datepicker-year-header': {
lineHeight: 2.1,
marginBottom: '0.5rem',
color: theme.palette.text.primary
},
'& .react-datepicker__triangle': {
display: 'none'
},
'& > .react-datepicker__navigation': {
top: theme.spacing(3),
'&.react-datepicker__navigation--previous': {
border: 'none',
backgroundImage: `${"url('data:image/svg+xml,%3Csvg xmlns=\\'http://www.w3.org/2000/svg\\' style=\\'width:24px;height:24px\\' viewBox=\\'0 0 24 24\\'%3E%3Cpath fill=\\'currentColor\\' d=\\'M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z\\' /%3E%3C/svg%3E')"
.replace('currentColor', theme.palette.text.secondary)
.replace('#', '%23')}`,
height: '24px',
width: '24px',
'& .react-datepicker__navigation-icon': {
display: 'none'
}
},
'&.react-datepicker__navigation--next': {
border: 'none',
backgroundImage: `${"url('data:image/svg+xml,%3Csvg xmlns=\\'http://www.w3.org/2000/svg\\' style=\\'width:24px;height:24px\\' viewBox=\\'0 0 24 24\\'%3E%3Cpath fill=\\'currentColor\\' d=\\'M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z\\' /%3E%3C/svg%3E')"
.replace('currentColor', theme.palette.text.secondary)
.replace('#', '%23')}`,
height: '24px',
width: '24px',
'& .react-datepicker__navigation-icon': {
display: 'none'
}
},
'&.react-datepicker__navigation--next--with-time': {
right: '122px'
},
'&:focus, &:active': {
outline: 0
}
},
'& .react-datepicker__current-month': {
lineHeight: 2.1,
fontSize: '1rem',
fontWeight: 'normal',
letterSpacing: '0.15px',
marginBottom: theme.spacing(2),
color: theme.palette.text.primary
},
'& .react-datepicker__day-name': {
lineHeight: 1.5,
width: '2.25rem',
fontSize: '0.75rem',
letterSpacing: '0.4px',
color: theme.palette.text.secondary
},
'& .react-datepicker__day': {
margin: 0,
width: '2.25rem',
lineHeight: 2.75,
height: '2.25rem',
borderRadius: '50%',
color: theme.palette.text.primary,
'&.react-datepicker__day--selected, &.react-datepicker__day--keyboard-selected': {
color: theme.palette.common.white,
backgroundColor: `${theme.palette.primary.main} !important`
},
'&.react-datepicker__day--in-range, &.react-datepicker__day--in-selecting-range': {
borderRadius: 0,
color: theme.palette.primary.main,
backgroundColor: `${hexToRGBA(theme.palette.primary.main, 0.06)} !important`,
'&:empty': {
backgroundColor: 'transparent !important'
}
},
'&.react-datepicker__day--selected.react-datepicker__day--in-selecting-range.react-datepicker__day--selecting-range-start, &.react-datepicker__day--selected.react-datepicker__day--range-start.react-datepicker__day--in-range, &.react-datepicker__day--range-start':
{
borderTopLeftRadius: '50%',
borderBottomLeftRadius: '50%',
color: theme.palette.common.white,
backgroundColor: `${theme.palette.primary.main} !important`
},
'&.react-datepicker__day--range-end': {
borderTopRightRadius: '50%',
borderBottomRightRadius: '50%',
color: theme.palette.common.white,
backgroundColor: `${theme.palette.primary.main} !important`
},
'&:focus, &:active': {
outline: 0
},
'&.react-datepicker__day--outside-month': {
height: 'auto'
},
'&.react-datepicker__day--outside-month, &.react-datepicker__day--disabled:not(.react-datepicker__day--selected)':
{
color: theme.palette.text.disabled,
'&:hover': {
backgroundColor: 'transparent'
}
},
'&.react-datepicker__day--highlighted, &.react-datepicker__day--highlighted:hover': {
color: theme.palette.success.main,
backgroundColor: hexToRGBA(theme.palette.success.main, 0.12)
},
'&.react-datepicker__day--today': {
fontWeight: 'normal'
}
},
'& .react-datepicker__header__dropdown': {
'& .react-datepicker__month-dropdown-container:not(:last-child)': {
marginRight: theme.spacing(8)
},
'& .react-datepicker__month-dropdown-container, & .react-datepicker__year-dropdown-container': {
marginBottom: theme.spacing(4)
},
'& .react-datepicker__month-read-view--selected-month, & .react-datepicker__year-read-view--selected-year': {
fontSize: '0.875rem',
marginRight: theme.spacing(1),
color: theme.palette.text.primary
},
'& .react-datepicker__month-read-view:hover .react-datepicker__month-read-view--down-arrow, & .react-datepicker__year-read-view:hover .react-datepicker__year-read-view--down-arrow':
{
borderTopColor: theme.palette.text.secondary,
borderRightColor: theme.palette.text.secondary
},
'& .react-datepicker__month-read-view--down-arrow, & .react-datepicker__year-read-view--down-arrow': {
top: 4,
borderTopColor: theme.palette.text.disabled,
borderRightColor: theme.palette.text.disabled
},
'& .react-datepicker__month-dropdown, & .react-datepicker__year-dropdown': {
paddingTop: theme.spacing(1.5),
paddingBottom: theme.spacing(1.5),
borderColor: theme.palette.divider,
borderRadius: theme.shape.borderRadius,
backgroundColor: theme.palette.background.paper,
boxShadow: theme.palette.mode === 'light' ? theme.shadows[8] : theme.shadows[9]
},
'& .react-datepicker__month-option, & .react-datepicker__year-option': {
paddingTop: theme.spacing(0.5),
paddingBottom: theme.spacing(0.5),
'&:hover': {
backgroundColor: theme.palette.action.hover
}
},
'& .react-datepicker__month-option.react-datepicker__month-option--selected_month': {
backgroundColor: hexToRGBA(theme.palette.primary.main, 0.08),
'&:hover': {
backgroundColor: hexToRGBA(theme.palette.primary.main, 0.12)
},
'& .react-datepicker__month-option--selected': {
display: 'none'
}
},
'& .react-datepicker__year-option.react-datepicker__year-option--selected_year': {
backgroundColor: hexToRGBA(theme.palette.primary.main, 0.08),
'&:hover': {
backgroundColor: hexToRGBA(theme.palette.primary.main, 0.12)
},
'& .react-datepicker__year-option--selected': {
display: 'none'
}
},
'& .react-datepicker__year-option': {
// TODO: Remove some of the following styles for arrow in Year dropdown when react-datepicker give arrows in Year dropdown
'& .react-datepicker__navigation--years-upcoming': {
width: 9,
height: 9,
borderStyle: 'solid',
borderWidth: '3px 3px 0 0',
transform: 'rotate(-45deg)',
borderTopColor: theme.palette.text.disabled,
borderRightColor: theme.palette.text.disabled,
margin: `${theme.spacing(2.75)} auto ${theme.spacing(0)}`
},
'&:hover .react-datepicker__navigation--years-upcoming': {
borderTopColor: theme.palette.text.secondary,
borderRightColor: theme.palette.text.secondary
},
'& .react-datepicker__navigation--years-previous': {
width: 9,
height: 9,
borderStyle: 'solid',
borderWidth: '0 0 3px 3px',
transform: 'rotate(-45deg)',
borderLeftColor: theme.palette.text.disabled,
borderBottomColor: theme.palette.text.disabled,
margin: `${theme.spacing(0)} auto ${theme.spacing(2.75)}`
},
'&:hover .react-datepicker__navigation--years-previous': {
borderLeftColor: theme.palette.text.secondary,
borderBottomColor: theme.palette.text.secondary
}
}
},
'& .react-datepicker__month': {
marginTop: theme.spacing(3)
},
[theme.breakpoints.down('sm')]: {
'& .react-datepicker__month': {
marginLeft: 0,
marginRight: 0,
marginBottom: 0
}
},
'& .react-datepicker__month, & .react-datepicker__year': {
'& .react-datepicker__month-text, & .react-datepicker__year-text, & .react-datepicker__quarter-text': {
height: '2rem',
alignItems: 'center',
display: 'inline-flex',
justifyContent: 'center',
'&:hover': {
borderRadius: theme.shape.borderRadius
},
'&:focus, &:active': {
outline: 0
}
},
'& .react-datepicker__quarter--selected, & .react-datepicker__year-text--selected, & .react-datepicker__month--selected, & .react-datepicker__quarter-text--keyboard-selected, & .react-datepicker__month-text--keyboard-selected, & .react-datepicker__year-text--keyboard-selected':
{
color: theme.palette.common.white,
borderRadius: theme.shape.borderRadius,
backgroundColor: `${theme.palette.primary.main} !important`
},
'& .react-datepicker__week-number': {
fontWeight: 600,
color: theme.palette.text.primary
}
},
'& .react-datepicker__year-wrapper': {
maxWidth: 205,
justifyContent: 'center'
},
'& .react-datepicker__input-time-container': {
display: 'flex',
alignItems: 'center'
},
'& .react-datepicker__today-button': {
borderRadius: '1rem',
margin: '0 1rem 0.3rem',
color: theme.palette.common.white,
backgroundColor: theme.palette.primary.main
},
// ** Time Picker
'& .react-datepicker__time-container': {
borderLeftColor: theme.palette.divider
},
'&.react-datepicker--time-only, & .react-datepicker__time-container': {
width: '7rem',
padding: theme.spacing(1.2, 0),
'& .react-datepicker-time__header': {
marginBottom: theme.spacing(3),
color: theme.palette.text.primary,
fontSize: theme.typography.body2.fontSize
},
'& .react-datepicker__time': {
background: theme.palette.background.paper,
'& .react-datepicker__time-box .react-datepicker__time-list-item--disabled': {
color: theme.palette.text.disabled
}
},
'& .react-datepicker__time-list-item': {
lineHeight: 1.75,
height: 'auto !important',
marginLeft: theme.spacing(3.2),
marginRight: theme.spacing(1.2),
color: theme.palette.text.primary,
borderRadius: theme.shape.borderRadius,
'&:focus, &:active': {
outline: 0
},
'&:hover': {
backgroundColor: `${theme.palette.action.hover} !important`
},
'&.react-datepicker__time-list-item--selected': {
color: `${theme.palette.common.white} !important`,
backgroundColor: `${theme.palette.primary.main} !important`
}
},
'& .react-datepicker__time-box': {
width: '100%'
},
'& .react-datepicker__time-list': {
'&::-webkit-scrollbar': {
width: 8
},
/* Track */
'&::-webkit-scrollbar-track': {
background: theme.palette.background.paper
},
/* Handle */
'&::-webkit-scrollbar-thumb': {
background: '#aaa',
borderRadius: '10px'
},
/* Handle on hover */
'&::-webkit-scrollbar-thumb:hover': {
background: '#999'
}
}
},
'&.react-datepicker--time-only .react-datepicker__time-container': {
width: 'calc(7rem - 2px)'
},
'& .react-datepicker__day:hover, & .react-datepicker__month-text:hover, & .react-datepicker__quarter-text:hover, & .react-datepicker__year-text:hover':
{
backgroundColor: theme.palette.action.hover
}
},
'& .react-datepicker__close-icon': {
paddingRight: theme.spacing(4),
'&:after': {
width: 'unset',
height: 'unset',
fontSize: '1.5rem',
color: theme.palette.text.primary,
backgroundColor: 'transparent !important'
}
}
}
})
export default DatePickerWrapper

View File

@ -0,0 +1,49 @@
// ** MUI Imports
import CssBaseline from '@mui/material/CssBaseline'
import GlobalStyles from '@mui/material/GlobalStyles'
import { ThemeProvider, createTheme, responsiveFontSizes } from '@mui/material/styles'
// ** Theme Config
import themeConfig from 'src/configs/themeConfig'
// ** Theme Override Imports
import overrides from './overrides'
import typography from './typography'
// ** Theme
import themeOptions from './ThemeOptions'
// ** Global Styles
import GlobalStyling from './globalStyles'
const ThemeComponent = props => {
// ** Props
const { settings, children } = props
// ** Merged ThemeOptions of Core and User
const coreThemeConfig = themeOptions(settings)
// ** Pass ThemeOptions to CreateTheme Function to create partial theme without component overrides
let theme = createTheme(coreThemeConfig)
// ** Continue theme creation and pass merged component overrides to CreateTheme function
theme = createTheme(theme, {
components: { ...overrides(theme) },
typography: { ...typography(theme) }
})
// ** Set responsive font sizes to true
if (themeConfig.responsiveFontSizes) {
theme = responsiveFontSizes(theme)
}
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<GlobalStyles styles={() => GlobalStyling(theme)} />
{children}
</ThemeProvider>
)
}
export default ThemeComponent

View File

@ -0,0 +1,54 @@
// ** MUI Theme Provider
import { deepmerge } from '@mui/utils'
// ** Theme Override Imports
import palette from './palette'
import spacing from './spacing'
import shadows from './shadows'
import breakpoints from './breakpoints'
const themeOptions = settings => {
// ** Vars
const { mode, themeColor } = settings
const themeConfig = {
palette: palette(mode, themeColor),
typography: {
fontFamily: [
'Inter',
'sans-serif',
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'Roboto',
'"Helvetica Neue"',
'Arial',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"'
].join(',')
},
shadows: shadows(mode),
...spacing,
breakpoints: breakpoints(),
shape: {
borderRadius: 6
},
mixins: {
toolbar: {
minHeight: 64
}
}
}
return deepmerge(themeConfig, {
palette: {
primary: {
...themeConfig.palette[themeColor]
}
}
})
}
export default themeOptions

View File

@ -0,0 +1,11 @@
const breakpoints = () => ({
values: {
xs: 0,
sm: 600,
md: 900,
lg: 1200,
xl: 1536
}
})
export default breakpoints

View File

@ -0,0 +1,43 @@
const GlobalStyles = theme => {
return {
'.ps__rail-y': {
zIndex: 1,
right: '0 !important',
left: 'auto !important',
'&:hover, &:focus, &.ps--clicking': {
backgroundColor: theme.palette.mode === 'light' ? '#E4E5EB !important' : '#423D5D !important'
},
'& .ps__thumb-y': {
right: '3px !important',
left: 'auto !important',
backgroundColor: theme.palette.mode === 'light' ? '#C2C4D1 !important' : '#504B6D !important'
},
'.layout-vertical-nav &': {
'& .ps__thumb-y': {
width: 4,
backgroundColor: theme.palette.mode === 'light' ? '#C2C4D1 !important' : '#504B6D !important'
},
'&:hover, &:focus, &.ps--clicking': {
backgroundColor: 'transparent !important',
'& .ps__thumb-y': {
width: 6
}
}
}
},
'#nprogress': {
pointerEvents: 'none',
'& .bar': {
left: 0,
top: 0,
height: 3,
width: '100%',
zIndex: 2000,
position: 'fixed',
backgroundColor: theme.palette.primary.main
}
}
}
}
export default GlobalStyles

View File

@ -0,0 +1,46 @@
const Accordion = theme => {
return {
MuiAccordion: {
styleOverrides: {
root: {
'&.Mui-disabled': {
backgroundColor: `rgba(${theme.palette.customColors.main}, 0.12)`
},
'&.Mui-expanded': {
boxShadow: theme.shadows[3]
}
}
}
},
MuiAccordionSummary: {
styleOverrides: {
root: {
padding: `0 ${theme.spacing(5)}`,
'& + .MuiCollapse-root': {
'& .MuiAccordionDetails-root:first-child': {
paddingTop: 0
}
}
},
content: {
margin: `${theme.spacing(2.5)} 0`
},
expandIconWrapper: {
color: theme.palette.text.secondary
}
}
},
MuiAccordionDetails: {
styleOverrides: {
root: {
padding: theme.spacing(5),
'& + .MuiAccordionDetails-root': {
paddingTop: 0
}
}
}
}
}
}
export default Accordion

View File

@ -0,0 +1,110 @@
import { lighten, darken } from '@mui/material/styles'
// ** Util Import
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba'
const Alert = theme => {
const getColor = theme.palette.mode === 'light' ? darken : lighten
return {
MuiAlert: {
styleOverrides: {
root: {
borderRadius: 5,
'& .MuiAlertTitle-root': {
marginBottom: theme.spacing(1.6)
},
'& a': {
color: 'inherit',
fontWeight: 500
}
},
standardSuccess: {
color: getColor(theme.palette.success.main, 0.12),
backgroundColor: hexToRGBA(theme.palette.success.main, 0.12),
'& .MuiAlertTitle-root': {
color: getColor(theme.palette.success.main, 0.12)
},
'& .MuiAlert-icon': {
color: getColor(theme.palette.success.main, 0.12)
}
},
standardInfo: {
color: getColor(theme.palette.info.main, 0.12),
backgroundColor: hexToRGBA(theme.palette.info.main, 0.12),
'& .MuiAlertTitle-root': {
color: getColor(theme.palette.info.main, 0.12)
},
'& .MuiAlert-icon': {
color: getColor(theme.palette.info.main, 0.12)
}
},
standardWarning: {
color: getColor(theme.palette.warning.main, 0.12),
backgroundColor: hexToRGBA(theme.palette.warning.main, 0.12),
'& .MuiAlertTitle-root': {
color: getColor(theme.palette.warning.main, 0.12)
},
'& .MuiAlert-icon': {
color: getColor(theme.palette.warning.main, 0.12)
}
},
standardError: {
color: getColor(theme.palette.error.main, 0.12),
backgroundColor: hexToRGBA(theme.palette.error.main, 0.12),
'& .MuiAlertTitle-root': {
color: getColor(theme.palette.error.main, 0.12)
},
'& .MuiAlert-icon': {
color: getColor(theme.palette.error.main, 0.12)
}
},
outlinedSuccess: {
borderColor: theme.palette.success.main,
color: getColor(theme.palette.success.main, 0.12),
'& .MuiAlertTitle-root': {
color: getColor(theme.palette.success.main, 0.12)
},
'& .MuiAlert-icon': {
color: getColor(theme.palette.success.main, 0.12)
}
},
outlinedInfo: {
borderColor: theme.palette.info.main,
color: getColor(theme.palette.info.main, 0.12),
'& .MuiAlertTitle-root': {
color: getColor(theme.palette.info.main, 0.12)
},
'& .MuiAlert-icon': {
color: getColor(theme.palette.info.main, 0.12)
}
},
outlinedWarning: {
borderColor: theme.palette.warning.main,
color: getColor(theme.palette.warning.main, 0.12),
'& .MuiAlertTitle-root': {
color: getColor(theme.palette.warning.main, 0.12)
},
'& .MuiAlert-icon': {
color: getColor(theme.palette.warning.main, 0.12)
}
},
outlinedError: {
borderColor: theme.palette.error.main,
color: getColor(theme.palette.error.main, 0.12),
'& .MuiAlertTitle-root': {
color: getColor(theme.palette.error.main, 0.12)
},
'& .MuiAlert-icon': {
color: getColor(theme.palette.error.main, 0.12)
}
},
filled: {
fontWeight: 400
}
}
}
}
}
export default Alert

View File

@ -0,0 +1,27 @@
const Avatar = theme => {
return {
MuiAvatar: {
styleOverrides: {
colorDefault: {
color: theme.palette.text.secondary,
backgroundColor: theme.palette.mode === 'light' ? theme.palette.grey[200] : theme.palette.grey[700]
},
rounded: {
borderRadius: 5
}
}
},
MuiAvatarGroup: {
styleOverrides: {
root: {
justifyContent: 'flex-end',
'.MuiCard-root & .MuiAvatar-root': {
borderColor: theme.palette.background.paper
}
}
}
}
}
}
export default Avatar

View File

@ -0,0 +1,22 @@
// ** Util Import
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba'
const Backdrop = theme => {
return {
MuiBackdrop: {
styleOverrides: {
root: {
backgroundColor:
theme.palette.mode === 'light'
? `rgba(${theme.palette.customColors.main}, 0.7)`
: hexToRGBA(theme.palette.background.default, 0.7)
},
invisible: {
backgroundColor: 'transparent'
}
}
}
}
}
export default Backdrop

View File

@ -0,0 +1,50 @@
// ** Theme Config Imports
import themeConfig from 'src/configs/themeConfig'
const Button = theme => {
return {
MuiButton: {
styleOverrides: {
root: {
fontWeight: 500,
borderRadius: 5,
lineHeight: 1.71,
letterSpacing: '0.3px',
padding: `${theme.spacing(1.875, 3)}`
},
contained: {
boxShadow: theme.shadows[3],
padding: `${theme.spacing(1.875, 5.5)}`
},
outlined: {
padding: `${theme.spacing(1.625, 5.25)}`
},
sizeSmall: {
padding: `${theme.spacing(1, 2.25)}`,
'&.MuiButton-contained': {
padding: `${theme.spacing(1, 3.5)}`
},
'&.MuiButton-outlined': {
padding: `${theme.spacing(0.75, 3.25)}`
}
},
sizeLarge: {
padding: `${theme.spacing(2.125, 5.5)}`,
'&.MuiButton-contained': {
padding: `${theme.spacing(2.125, 6.5)}`
},
'&.MuiButton-outlined': {
padding: `${theme.spacing(1.875, 6.25)}`
}
}
}
},
MuiButtonBase: {
defaultProps: {
disableRipple: themeConfig.disableRipple
}
}
}
}
export default Button

View File

@ -0,0 +1,83 @@
const Card = theme => {
return {
MuiCard: {
styleOverrides: {
root: {
boxShadow: theme.shadows[6],
'& .card-more-options': {
marginTop: theme.spacing(-1),
marginRight: theme.spacing(-3)
}
}
}
},
MuiCardHeader: {
styleOverrides: {
root: {
padding: theme.spacing(5),
'& + .MuiCardContent-root, & + .MuiCollapse-root .MuiCardContent-root': {
paddingTop: 0
},
'& .MuiCardHeader-subheader': {
fontSize: '0.875rem'
}
},
title: {
lineHeight: 1,
fontWeight: 500,
fontSize: '1.25rem',
letterSpacing: '0.0125em'
},
action: {
marginTop: 0,
marginRight: 0
}
}
},
MuiCardContent: {
styleOverrides: {
root: {
padding: theme.spacing(5),
'& + .MuiCardContent-root': {
paddingTop: 0
},
'&:last-of-type': {
paddingBottom: theme.spacing(5)
},
'& + .MuiCardActions-root': {
paddingTop: 0
}
}
}
},
MuiCardActions: {
styleOverrides: {
root: {
padding: theme.spacing(5),
'&.card-action-dense': {
padding: theme.spacing(0, 2.5, 2.5),
'.MuiCard-root .MuiCardMedia-root + &': {
paddingTop: theme.spacing(2.5)
},
'.MuiCard-root &:first-of-type': {
paddingTop: theme.spacing(5),
paddingBottom: theme.spacing(5),
'& + .MuiCardContent-root': {
paddingTop: 0
},
'& + .MuiCardHeader-root': {
paddingTop: 0
}
}
},
'& .MuiButton-text': {
paddingLeft: theme.spacing(2.5),
paddingRight: theme.spacing(2.5)
}
}
}
}
}
}
export default Card

View File

@ -0,0 +1,19 @@
const Chip = theme => {
return {
MuiChip: {
styleOverrides: {
outlined: {
'&.MuiChip-colorDefault': {
borderColor: `rgba(${theme.palette.customColors.main}, 0.22)`
}
},
deleteIcon: {
width: 18,
height: 18
}
}
}
}
}
export default Chip

View File

@ -0,0 +1,61 @@
const DateTimePicker = theme => {
return {
MuiCalendarPicker: {
styleOverrides: {
root: {
'& [role="presentation"]': {
fontWeight: 400,
'& .PrivatePickersFadeTransitionGroup-root + .PrivatePickersFadeTransitionGroup-root > div': {
marginRight: 0
},
'& .MuiIconButton-sizeSmall': {
padding: theme.spacing(0.5)
},
'& + div .MuiIconButton-root:not(.Mui-disabled)': {
color: theme.palette.text.secondary
}
},
'& .PrivatePickersSlideTransition-root': {
minHeight: 240
}
}
}
},
MuiPickersDay: {
styleOverrides: {
root: {
fontSize: '0.875rem'
}
}
},
MuiClockPicker: {
styleOverrides: {
arrowSwitcher: {
'& .MuiIconButton-root:not(.Mui-disabled)': {
color: theme.palette.text.secondary
},
'& + div': {
'& > div': {
backgroundColor:
theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default,
'& ~ .MuiIconButton-root span.MuiTypography-caption': {
color: 'inherit'
}
}
}
}
}
},
MuiMonthPicker: {
styleOverrides: {
root: {
'& > .MuiTypography-root.Mui-selected': {
fontSize: '1rem'
}
}
}
}
}
}
export default DateTimePicker

View File

@ -0,0 +1,104 @@
// ** Util Import
import { hexToRGBA } from 'src/@core/utils/hex-to-rgba'
const Dialog = theme => {
return {
MuiDialog: {
styleOverrides: {
paper: {
boxShadow: theme.shadows[6],
'&:not(.MuiDialog-paperFullScreen)': {
'@media (max-width:599px)': {
margin: theme.spacing(4),
width: `calc(100% - ${theme.spacing(8)})`,
maxWidth: `calc(100% - ${theme.spacing(8)}) !important`
}
},
'& > .MuiList-root': {
paddingLeft: theme.spacing(1),
paddingRight: theme.spacing(1)
}
}
}
},
MuiDialogTitle: {
styleOverrides: {
root: {
padding: theme.spacing(5)
}
}
},
MuiDialogContent: {
styleOverrides: {
root: {
padding: theme.spacing(5),
'& + .MuiDialogContent-root': {
paddingTop: 0
},
'& + .MuiDialogActions-root': {
paddingTop: 0
},
// Styling for Mobile Date Picker starts
'& .PrivatePickersToolbar-root': {
padding: theme.spacing(4, 5),
color: theme.palette.primary.contrastText,
backgroundColor: theme.palette.primary.main,
'& .MuiTypography-root': {
color: theme.palette.primary.contrastText
},
'& span.MuiTypography-overline': {
fontSize: '1rem',
lineHeight: '24px',
letterSpacing: '0.15px'
},
'& ~ div[class^="css-"] > div[class^="css-"]': {
marginTop: theme.spacing(6),
marginBottom: theme.spacing(6),
'& > div[class^="css-"]': {
backgroundColor:
theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default,
'& ~ .MuiIconButton-root span.MuiTypography-caption': {
color: 'inherit'
}
}
},
'& .PrivateTimePickerToolbar-hourMinuteLabel': {
alignItems: 'center',
'& > .MuiButton-root span.MuiTypography-root': {
fontWeight: 300,
lineHeight: '72px',
fontSize: '3.75rem',
letterSpacing: '-0.5px'
},
'& > .MuiTypography-root': {
color: hexToRGBA(theme.palette.primary.contrastText, 0.54),
'& + .MuiButton-root > span.MuiTypography-root': {
color: hexToRGBA(theme.palette.primary.contrastText, 0.54)
}
}
},
'& .PrivateTimePickerToolbar-ampmSelection span.MuiTypography-root:not(.Mui-selected)': {
color: hexToRGBA(theme.palette.primary.contrastText, 0.54)
}
}
// Styling for Mobile Date Picker ends
}
}
},
MuiDialogActions: {
styleOverrides: {
root: {
padding: theme.spacing(5),
'&.dialog-actions-dense': {
padding: theme.spacing(2.5),
paddingTop: 0
}
}
}
}
}
}
export default Dialog

View File

@ -0,0 +1,13 @@
const Divider = theme => {
return {
MuiDivider: {
styleOverrides: {
root: {
margin: `${theme.spacing(2)} 0`
}
}
}
}
}
export default Divider

View File

@ -0,0 +1,85 @@
// ** Overrides Imports
import MuiCard from './card'
import MuiChip from './chip'
import MuiLink from './link'
import MuiList from './list'
import MuiMenu from './menu'
import MuiTabs from './tabs'
import MuiInput from './input'
import MuiPaper from './paper'
import MuiTable from './table'
import MuiAlerts from './alerts'
import MuiButton from './button'
import MuiDialog from './dialog'
import MuiRating from './rating'
import MuiSelect from './select'
import MuiAvatar from './avatars'
import MuiDivider from './divider'
import MuiPopover from './popover'
import MuiTooltip from './tooltip'
import MuiBackdrop from './backdrop'
import MuiSnackbar from './snackbar'
import MuiSwitches from './switches'
import MuiTimeline from './timeline'
import MuiAccordion from './accordion'
import MuiPagination from './pagination'
import MuiTypography from './typography'
import MuiToggleButton from './toggleButton'
import MuiDateTimePicker from './dateTimePicker'
const Overrides = theme => {
const chip = MuiChip(theme)
const list = MuiList(theme)
const menu = MuiMenu(theme)
const tabs = MuiTabs(theme)
const cards = MuiCard(theme)
const input = MuiInput(theme)
const tables = MuiTable(theme)
const alerts = MuiAlerts(theme)
const button = MuiButton(theme)
const rating = MuiRating(theme)
const avatars = MuiAvatar(theme)
const divider = MuiDivider(theme)
const dialog = MuiDialog(theme)
const popover = MuiPopover(theme)
const tooltip = MuiTooltip(theme)
const backdrop = MuiBackdrop(theme)
const snackbar = MuiSnackbar(theme)
const switches = MuiSwitches(theme)
const timeline = MuiTimeline(theme)
const accordion = MuiAccordion(theme)
const pagination = MuiPagination(theme)
const dateTimePicker = MuiDateTimePicker(theme)
return Object.assign(
chip,
list,
menu,
tabs,
cards,
input,
alerts,
button,
dialog,
rating,
tables,
avatars,
divider,
MuiLink,
popover,
tooltip,
backdrop,
MuiPaper,
snackbar,
switches,
timeline,
accordion,
MuiSelect,
pagination,
MuiTypography,
dateTimePicker,
MuiToggleButton
)
}
export default Overrides

View File

@ -0,0 +1,62 @@
const input = theme => {
return {
MuiInputLabel: {
styleOverrides: {
root: {
color: theme.palette.text.secondary
}
}
},
MuiInput: {
styleOverrides: {
root: {
'&:before': {
borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.22)`
},
'&:hover:not(.Mui-disabled):before': {
borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.32)`
},
'&.Mui-disabled:before': {
borderBottom: `1px solid ${theme.palette.text.disabled}`
}
}
}
},
MuiFilledInput: {
styleOverrides: {
root: {
backgroundColor: `rgba(${theme.palette.customColors.main}, 0.04)`,
'&:hover:not(.Mui-disabled)': {
backgroundColor: `rgba(${theme.palette.customColors.main}, 0.08)`
},
'&:before': {
borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.22)`
},
'&:hover:not(.Mui-disabled):before': {
borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.32)`
}
}
}
},
MuiOutlinedInput: {
styleOverrides: {
root: {
'&:hover:not(.Mui-focused) .MuiOutlinedInput-notchedOutline': {
borderColor: `rgba(${theme.palette.customColors.main}, 0.32)`
},
'&:hover.Mui-error .MuiOutlinedInput-notchedOutline': {
borderColor: theme.palette.error.main
},
'& .MuiOutlinedInput-notchedOutline': {
borderColor: `rgba(${theme.palette.customColors.main}, 0.22)`
},
'&.Mui-disabled .MuiOutlinedInput-notchedOutline': {
borderColor: theme.palette.text.disabled
}
}
}
}
}
}
export default input

View File

@ -0,0 +1,9 @@
export default {
MuiLink: {
styleOverrides: {
root: {
textDecoration: 'none'
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More