main
Lim Jonguk 3 years ago
commit 4f62ca2f21

@ -0,0 +1 @@
REACT_APP_VERSION = v3.1.0

@ -0,0 +1,58 @@
{
"root": true,
"env": {
"browser": true,
"es2021": true
},
"extends": ["airbnb", "prettier", "plugin:react/jsx-runtime", "plugin:jsx-a11y/recommended", "plugin:react-hooks/recommended"],
"settings": {
"import/resolver": {
"node": {
"moduleDirectory": ["node_modules", "src/"]
}
}
},
"parser": "@babel/eslint-parser",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"impliedStrict": true
},
"ecmaVersion": 12
},
"plugins": ["prettier", "react", "react-hooks"],
"rules": {
"react/jsx-filename-extension": 0,
"no-param-reassign": 0,
"react/prop-types": 1,
"react/require-default-props": 0,
"react/no-array-index-key": 0,
"react/jsx-props-no-spreading": 0,
"react/forbid-prop-types": 0,
"import/order": 0,
"import/no-cycle": 0,
"no-console": 0,
"jsx-a11y/anchor-is-valid": 0,
"prefer-destructuring": 0,
"no-shadow": 0,
"import/no-named-as-default": 0,
"no-unused-vars": [
1,
{
"ignoreRestSiblings": false
}
],
"prettier/prettier": [
2,
{
"bracketSpacing": true,
"printWidth": 140,
"singleQuote": true,
"trailingComma": "none",
"tabWidth": 2,
"useTabs": false,
"endOfLine": "auto"
}
]
}
}

24
.gitignore vendored

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

@ -0,0 +1,8 @@
{
"bracketSpacing": true,
"printWidth": 140,
"singleQuote": true,
"trailingComma": "none",
"tabWidth": 2,
"useTabs": false
}

@ -0,0 +1,12 @@
# Introduction
This is material design template created based on materially structure
# Getting Started
1. Installation process
- run 'npm install / yarn'
- start dev server run 'npm run start / yarn start'
2. Deployment process
- Goto full-version directory and open package.json. Update homepage URL to the production URL
- Goto full-version directory and run 'npm run build / yarn build'

@ -0,0 +1,9 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"baseUrl": "src"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}

46759
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,131 @@
{
"name": "berry-material-react",
"version": "3.1.0",
"private": true,
"dependencies": {
"@auth0/auth0-spa-js": "^1.19.4",
"@emotion/cache": "^11.7.1",
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"@fullcalendar/daygrid": "^5.10.1",
"@fullcalendar/interaction": "^5.10.1",
"@fullcalendar/list": "^5.10.1",
"@fullcalendar/react": "^5.10.1",
"@fullcalendar/timegrid": "^5.10.1",
"@fullcalendar/timeline": "^5.10.1",
"@hookform/resolvers": "^2.8.8",
"@mui/icons-material": "^5.4.1",
"@mui/lab": "^5.0.0-alpha.68",
"@mui/material": "^5.4.1",
"@mui/styles": "^5.4.1",
"@mui/system": "^5.4.1",
"@mui/utils": "^5.4.1",
"@mui/x-data-grid": "^5.5.0",
"@reduxjs/toolkit": "^1.7.2",
"@tabler/icons": "^1.53.0",
"amazon-cognito-identity-js": "^5.2.6",
"apexcharts": "^3.33.1",
"axios": "^0.25.0",
"axios-mock-adapter": "^1.20.0",
"chance": "^1.1.8",
"csstype": "^3.0.10",
"date-fns": "^2.28.0",
"draft-js": "^0.11.7",
"emoji-picker-react": "^3.5.1",
"firebase": "^9.6.6",
"formik": "^2.2.9",
"framer-motion": "^4.1.13",
"history": "^5.2.0",
"image-to-base64": "^2.2.0",
"jsonwebtoken": "^8.5.1",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21",
"material-ui-popup-state": "^2.0.0",
"prop-types": "^15.8.1",
"react": "^17.0.2",
"react-apexcharts": "^1.3.9",
"react-beautiful-dnd": "^13.1.0",
"react-copy-to-clipboard": "^5.0.4",
"react-currency-format": "^1.1.0",
"react-dom": "^17.0.2",
"react-draft-wysiwyg": "^1.14.7",
"react-draggable": "^4.4.4",
"react-dropzone": "^12.0.2",
"react-google-recaptcha": "^2.1.0",
"react-hook-form": "^7.26.1",
"react-images": "^1.2.0-beta.7",
"react-intersection-observer": "^8.33.1",
"react-intl": "^5.24.6",
"react-markdown": "^8.0.0",
"react-number-format": "^4.9.1",
"react-organizational-chart": "^2.1.1",
"react-otp-input-rc-17": "^2.4.1-minor",
"react-perfect-scrollbar": "^1.5.8",
"react-quill": "^2.0.0-beta.4",
"react-redux": "^7.2.6",
"react-router-dom": "^6.2.1",
"react-scripts": "^4.0.3",
"react-slick": "^0.28.1",
"react-syntax-highlighter": "^15.4.5",
"react-timer-hook": "^3.0.5",
"react-to-print": "^2.14.4",
"react-window": "^1.8.6",
"redux": "^4.1.2",
"redux-persist": "^6.0.0",
"remark-gfm": "^3.0.1",
"slick-carousel": "^1.8.1",
"stylis-plugin-rtl": "^2.1.1",
"typescript": "^4.5.5",
"uuid": "^8.3.2",
"web-vitals": "^2.1.4",
"yup": "^0.32.11"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"format": "prettier --write ."
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"babel": {
"presets": [
"@babel/preset-react"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/core": "^7.17.2",
"@babel/eslint-parser": "^7.15.8",
"eslint": "^7.27.0",
"eslint-config-airbnb-typescript": "^12.3.1",
"eslint-config-prettier": "^8.3.0",
"eslint-config-react-app": "6.0.0",
"eslint-import-resolver-typescript": "^2.5.0",
"eslint-plugin-flowtype": "^5.7.2",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
"prettier": "^2.5.1",
"react-error-overlay": "6.0.9",
"sass": "^1.49.7"
}
}

@ -0,0 +1,18 @@
<svg width="46" height="55" viewBox="0 0 46 55" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0)">
<path d="M19.6667 55C8.82205 55 0 46.2504 0 35.4968C0 24.7431 8.82292 15.9935 19.6667 15.9935C30.5105 15.9935 39.3334 24.7431 39.3334 35.4968C39.3334 46.2504 30.5122 55 19.6667 55ZM19.6667 17.8563C9.8587 17.8563 1.87839 25.7686 1.87839 35.4959C1.87839 45.2233 9.8587 53.1355 19.6667 53.1355C29.4747 53.1355 37.4559 45.2215 37.4559 35.4942C37.4559 25.7668 29.4765 17.8563 19.6667 17.8563Z" fill="#2196F3"/>
<path d="M33.9387 36.3618C33.3269 34.1133 27.7188 33.8706 24.3807 34.6949C22.6326 35.1283 20.846 35.6917 19.0034 36.0159C20.3521 37.2026 21.8005 38.3251 23.879 38.6042C29.0361 39.2942 32.2404 37.6898 33.9387 36.3618Z" fill="#2196F3"/>
<path d="M23.8788 38.6042C21.7959 38.3251 20.3519 37.2026 19.0032 36.016C16.9159 34.1792 15.0594 32.189 11.4154 32.9379C5.62198 34.1289 4.85978 40.9247 9.3333 45.2917C11.254 47.2864 13.7197 48.6822 16.4284 49.3079C19.137 49.9336 21.9709 49.7621 24.5828 48.8144C27.1946 47.8667 29.4709 46.1839 31.1327 43.9724C32.7945 41.7608 33.7696 39.1165 33.9385 36.3635C32.2402 37.6898 29.0358 39.2942 23.8788 38.6042Z" fill="#673AB7"/>
<path d="M26.9105 23.8962C26.1876 25.4331 32.6321 27.1381 33.4031 32.2419C33.7746 27.2178 27.8046 21.9962 26.9105 23.8962Z" fill="#2196F3"/>
<path d="M13.3649 30.3107C14.5267 29.8335 15.0784 28.5126 14.5972 27.3604C14.116 26.2083 12.784 25.6611 11.6222 26.1384C10.4604 26.6156 9.90867 27.9365 10.3899 29.0887C10.8712 30.2408 12.2031 30.7879 13.3649 30.3107Z" fill="#673AB7"/>
<path d="M18.5351 24.1103C19.0786 23.5714 19.0786 22.6977 18.5351 22.1587C17.9917 21.6198 17.1106 21.6198 16.5672 22.1587C16.0238 22.6977 16.0238 23.5714 16.5672 24.1103C17.1106 24.6492 17.9917 24.6492 18.5351 24.1103Z" fill="#2196F3"/>
<path d="M23.4513 15.2376C25.4617 9.3485 24.1103 4.64345 19.9786 2.40881C17.1544 2.97831 15.4779 4.334 14.5444 6.20544C20.0843 5.76077 23.5999 9.1994 23.4513 15.2376Z" fill="#2196F3"/>
<path d="M46.0001 10.0923C36.0487 6.55051 29.7685 7.76491 28.7808 15.8349C34.4841 21.6703 40.2286 18.8774 46.0001 10.0923Z" fill="#2196F3"/>
<path d="M38.0851 6.89635C38.5466 4.94082 38.7861 2.6299 38.8219 0C28.5017 2.27885 23.8473 6.6337 27.3584 13.9782C27.5333 14.0198 27.7011 14.0536 27.8698 14.0883C28.6905 8.34132 32.3031 6.2133 38.0851 6.89635Z" fill="#2196F3"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="46" height="55" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Berry - React Material Admin Dashboard Template</title>
<link rel="icon" href="%PUBLIC_URL%/favicon.svg" />
<!-- Meta Tags-->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#2296f3" />
<meta name="title" content="Berry - React Material Admin Dashboard Template by CodedThemes" />
<meta
name="description"
content="Start your next React project with Berry admin template. It build with Reactjs, Material-UI, Redux, and Hook for faster web development."
/>
<meta
name="keywords"
content="react admin template, material-ui react dashboard template, reactjs admin template, reactjs dashboard, react backend template"
/>
<meta name="author" content="CodedThemes" />
<!-- Open Graph / Facebook -->
<meta property="og:locale" content="en_US" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://berrydashboard.io/" />
<meta property="og:site_name" content="berrydashboard.io" />
<meta property="article:publisher" content="https://www.facebook.com/codedthemes" />
<meta property="og:title" content="Berry - React Material Dashboard Template" />
<meta
property="og:description"
content="Berry Dashboard is made for the faster web application development built using Material-UI, Reactjs, Redux & Hook API."
/>
<meta property="og:image" content="https://berrydashboard.io/og-image/og-facebook.png" />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content="https://berrydashboard.io" />
<meta property="twitter:title" content="Berry - React Material Dashboard Template" />
<meta
property="twitter:description"
content="Berry Dashboard is made for the faster web application development built using Material-UI, Reactjs, Redux & Hook API."
/>
<meta property="twitter:image" content="https://berrydashboard.io/og-image/og-twitter.png" />
<meta name="twitter:creator" content="@codedthemes" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@400;500;600;700&family=Roboto:wght@400;500;700&display=swap"
rel="stylesheet"
crossorigin="anonymous"
/>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<script type="text/javascript">
(function (c, l, a, r, i, t, y) {
c[a] =
c[a] ||
function () {
(c[a].q = c[a].q || []).push(arguments);
};
t = l.createElement(r);
t.async = 1;
t.src = 'https://www.clarity.ms/tag/' + i;git
y = l.getElementsByTagName(r)[0];
y.parentNode.insertBefore(t, y);
})(window, document, 'clarity', 'script', '6sbb1vpcjo');
</script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-X1LG1CJ1GG"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-X1LG1CJ1GG');
gtag('event', 'action', { non_interaction: true });
</script>
</body>
</html>

@ -0,0 +1,37 @@
// routing
import Routes from 'routes';
// project imports
import Locales from 'ui-component/Locales';
import NavigationScroll from 'layout/NavigationScroll';
import RTLLayout from 'ui-component/RTLLayout';
import Snackbar from 'ui-component/extended/Snackbar';
import ThemeCustomization from 'themes';
// auth provider
import { FirebaseProvider as AuthProvider } from 'contexts/FirebaseContext';
// import { AWSCognitoProvider as AuthProvider } from 'contexts/AWSCognitoContext';
// import { JWTProvider as AuthProvider } from 'contexts/JWTContext';
// import { Auth0Provider as AuthProvider } from 'contexts/Auth0Context';
// ==============================|| APP ||============================== //
const App = () => (
<ThemeCustomization>
{/* RTL layout */}
<RTLLayout>
<Locales>
<NavigationScroll>
<AuthProvider>
<>
<Routes />
<Snackbar />
</>
</AuthProvider>
</NavigationScroll>
</Locales>
</RTLLayout>
</ThemeCustomization>
);
export default App;

@ -0,0 +1,6 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.06129 13.2253L4.31871 15.9975L1.60458 16.0549C0.793457 14.5504 0.333374 12.8292 0.333374 11C0.333374 9.23119 0.763541 7.56319 1.52604 6.09448H1.52662L3.94296 6.53748L5.00146 8.93932C4.77992 9.58519 4.65917 10.2785 4.65917 11C4.65925 11.783 4.80108 12.5332 5.06129 13.2253Z" fill="#FBBB00"/>
<path d="M21.4804 9.00732C21.6029 9.65257 21.6668 10.3189 21.6668 11C21.6668 11.7637 21.5865 12.5086 21.4335 13.2271C20.9143 15.6722 19.5575 17.8073 17.678 19.3182L17.6774 19.3177L14.6339 19.1624L14.2031 16.4734C15.4503 15.742 16.425 14.5974 16.9384 13.2271H11.2346V9.00732H17.0216H21.4804Z" fill="#518EF8"/>
<path d="M17.6772 19.3176L17.6777 19.3182C15.8498 20.7875 13.5277 21.6666 11 21.6666C6.93783 21.6666 3.40612 19.3962 1.60449 16.0549L5.0612 13.2253C5.96199 15.6294 8.28112 17.3408 11 17.3408C12.1686 17.3408 13.2634 17.0249 14.2029 16.4734L17.6772 19.3176Z" fill="#28B446"/>
<path d="M17.8085 2.78892L14.353 5.61792C13.3807 5.01017 12.2313 4.65908 11 4.65908C8.21963 4.65908 5.85713 6.44896 5.00146 8.93925L1.52658 6.09442H1.526C3.30125 2.67171 6.8775 0.333252 11 0.333252C13.5881 0.333252 15.9612 1.25517 17.8085 2.78892Z" fill="#F14336"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 250 KiB

@ -0,0 +1,157 @@
// paper & background
$paper: #ffffff;
// primary
$primaryLight: #eceff1;
$primaryMain: #607d8b;
$primaryDark: #546e7a;
$primary200: #b0bec5;
$primary800: #455a64;
// secondary
$secondaryLight: #e0f2f1;
$secondaryMain: #009688;
$secondaryDark: #00897b;
$secondary200: #80cbc4;
$secondary800: #00695c;
// success Colors
$successLight: #edf7ed;
$success200: #b6e0b3;
$successMain: #6cc067;
$successDark: #64ba5f;
// error
$errorLight: #e48784;
$errorMain: #d9534f;
$errorDark: #d54c48;
// orange
$orangeLight: #fbe9e7;
$orangeMain: #ffab91;
$orangeDark: #d84315;
// warning
$warningLight: #fdf5ea;
$warningMain: #f0ad4e;
$warningDark: #ec9c3d;
// grey
$grey50: #fafafa;
$grey100: #f5f5f5;
$grey200: #eeeeee;
$grey300: #e0e0e0;
$grey500: #9e9e9e;
$grey600: #757575;
$grey700: #616161;
$grey900: #212121;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
$darkBackground: #0e1b23; // level 3
$darkPaper: #060d12; // level 4
// dark 800 & 900
$darkLevel1: #0b161d; // level 1
$darkLevel2: #14252f; // level 2
// primary dark
$darkPrimaryLight: #eceff1;
$darkPrimaryMain: #78919c;
$darkPrimaryDark: #587583;
$darkPrimary200: #b0bec5;
$darkPrimary800: #44606e;
// secondary dark
$darkSecondaryLight: #e0f2f1;
$darkSecondaryMain: #009688;
$darkSecondaryDark: #00897b;
$darkSecondary200: #80cbc4;
$darkSecondary800: #00695c;
// text variants
$darkTextTitle: #e4e8f7;
$darkTextPrimary: #d5d9e9;
$darkTextSecondary: #d8ddf0;
// ==============================|| JAVASCRIPT ||============================== //
:export {
// paper & background
paper: $paper;
// primary
primaryLight: $primaryLight;
primary200: $primary200;
primaryMain: $primaryMain;
primaryDark: $primaryDark;
primary800: $primary800;
// secondary
secondaryLight: $secondaryLight;
secondary200: $secondary200;
secondaryMain: $secondaryMain;
secondaryDark: $secondaryDark;
secondary800: $secondary800;
// success
successLight: $successLight;
success200: $success200;
successMain: $successMain;
successDark: $successDark;
// error
errorLight: $errorLight;
errorMain: $errorMain;
errorDark: $errorDark;
// orange
orangeLight: $orangeLight;
orangeMain: $orangeMain;
orangeDark: $orangeDark;
// warning
warningLight: $warningLight;
warningMain: $warningMain;
warningDark: $warningDark;
// grey
grey50: $grey50;
grey100: $grey100;
grey200: $grey200;
grey300: $grey300;
grey500: $grey500;
grey600: $grey600;
grey700: $grey700;
grey900: $grey900;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
darkPaper: $darkPaper;
darkBackground: $darkBackground;
// dark 800 & 900
darkLevel1: $darkLevel1;
darkLevel2: $darkLevel2;
// text variants
darkTextTitle: $darkTextTitle;
darkTextPrimary: $darkTextPrimary;
darkTextSecondary: $darkTextSecondary;
// primary dark
darkPrimaryLight: $darkPrimaryLight;
darkPrimaryMain: $darkPrimaryMain;
darkPrimaryDark: $darkPrimaryDark;
darkPrimary200: $darkPrimary200;
darkPrimary800: $darkPrimary800;
// secondary dark
darkSecondaryLight: $darkSecondaryLight;
darkSecondaryMain: $darkSecondaryMain;
darkSecondaryDark: $darkSecondaryDark;
darkSecondary200: $darkSecondary200;
darkSecondary800: $darkSecondary800;
}

@ -0,0 +1,157 @@
// paper & background
$paper: #ffffff;
// primary
$primaryLight: #e4e7ec;
$primaryMain: #203461;
$primaryDark: #1c2f59;
$primary200: #909ab0;
$primary800: #132145;
// secondary
$secondaryLight: #fde8ef;
$secondaryMain: #ec407a;
$secondaryDark: #ea3a72;
$secondary200: #f6a0bd;
$secondary800: #e42a5d;
// success Colors
$successLight: #e3f8e8;
$success200: #8be09f;
$successMain: #17c13e;
$successDark: #14bb38;
// error
$errorLight: #e48784;
$errorMain: #d9534f;
$errorDark: #d54c48;
// orange
$orangeLight: #fbe9e7;
$orangeMain: #ffab91;
$orangeDark: #d84315;
// warning
$warningLight: #fdf5ea;
$warningMain: #f0ad4e;
$warningDark: #ec9c3d;
// grey
$grey50: #fafafa;
$grey100: #f5f5f5;
$grey200: #eeeeee;
$grey300: #e0e0e0;
$grey500: #9e9e9e;
$grey600: #757575;
$grey700: #616161;
$grey900: #212121;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
$darkBackground: #0a0f23; // level 3
$darkPaper: #030614; // level 4
// dark 800 & 900
$darkLevel1: #070e13; // level 1
$darkLevel2: #12172f; // level 2
// primary dark
$darkPrimaryLight: #ecedf1;
$darkPrimaryMain: #606d88;
$darkPrimaryDark: #586580;
$darkPrimary200: #b0b6c4;
$darkPrimary800: #44506b;
// secondary dark
$darkSecondaryLight: #fde8ef;
$darkSecondaryMain: #ec407a;
$darkSecondaryDark: #ea3a72;
$darkSecondary200: #f6a0bd;
$darkSecondary800: #e42a5d;
// text variants
$darkTextTitle: #e4e8f7;
$darkTextPrimary: #d5d9e9;
$darkTextSecondary: #d8ddf0;
// ==============================|| JAVASCRIPT ||============================== //
:export {
// paper & background
paper: $paper;
// primary
primaryLight: $primaryLight;
primary200: $primary200;
primaryMain: $primaryMain;
primaryDark: $primaryDark;
primary800: $primary800;
// secondary
secondaryLight: $secondaryLight;
secondary200: $secondary200;
secondaryMain: $secondaryMain;
secondaryDark: $secondaryDark;
secondary800: $secondary800;
// success
successLight: $successLight;
success200: $success200;
successMain: $successMain;
successDark: $successDark;
// error
errorLight: $errorLight;
errorMain: $errorMain;
errorDark: $errorDark;
// orange
orangeLight: $orangeLight;
orangeMain: $orangeMain;
orangeDark: $orangeDark;
// warning
warningLight: $warningLight;
warningMain: $warningMain;
warningDark: $warningDark;
// grey
grey50: $grey50;
grey100: $grey100;
grey200: $grey200;
grey300: $grey300;
grey500: $grey500;
grey600: $grey600;
grey700: $grey700;
grey900: $grey900;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
darkPaper: $darkPaper;
darkBackground: $darkBackground;
// dark 800 & 900
darkLevel1: $darkLevel1;
darkLevel2: $darkLevel2;
// text variants
darkTextTitle: $darkTextTitle;
darkTextPrimary: $darkTextPrimary;
darkTextSecondary: $darkTextSecondary;
// primary dark
darkPrimaryLight: $darkPrimaryLight;
darkPrimaryMain: $darkPrimaryMain;
darkPrimaryDark: $darkPrimaryDark;
darkPrimary200: $darkPrimary200;
darkPrimary800: $darkPrimary800;
// secondary dark
darkSecondaryLight: $darkSecondaryLight;
darkSecondaryMain: $darkSecondaryMain;
darkSecondaryDark: $darkSecondaryDark;
darkSecondary200: $darkSecondary200;
darkSecondary800: $darkSecondary800;
}

@ -0,0 +1,157 @@
// paper & background
$paper: #ffffff;
// primary
$primaryLight: #e3ebeb;
$primaryMain: #16595a;
$primaryDark: #135152;
$primary200: #8bacad;
$primary800: #0c3e3f;
// secondary
$secondaryLight: #f8f0e5;
$secondaryMain: #c77e23;
$secondaryDark: #c1761f;
$secondary200: #e3bf91;
$secondary800: #b36115;
// success Colors
$successLight: #b9f6ca;
$success200: #69f0ae;
$successMain: #00e676;
$successDark: #00c853;
// error
$errorLight: #ef9a9a;
$errorMain: #f44336;
$errorDark: #c62828;
// orange
$orangeLight: #fbe9e7;
$orangeMain: #ffab91;
$orangeDark: #d84315;
// warning
$warningLight: #fff8e1;
$warningMain: #ffe57f;
$warningDark: #ffc107;
// grey
$grey50: #fafafa;
$grey100: #f5f5f5;
$grey200: #eeeeee;
$grey300: #e0e0e0;
$grey500: #9e9e9e;
$grey600: #757575;
$grey700: #616161;
$grey900: #212121;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
$darkBackground: #010606; // level 3
$darkPaper: #010f17; // level 4
// dark 800 & 900
$darkLevel1: #02131d; // level 1
$darkLevel2: #010f17; // level 2
// primary dark
$darkPrimaryLight: #eceff1;
$darkPrimaryMain: #1f7778;
$darkPrimaryDark: #1b6f70;
$darkPrimary200: #8fbbbc;
$darkPrimary800: #125a5b;
// secondary dark
$darkSecondaryLight: #f8f0e5;
$darkSecondaryMain: #c77e23;
$darkSecondaryDark: #c1761f;
$darkSecondary200: #e3bf91;
$darkSecondary800: #b36115;
// text variants
$darkTextTitle: #ffffff;
$darkTextPrimary: #ffffff;
$darkTextSecondary: #8492c4;
// ==============================|| JAVASCRIPT ||============================== //
:export {
// paper & background
paper: $paper;
// primary
primaryLight: $primaryLight;
primary200: $primary200;
primaryMain: $primaryMain;
primaryDark: $primaryDark;
primary800: $primary800;
// secondary
secondaryLight: $secondaryLight;
secondary200: $secondary200;
secondaryMain: $secondaryMain;
secondaryDark: $secondaryDark;
secondary800: $secondary800;
// success
successLight: $successLight;
success200: $success200;
successMain: $successMain;
successDark: $successDark;
// error
errorLight: $errorLight;
errorMain: $errorMain;
errorDark: $errorDark;
// orange
orangeLight: $orangeLight;
orangeMain: $orangeMain;
orangeDark: $orangeDark;
// warning
warningLight: $warningLight;
warningMain: $warningMain;
warningDark: $warningDark;
// grey
grey50: $grey50;
grey100: $grey100;
grey200: $grey200;
grey300: $grey300;
grey500: $grey500;
grey600: $grey600;
grey700: $grey700;
grey900: $grey900;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
darkPaper: $darkPaper;
darkBackground: $darkBackground;
// dark 800 & 900
darkLevel1: $darkLevel1;
darkLevel2: $darkLevel2;
// text variants
darkTextTitle: $darkTextTitle;
darkTextPrimary: $darkTextPrimary;
darkTextSecondary: $darkTextSecondary;
// primary dark
darkPrimaryLight: $darkPrimaryLight;
darkPrimaryMain: $darkPrimaryMain;
darkPrimaryDark: $darkPrimaryDark;
darkPrimary200: $darkPrimary200;
darkPrimary800: $darkPrimary800;
// secondary dark
darkSecondaryLight: $darkSecondaryLight;
darkSecondaryMain: $darkSecondaryMain;
darkSecondaryDark: $darkSecondaryDark;
darkSecondary200: $darkSecondary200;
darkSecondary800: $darkSecondary800;
}

@ -0,0 +1,157 @@
// paper & background
$paper: #ffffff;
// primary
$primaryLight: #e3e8e8;
$primaryMain: #173e43;
$primaryDark: #14383d;
$primary200: #8b9fa1;
$primary800: #0d282c;
// secondary
$secondaryLight: #e8f6f5;
$secondaryMain: #3fb0ac;
$secondaryDark: #39a9a5;
$secondary200: #9fd8d6;
$secondary800: #299792;
// success Colors
$successLight: #b9f6ca;
$success200: #69f0ae;
$successMain: #00e676;
$successDark: #00c853;
// error
$errorLight: #ef9a9a;
$errorMain: #f44336;
$errorDark: #c62828;
// orange
$orangeLight: #fbe9e7;
$orangeMain: #ffab91;
$orangeDark: #d84315;
// warning
$warningLight: #fff8e1;
$warningMain: #ffe57f;
$warningDark: #ffc107;
// grey
$grey50: #fafafa;
$grey100: #f5f5f5;
$grey200: #eeeeee;
$grey300: #e0e0e0;
$grey500: #9e9e9e;
$grey600: #757575;
$grey700: #616161;
$grey900: #212121;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
$darkBackground: #030708; // level 3
$darkPaper: #051114; // level 4
// dark 800 & 900
$darkLevel1: #02131d; // level 1
$darkLevel2: #051114; // level 2
// primary dark
$darkPrimaryLight: #e3e8e8;
$darkPrimaryMain: #3a5b5f;
$darkPrimaryDark: #14383d;
$darkPrimary200: #8b9fa1;
$darkPrimary800: #0d282c;
// secondary dark
$darkSecondaryLight: #e8f6f5;
$darkSecondaryMain: #3fb0ac;
$darkSecondaryDark: #39a9a5;
$darkSecondary200: #9fd8d6;
$darkSecondary800: #299792;
// text variants
$darkTextTitle: #ffffff;
$darkTextPrimary: #ffffff;
$darkTextSecondary: #ccd2eb;
// ==============================|| JAVASCRIPT ||============================== //
:export {
// paper & background
paper: $paper;
// primary
primaryLight: $primaryLight;
primary200: $primary200;
primaryMain: $primaryMain;
primaryDark: $primaryDark;
primary800: $primary800;
// secondary
secondaryLight: $secondaryLight;
secondary200: $secondary200;
secondaryMain: $secondaryMain;
secondaryDark: $secondaryDark;
secondary800: $secondary800;
// success
successLight: $successLight;
success200: $success200;
successMain: $successMain;
successDark: $successDark;
// error
errorLight: $errorLight;
errorMain: $errorMain;
errorDark: $errorDark;
// orange
orangeLight: $orangeLight;
orangeMain: $orangeMain;
orangeDark: $orangeDark;
// warning
warningLight: $warningLight;
warningMain: $warningMain;
warningDark: $warningDark;
// grey
grey50: $grey50;
grey100: $grey100;
grey200: $grey200;
grey300: $grey300;
grey500: $grey500;
grey600: $grey600;
grey700: $grey700;
grey900: $grey900;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
darkPaper: $darkPaper;
darkBackground: $darkBackground;
// dark 800 & 900
darkLevel1: $darkLevel1;
darkLevel2: $darkLevel2;
// text variants
darkTextTitle: $darkTextTitle;
darkTextPrimary: $darkTextPrimary;
darkTextSecondary: $darkTextSecondary;
// primary dark
darkPrimaryLight: $darkPrimaryLight;
darkPrimaryMain: $darkPrimaryMain;
darkPrimaryDark: $darkPrimaryDark;
darkPrimary200: $darkPrimary200;
darkPrimary800: $darkPrimary800;
// secondary dark
darkSecondaryLight: $darkSecondaryLight;
darkSecondaryMain: $darkSecondaryMain;
darkSecondaryDark: $darkSecondaryDark;
darkSecondary200: $darkSecondary200;
darkSecondary800: $darkSecondary800;
}

@ -0,0 +1,157 @@
// paper & background
$paper: #ffffff;
// primary
$primaryLight: #e2e5e8;
$primaryMain: #0a2342;
$primaryDark: #091f3c;
$primary200: #8591a1;
$primary800: #05152b;
// secondary
$secondaryLight: #e6f4f1;
$secondaryMain: #2ca58d;
$secondaryDark: #279d85;
$secondary200: #96d2c6;
$secondary800: #1b8a70;
// success Colors
$successLight: #b9f6ca;
$success200: #69f0ae;
$successMain: #00e676;
$successDark: #00c853;
// error
$errorLight: #ef9a9a;
$errorMain: #f44336;
$errorDark: #c62828;
// orange
$orangeLight: #fbe9e7;
$orangeMain: #ffab91;
$orangeDark: #d84315;
// warning
$warningLight: #fff8e1;
$warningMain: #ffe57f;
$warningDark: #ffc107;
// grey
$grey50: #fafafa;
$grey100: #f5f5f5;
$grey200: #eeeeee;
$grey300: #e0e0e0;
$grey500: #9e9e9e;
$grey600: #757575;
$grey700: #616161;
$grey900: #212121;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
$darkBackground: #051327; // level 3
$darkPaper: #030c1d; // level 4
// dark 800 & 900
$darkLevel1: #071a33; // level 1
$darkLevel2: #091f3c; // level 2
// primary dark
$darkPrimaryLight: #e2e5e8;
$darkPrimaryMain: #54657b;
$darkPrimaryDark: #2f445e;
$darkPrimary200: #8591a1;
$darkPrimary800: #05152b;
// secondary dark
$darkSecondaryLight: #e6f4f1;
$darkSecondaryMain: #2ca58d;
$darkSecondaryDark: #279d85;
$darkSecondary200: #96d2c6;
$darkSecondary800: #1b8a70;
// text variants
$darkTextTitle: #d7dcec;
$darkTextPrimary: #bdc8f0;
$darkTextSecondary: #8492c4;
// ==============================|| JAVASCRIPT ||============================== //
:export {
// paper & background
paper: $paper;
// primary
primaryLight: $primaryLight;
primary200: $primary200;
primaryMain: $primaryMain;
primaryDark: $primaryDark;
primary800: $primary800;
// secondary
secondaryLight: $secondaryLight;
secondary200: $secondary200;
secondaryMain: $secondaryMain;
secondaryDark: $secondaryDark;
secondary800: $secondary800;
// success
successLight: $successLight;
success200: $success200;
successMain: $successMain;
successDark: $successDark;
// error
errorLight: $errorLight;
errorMain: $errorMain;
errorDark: $errorDark;
// orange
orangeLight: $orangeLight;
orangeMain: $orangeMain;
orangeDark: $orangeDark;
// warning
warningLight: $warningLight;
warningMain: $warningMain;
warningDark: $warningDark;
// grey
grey50: $grey50;
grey100: $grey100;
grey200: $grey200;
grey300: $grey300;
grey500: $grey500;
grey600: $grey600;
grey700: $grey700;
grey900: $grey900;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
darkPaper: $darkPaper;
darkBackground: $darkBackground;
// dark 800 & 900
darkLevel1: $darkLevel1;
darkLevel2: $darkLevel2;
// text variants
darkTextTitle: $darkTextTitle;
darkTextPrimary: $darkTextPrimary;
darkTextSecondary: $darkTextSecondary;
// primary dark
darkPrimaryLight: $darkPrimaryLight;
darkPrimaryMain: $darkPrimaryMain;
darkPrimaryDark: $darkPrimaryDark;
darkPrimary200: $darkPrimary200;
darkPrimary800: $darkPrimary800;
// secondary dark
darkSecondaryLight: $darkSecondaryLight;
darkSecondaryMain: $darkSecondaryMain;
darkSecondaryDark: $darkSecondaryDark;
darkSecondary200: $darkSecondary200;
darkSecondary800: $darkSecondary800;
}

@ -0,0 +1,157 @@
// paper & background
$paper: #ffffff;
// primary
$primaryLight: #e8eaf6;
$primaryMain: #3f51b5;
$primaryDark: #3949ab;
$primary200: #9fa8da;
$primary800: #283593;
// secondary
$secondaryLight: #e8eaf6;
$secondaryMain: #3f51b5;
$secondaryDark: #3949ab;
$secondary200: #9fa8da;
$secondary800: #283593;
// success Colors
$successLight: #b9f6ca;
$success200: #69f0ae;
$successMain: #00e676;
$successDark: #00c853;
// error
$errorLight: #ef9a9a;
$errorMain: #f44336;
$errorDark: #c62828;
// orange
$orangeLight: #fbe9e7;
$orangeMain: #ffab91;
$orangeDark: #d84315;
// warning
$warningLight: #fff8e1;
$warningMain: #ffe57f;
$warningDark: #ffc107;
// grey
$grey50: #fafafa;
$grey100: #f5f5f5;
$grey200: #eeeeee;
$grey300: #e0e0e0;
$grey500: #9e9e9e;
$grey600: #757575;
$grey700: #616161;
$grey900: #212121;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
$darkBackground: #1a223f; // level 3
$darkPaper: #111936; // level 4
// dark 800 & 900
$darkLevel1: #29314f; // level 1
$darkLevel2: #212946; // level 2
// primary dark
$darkPrimaryLight: #eeedfd;
$darkPrimaryMain: #7267ef;
$darkPrimaryDark: #6a5fed;
$darkPrimary200: #b9b3f7;
$darkPrimary800: #554ae8;
// secondary dark
$darkSecondaryLight: #eeedfd;
$darkSecondaryMain: #7267ef;
$darkSecondaryDark: #6a5fed;
$darkSecondary200: #b9b3f7;
$darkSecondary800: #554ae8;
// text variants
$darkTextTitle: #d7dcec;
$darkTextPrimary: #bdc8f0;
$darkTextSecondary: #8492c4;
// ==============================|| JAVASCRIPT ||============================== //
:export {
// paper & background
paper: $paper;
// primary
primaryLight: $primaryLight;
primary200: $primary200;
primaryMain: $primaryMain;
primaryDark: $primaryDark;
primary800: $primary800;
// secondary
secondaryLight: $secondaryLight;
secondary200: $secondary200;
secondaryMain: $secondaryMain;
secondaryDark: $secondaryDark;
secondary800: $secondary800;
// success
successLight: $successLight;
success200: $success200;
successMain: $successMain;
successDark: $successDark;
// error
errorLight: $errorLight;
errorMain: $errorMain;
errorDark: $errorDark;
// orange
orangeLight: $orangeLight;
orangeMain: $orangeMain;
orangeDark: $orangeDark;
// warning
warningLight: $warningLight;
warningMain: $warningMain;
warningDark: $warningDark;
// grey
grey50: $grey50;
grey100: $grey100;
grey200: $grey200;
grey300: $grey300;
grey500: $grey500;
grey600: $grey600;
grey700: $grey700;
grey900: $grey900;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
darkPaper: $darkPaper;
darkBackground: $darkBackground;
// dark 800 & 900
darkLevel1: $darkLevel1;
darkLevel2: $darkLevel2;
// text variants
darkTextTitle: $darkTextTitle;
darkTextPrimary: $darkTextPrimary;
darkTextSecondary: $darkTextSecondary;
// primary dark
darkPrimaryLight: $darkPrimaryLight;
darkPrimaryMain: $darkPrimaryMain;
darkPrimaryDark: $darkPrimaryDark;
darkPrimary200: $darkPrimary200;
darkPrimary800: $darkPrimary800;
// secondary dark
darkSecondaryLight: $darkSecondaryLight;
darkSecondaryMain: $darkSecondaryMain;
darkSecondaryDark: $darkSecondaryDark;
darkSecondary200: $darkSecondary200;
darkSecondary800: $darkSecondary800;
}

@ -0,0 +1,157 @@
// paper & background
$paper: #ffffff;
// primary
$primaryLight: #e3f2fd;
$primaryMain: #2196f3;
$primaryDark: #1e88e5;
$primary200: #90caf9;
$primary800: #1565c0;
// secondary
$secondaryLight: #ede7f6;
$secondaryMain: #673ab7;
$secondaryDark: #5e35b1;
$secondary200: #b39ddb;
$secondary800: #4527a0;
// success Colors
$successLight: #b9f6ca;
$success200: #69f0ae;
$successMain: #00e676;
$successDark: #00c853;
// error
$errorLight: #ef9a9a;
$errorMain: #f44336;
$errorDark: #c62828;
// orange
$orangeLight: #fbe9e7;
$orangeMain: #ffab91;
$orangeDark: #d84315;
// warning
$warningLight: #fff8e1;
$warningMain: #ffe57f;
$warningDark: #ffc107;
// grey
$grey50: #fafafa;
$grey100: #f5f5f5;
$grey200: #eeeeee;
$grey300: #e0e0e0;
$grey500: #9e9e9e;
$grey600: #757575;
$grey700: #616161;
$grey900: #212121;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
$darkBackground: #1a223f; // level 3
$darkPaper: #111936; // level 4
// dark 800 & 900
$darkLevel1: #29314f; // level 1
$darkLevel2: #212946; // level 2
// primary dark
$darkPrimaryLight: #e3f2fd;
$darkPrimaryMain: #2196f3;
$darkPrimaryDark: #1e88e5;
$darkPrimary200: #90caf9;
$darkPrimary800: #1565c0;
// secondary dark
$darkSecondaryLight: #d1c4e9;
$darkSecondaryMain: #7c4dff;
$darkSecondaryDark: #651fff;
$darkSecondary200: #b39ddb;
$darkSecondary800: #6200ea;
// text variants
$darkTextTitle: #d7dcec;
$darkTextPrimary: #bdc8f0;
$darkTextSecondary: #8492c4;
// ==============================|| JAVASCRIPT ||============================== //
:export {
// paper & background
paper: $paper;
// primary
primaryLight: $primaryLight;
primary200: $primary200;
primaryMain: $primaryMain;
primaryDark: $primaryDark;
primary800: $primary800;
// secondary
secondaryLight: $secondaryLight;
secondary200: $secondary200;
secondaryMain: $secondaryMain;
secondaryDark: $secondaryDark;
secondary800: $secondary800;
// success
successLight: $successLight;
success200: $success200;
successMain: $successMain;
successDark: $successDark;
// error
errorLight: $errorLight;
errorMain: $errorMain;
errorDark: $errorDark;
// orange
orangeLight: $orangeLight;
orangeMain: $orangeMain;
orangeDark: $orangeDark;
// warning
warningLight: $warningLight;
warningMain: $warningMain;
warningDark: $warningDark;
// grey
grey50: $grey50;
grey100: $grey100;
grey200: $grey200;
grey300: $grey300;
grey500: $grey500;
grey600: $grey600;
grey700: $grey700;
grey900: $grey900;
// ==============================|| DARK THEME VARIANTS ||============================== //
// paper & background
darkPaper: $darkPaper;
darkBackground: $darkBackground;
// dark 800 & 900
darkLevel1: $darkLevel1;
darkLevel2: $darkLevel2;
// text variants
darkTextTitle: $darkTextTitle;
darkTextPrimary: $darkTextPrimary;
darkTextSecondary: $darkTextSecondary;
// primary dark
darkPrimaryLight: $darkPrimaryLight;
darkPrimaryMain: $darkPrimaryMain;
darkPrimaryDark: $darkPrimaryDark;
darkPrimary200: $darkPrimary200;
darkPrimary800: $darkPrimary800;
// secondary dark
darkSecondaryLight: $darkSecondaryLight;
darkSecondaryMain: $darkSecondaryMain;
darkSecondaryDark: $darkSecondaryDark;
darkSecondary200: $darkSecondary200;
darkSecondary800: $darkSecondary800;
}

@ -0,0 +1,135 @@
// color variants
@import 'themes-vars.module.scss';
// third-party
@import '~react-perfect-scrollbar/dist/css/styles.css';
@import '~slick-carousel/slick/slick.css';
@import '~slick-carousel/slick/slick-theme.css';
// ==============================|| LIGHT BOX ||============================== //
.slick-arrow:before {
color: $grey500;
}
// ==============================|| LIGHT BOX ||============================== //
.fullscreen .react-images__blanket {
z-index: 1200;
}
// ==============================|| APEXCHART ||============================== //
.apexcharts-legend-series .apexcharts-legend-marker {
margin-right: 8px;
}
// ==============================|| PERFECT SCROLLBAR ||============================== //
.scrollbar-container {
.ps__rail-y {
&:hover > .ps__thumb-y,
&:focus > .ps__thumb-y,
&.ps--clicking .ps__thumb-y {
background-color: $grey500;
width: 5px;
}
}
.ps__thumb-y {
background-color: $grey500;
border-radius: 6px;
width: 5px;
right: 0;
}
}
.scrollbar-container.ps,
.scrollbar-container > .ps {
&.ps--active-y > .ps__rail-y {
width: 5px;
background-color: transparent !important;
z-index: 999;
&:hover,
&.ps--clicking {
width: 5px;
background-color: transparent;
}
}
&.ps--scrolling-y > .ps__rail-y,
&.ps--scrolling-x > .ps__rail-x {
opacity: 0.4;
background-color: transparent;
}
}
// ==============================|| ANIMATION KEYFRAMES ||============================== //
@keyframes wings {
50% {
transform: translateY(-40px);
}
100% {
transform: translateY(0px);
}
}
@keyframes blink {
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes bounce {
0%,
20%,
53%,
to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
transform: translateZ(0);
}
40%,
43% {
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transform: translate3d(0, -5px, 0);
}
70% {
animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transform: translate3d(0, -7px, 0);
}
80% {
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
transform: translateZ(0);
}
90% {
transform: translate3d(0, -2px, 0);
}
}
@keyframes slideY {
0%,
50%,
100% {
transform: translateY(0px);
}
25% {
transform: translateY(-10px);
}
75% {
transform: translateY(10px);
}
}
@keyframes slideX {
0%,
50%,
100% {
transform: translateX(0px);
}
25% {
transform: translateX(-10px);
}
75% {
transform: translateX(10px);
}
}

@ -0,0 +1,43 @@
export const JWT_API = {
secret: 'SECRET-KEY',
timeout: '1 days'
};
export const FIREBASE_API = {
apiKey: 'AIzaSyBernKzdSojh_vWXBHt0aRhf5SC9VLChbM',
authDomain: 'berry-material-react.firebaseapp.com',
projectId: 'berry-material-react',
storageBucket: 'berry-material-react.appspot.com',
messagingSenderId: '901111229354',
appId: '1:901111229354:web:a5ae5aa95486297d69d9d3',
measurementId: 'G-MGJHSL8XW3'
};
export const AUTH0_API = {
client_id: '7T4IlWis4DKHSbG8JAye4Ipk0rvXkH9V',
domain: 'dev-w0-vxep3.us.auth0.com'
};
export const AWS_API = {
poolId: 'us-east-1_AOfOTXLvD',
appClientId: '3eau2osduslvb7vks3vsh9t7b0'
};
// basename: only at build time to set, and Don't add '/' at end off BASENAME for breadcrumbs, also Don't put only '/' use blank('') instead,
// like '/berry-material-react/react/default'
export const BASE_PATH = '';
export const DASHBOARD_PATH = '/sample-page';
const config = {
fontFamily: `'Roboto', sans-serif`,
borderRadius: 8,
outlinedFilled: true,
navType: 'light', // light, dark
presetColor: 'default', // default, theme1, theme2, theme3, theme4, theme5, theme6
locale: 'en', // 'en' - English, 'fr' - French, 'ro' - Romanian, 'zh' - Chinese
rtlLayout: false,
container: false
};
export default config;

@ -0,0 +1,153 @@
import PropTypes from 'prop-types';
import React, { createContext, useEffect, useReducer } from 'react';
// third-party
import { CognitoUser, CognitoUserPool, CognitoUserAttribute, AuthenticationDetails } from 'amazon-cognito-identity-js';
// reducer - state management
import { LOGIN, LOGOUT } from 'store/actions';
import accountReducer from 'store/accountReducer';
// project imports
import Loader from 'ui-component/Loader';
import { AWS_API } from 'config';
// constant
const initialState = {
isLoggedIn: false,
isInitialized: false,
user: null
};
export const userPool = new CognitoUserPool({
UserPoolId: AWS_API.poolId || '',
ClientId: AWS_API.appClientId || ''
});
const setSession = (serviceToken? | null) => {
if (serviceToken) {
localStorage.setItem('serviceToken', serviceToken);
} else {
localStorage.removeItem('serviceToken');
}
};
// ==============================|| AWS Cognito CONTEXT & PROVIDER ||============================== //
const AWSCognitoContext = createContext(null);
export const AWSCognitoProvider = ({ children }) => {
const [state, dispatch] = useReducer(accountReducer, initialState);
useEffect(() => {
const init = async () => {
try {
const serviceToken = window.localStorage.getItem('serviceToken');
if (serviceToken) {
setSession(serviceToken);
dispatch({
type: LOGIN,
payload: {
isLoggedIn: true,
user: {
name: 'Betty'
}
}
});
} else {
dispatch({
type: LOGOUT
});
}
} catch (err) {
console.error(err);
dispatch({
type: LOGOUT
});
}
};
init();
}, []);
const login = async (email, password) => {
const usr = new CognitoUser({
Username: email,
Pool: userPool
});
const authData = new AuthenticationDetails({
Username: email,
Password: password
});
usr.authenticateUser(authData, {
onSuccess: (session) => {
setSession(session.getAccessToken().getJwtToken());
dispatch({
type: LOGIN,
payload: {
isLoggedIn: true,
user: {
email: authData.getUsername(),
name: 'John Doe'
}
}
});
},
onFailure: (_err) => {},
newPasswordRequired: (userAttributes, requiredAttributes) => {
// // User was signed up by an admin and must provide new
// // password and required attributes, if any, to complete
// // authentication.
// // the api doesn't accept this field back
// delete userAttributes.email_verified;
// // unsure about this field, but I don't send this back
// delete userAttributes.phone_number_verified;
// // Get these details and call
// usr.completeNewPasswordChallenge(password, userAttributes, requiredAttributes);
}
});
};
const register = (email, password, firstName, lastName) =>
new Promise((success, rej) => {
userPool.signUp(
email,
password,
[
new CognitoUserAttribute({ Name: 'email', Value: email }),
new CognitoUserAttribute({ Name: 'name', Value: `${firstName} ${lastName}` })
],
[],
async (err, result) => {
if (err) {
rej(err);
return;
}
success(result);
}
);
});
const logout = () => {
const loggedInUser = userPool.getCurrentUser();
if (loggedInUser) {
setSession(null);
loggedInUser.signOut();
dispatch({ type: LOGOUT });
}
};
if (state.isInitialized !== undefined && !state.isInitialized) {
return <Loader />;
}
return <AWSCognitoContext.Provider value={{ ...state, login, logout, register }}>{children}</AWSCognitoContext.Provider>;
};
AWSCognitoProvider.propTypes = {
children: PropTypes.node
};
export default AWSCognitoContext;

@ -0,0 +1,115 @@
import PropTypes from 'prop-types';
import { createContext, useEffect, useReducer } from 'react';
// third-party
import { Auth0Client } from '@auth0/auth0-spa-js';
// reducer - state management
import { LOGIN, LOGOUT } from 'store/actions';
import accountReducer from 'store/accountReducer';
// project imports
import Loader from 'ui-component/Loader';
import { AUTH0_API } from 'config';
// constant
let auth0Client;
const initialState = {
isLoggedIn: false,
isInitialized: false,
user: null
};
// ==============================|| AUTH0 CONTEXT & PROVIDER ||============================== //
const Auth0Context = createContext(null);
export const Auth0Provider = ({ children }) => {
const [state, dispatch] = useReducer(accountReducer, initialState);
useEffect(() => {
const init = async () => {
try {
auth0Client = new Auth0Client({
redirect_uri: window.location.origin,
...AUTH0_API
});
await auth0Client.checkSession();
const isLoggedIn = await auth0Client.isAuthenticated();
if (isLoggedIn) {
const user = await auth0Client.getUser();
dispatch({
type: LOGIN,
payload: {
isLoggedIn: true,
user: {
id: user?.sub,
email: user?.email
}
}
});
} else {
dispatch({
type: LOGOUT
});
}
} catch (err) {
dispatch({
type: LOGOUT
});
}
};
init();
}, []);
const login = async (options) => {
await auth0Client.loginWithPopup(options);
const isLoggedIn = await auth0Client.isAuthenticated();
if (isLoggedIn) {
const user = await auth0Client.getUser();
dispatch({
type: LOGIN,
payload: {
isLoggedIn: true,
user: {
id: user?.sub,
avatar: user?.picture,
email: user?.email,
name: user?.name,
tier: 'Premium'
}
}
});
}
};
const logout = () => {
auth0Client.logout();
dispatch({
type: LOGOUT
});
};
const resetPassword = (email) => {};
const updateProfile = () => {};
if (state.isInitialized !== undefined && !state.isInitialized) {
return <Loader />;
}
return <Auth0Context.Provider value={{ ...state, login, logout, resetPassword, updateProfile }}>{children}</Auth0Context.Provider>;
};
Auth0Provider.propTypes = {
children: PropTypes.node
};
export default Auth0Context;

@ -0,0 +1,115 @@
import PropTypes from 'prop-types';
import { createContext } from 'react';
// project import
import defaultConfig from 'config';
import useLocalStorage from 'hooks/useLocalStorage';
// initial state
const initialState = {
...defaultConfig,
onChangeMenuType: () => {},
onChangePresetColor: () => {},
onChangeLocale: () => {},
onChangeRTL: () => {},
onChangeContainer: () => {},
onChangeFontFamily: () => {},
onChangeBorderRadius: () => {},
onChangeOutlinedField: () => {}
};
// ==============================|| CONFIG CONTEXT & PROVIDER ||============================== //
const ConfigContext = createContext(initialState);
function ConfigProvider({ children }) {
const [config, setConfig] = useLocalStorage('berry-config', {
fontFamily: initialState.fontFamily,
borderRadius: initialState.borderRadius,
outlinedFilled: initialState.outlinedFilled,
navType: initialState.navType,
presetColor: initialState.presetColor,
locale: initialState.locale,
rtlLayout: initialState.rtlLayout
});
const onChangeMenuType = (navType) => {
setConfig({
...config,
navType
});
};
const onChangePresetColor = (presetColor) => {
setConfig({
...config,
presetColor
});
};
const onChangeLocale = (locale) => {
setConfig({
...config,
locale
});
};
const onChangeRTL = (rtlLayout) => {
setConfig({
...config,
rtlLayout
});
};
const onChangeContainer = () => {
setConfig({
...config,
container: !config.container
});
};
const onChangeFontFamily = (fontFamily) => {
setConfig({
...config,
fontFamily
});
};
const onChangeBorderRadius = (event, newValue) => {
setConfig({
...config,
borderRadius: newValue
});
};
const onChangeOutlinedField = (outlinedFilled) => {
setConfig({
...config,
outlinedFilled
});
};
return (
<ConfigContext.Provider
value={{
...config,
onChangeMenuType,
onChangePresetColor,
onChangeLocale,
onChangeRTL,
onChangeContainer,
onChangeFontFamily,
onChangeBorderRadius,
onChangeOutlinedField
}}
>
{children}
</ConfigContext.Provider>
);
}
ConfigProvider.propTypes = {
children: PropTypes.node
};
export { ConfigProvider, ConfigContext };

@ -0,0 +1,103 @@
import PropTypes from 'prop-types';
import { createContext, useEffect, useReducer } from 'react';
// third-party
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
// action - state management
import { LOGIN, LOGOUT } from 'store/actions';
import accountReducer from 'store/accountReducer';
// project imports
import Loader from 'ui-component/Loader';
import { FIREBASE_API } from 'config';
// firebase initialize
if (!firebase.apps.length) {
firebase.initializeApp(FIREBASE_API);
}
// const
const initialState = {
isLoggedIn: false,
isInitialized: false,
user: null
};
// ==============================|| FIREBASE CONTEXT & PROVIDER ||============================== //
const FirebaseContext = createContext(null);
export const FirebaseProvider = ({ children }) => {
const [state, dispatch] = useReducer(accountReducer, initialState);
useEffect(
() =>
firebase.auth().onAuthStateChanged((user) => {
if (user) {
dispatch({
type: LOGIN,
payload: {
isLoggedIn: true,
user: {
id: user.uid,
email: user.email,
name: user.displayName || 'John Doe'
}
}
});
} else {
dispatch({
type: LOGOUT
});
}
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[dispatch]
);
const firebaseEmailPasswordSignIn = (email, password) => firebase.auth().signInWithEmailAndPassword(email, password);
const firebaseGoogleSignIn = () => {
const provider = new firebase.auth.GoogleAuthProvider();
return firebase.auth().signInWithPopup(provider);
};
const firebaseRegister = async (email, password) => firebase.auth().createUserWithEmailAndPassword(email, password);
const logout = () => firebase.auth().signOut();
const resetPassword = async (email) => {
await firebase.auth().sendPasswordResetEmail(email);
};
const updateProfile = () => {};
if (state.isInitialized !== undefined && !state.isInitialized) {
return <Loader />;
}
return (
<FirebaseContext.Provider
value={{
...state,
firebaseRegister,
firebaseEmailPasswordSignIn,
login: () => {},
firebaseGoogleSignIn,
logout,
resetPassword,
updateProfile
}}
>
{children}
</FirebaseContext.Provider>
);
};
FirebaseProvider.propTypes = {
children: PropTypes.node
};
export default FirebaseContext;

@ -0,0 +1,144 @@
import PropTypes from 'prop-types';
import { createContext, useEffect, useReducer } from 'react';
// third-party
import { Chance } from 'chance';
import jwtDecode from 'jwt-decode';
// reducer - state management
import { LOGIN, LOGOUT } from 'store/actions';
import accountReducer from 'store/accountReducer';
// project imports
import Loader from 'ui-component/Loader';
import axios from 'utils/axios';
const chance = new Chance();
// constant
const initialState = {
isLoggedIn: false,
isInitialized: false,
user: null
};
const verifyToken = (serviceToken) => {
if (!serviceToken) {
return false;
}
const decoded = jwtDecode(serviceToken);
/**
* Property 'exp' does not exist on type '<T = unknown>(token, options?: JwtDecodeOptions | undefined) => T'.
*/
return decoded.exp > Date.now() / 1000;
};
const setSession = (serviceToken) => {
if (serviceToken) {
localStorage.setItem('serviceToken', serviceToken);
axios.defaults.headers.common.Authorization = `Bearer ${serviceToken}`;
} else {
localStorage.removeItem('serviceToken');
delete axios.defaults.headers.common.Authorization;
}
};
// ==============================|| JWT CONTEXT & PROVIDER ||============================== //
const JWTContext = createContext(null);
export const JWTProvider = ({ children }) => {
const [state, dispatch] = useReducer(accountReducer, initialState);
useEffect(() => {
const init = async () => {
try {
const serviceToken = window.localStorage.getItem('serviceToken');
if (serviceToken && verifyToken(serviceToken)) {
setSession(serviceToken);
const response = await axios.get('/api/account/me');
const { user } = response.data;
dispatch({
type: LOGIN,
payload: {
isLoggedIn: true,
user
}
});
} else {
dispatch({
type: LOGOUT
});
}
} catch (err) {
console.error(err);
dispatch({
type: LOGOUT
});
}
};
init();
}, []);
const login = async (email, password) => {
const response = await axios.post('/api/account/login', { email, password });
const { serviceToken, user } = response.data;
setSession(serviceToken);
dispatch({
type: LOGIN,
payload: {
isLoggedIn: true,
user
}
});
};
const register = async (email, password, firstName, lastName) => {
// todo: this flow need to be recode as it not verified
const id = chance.bb_pin();
const response = await axios.post('/api/account/register', {
id,
email,
password,
firstName,
lastName
});
let users = response.data;
if (window.localStorage.getItem('users') !== undefined && window.localStorage.getItem('users') !== null) {
const localUsers = window.localStorage.getItem('users');
users = [
...JSON.parse(localUsers),
{
id,
email,
password,
name: `${firstName} ${lastName}`
}
];
}
window.localStorage.setItem('users', JSON.stringify(users));
};
const logout = () => {
setSession(null);
dispatch({ type: LOGOUT });
};
const resetPassword = (email) => console.log(email);
const updateProfile = () => {};
if (state.isInitialized !== undefined && !state.isInitialized) {
return <Loader />;
}
return <JWTContext.Provider value={{ ...state, login, logout, register, resetPassword, updateProfile }}>{children}</JWTContext.Provider>;
};
JWTProvider.propTypes = {
children: PropTypes.node
};
export default JWTContext;

@ -0,0 +1,19 @@
import { useContext } from 'react';
// auth provider
import AuthContext from 'contexts/FirebaseContext';
// import AuthContext from 'contexts/Auth0Context';
// import AuthContext from 'contexts/JWTContext';
// import AuthContext from 'contexts/AWSCognitoContext';
// ==============================|| AUTH HOOKS ||============================== //
const useAuth = () => {
const context = useContext(AuthContext);
if (!context) throw new Error('context must be use inside provider');
return context;
};
export default useAuth;

@ -0,0 +1,8 @@
import { useContext } from 'react';
import { ConfigContext } from 'contexts/ConfigContext';
// ==============================|| CONFIG - HOOKS ||============================== //
const useConfig = () => useContext(ConfigContext);
export default useConfig;

@ -0,0 +1,33 @@
import { useState, useEffect } from 'react';
// ==============================|| CONFIG - LOCAL STORAGE ||============================== //
export default function useLocalStorage(key, defaultValue) {
const [value, setValue] = useState(() => {
const storedValue = localStorage.getItem(key);
return storedValue === null ? defaultValue : JSON.parse(storedValue);
});
useEffect(() => {
const listener = (e) => {
if (e.storageArea === localStorage && e.key === key) {
setValue(e.newValue ? JSON.parse(e.newValue) : e.newValue);
}
};
window.addEventListener('storage', listener);
return () => {
window.removeEventListener('storage', listener);
};
}, [key, defaultValue]);
const setValueInLocalStorage = (newValue) => {
setValue((currentValue) => {
const result = typeof newValue === 'function' ? newValue(currentValue) : newValue;
localStorage.setItem(key, JSON.stringify(result));
return result;
});
};
return [value, setValueInLocalStorage];
}

@ -0,0 +1,18 @@
import { useEffect, useRef } from 'react';
// ==============================|| ELEMENT REFERENCE HOOKS ||============================== //
const useScriptRef = () => {
const scripted = useRef(true);
useEffect(
() => () => {
scripted.current = false;
},
[]
);
return scripted;
};
export default useScriptRef;

@ -0,0 +1,42 @@
import ReactDOM from 'react-dom';
// third party
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
// project imports
import App from 'App';
import { BASE_PATH } from 'config';
import { store, persister } from 'store';
import * as serviceWorker from 'serviceWorker';
import reportWebVitals from 'reportWebVitals';
import { ConfigProvider } from 'contexts/ConfigContext';
// style + assets
import 'assets/scss/style.scss';
// ==============================|| REACT DOM RENDER ||============================== //
ReactDOM.render(
<Provider store={store}>
<PersistGate loading={null} persistor={persister}>
<ConfigProvider>
<BrowserRouter basename={BASE_PATH}>
<App />
</BrowserRouter>
</ConfigProvider>
</PersistGate>
</Provider>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

@ -0,0 +1,56 @@
// material-ui
import { useTheme } from '@mui/material/styles';
import { Grid, Slider, Typography } from '@mui/material';
// project imports
import useConfig from 'hooks/useConfig';
import SubCard from 'ui-component/cards/SubCard';
// concat 'px'
function valueText(value) {
return `${value}px`;
}
const BorderRadius = () => {
const theme = useTheme();
const { borderRadius, onChangeBorderRadius } = useConfig();
return (
<SubCard title="Border Radius">
<Grid item xs={12} container spacing={2} alignItems="center" sx={{ mt: 2.5 }}>
<Grid item>
<Typography variant="h6" color="secondary">
4px
</Typography>
</Grid>
<Grid item xs>
<Slider
size="small"
value={borderRadius}
onChange={onChangeBorderRadius}
getAriaValueText={valueText}
valueLabelDisplay="on"
aria-labelledby="discrete-slider-small-steps"
marks
step={2}
min={4}
max={24}
color="secondary"
sx={{
'& .MuiSlider-valueLabel': {
color: theme.palette.mode === 'dark' ? 'secondary.dark' : 'secondary.light'
}
}}
/>
</Grid>
<Grid item>
<Typography variant="h6" color="secondary">
24px
</Typography>
</Grid>
</Grid>
</SubCard>
);
};
export default BorderRadius;

@ -0,0 +1,25 @@
// material-ui
import { FormControl, FormControlLabel, Switch } from '@mui/material';
// project imports
import useConfig from 'hooks/useConfig';
import SubCard from 'ui-component/cards/SubCard';
const BoxContainer = () => {
const { container, onChangeContainer } = useConfig();
return (
<SubCard title="Box Container">
<FormControl component="fieldset" sx={{ mt: 2 }}>
<FormControlLabel
control={
<Switch checked={container} onChange={() => onChangeContainer()} inputProps={{ 'aria-label': 'controlled-direction' }} />
}
label="Container"
/>
</FormControl>
</SubCard>
);
};
export default BoxContainer;

@ -0,0 +1,74 @@
import { useState } from 'react';
// material-ui
import { useTheme } from '@mui/material/styles';
import { FormControl, FormControlLabel, Radio, RadioGroup } from '@mui/material';
// project imports
import useConfig from 'hooks/useConfig';
import SubCard from 'ui-component/cards/SubCard';
const FontFamily = () => {
const theme = useTheme();
const { fontFamily, onChangeFontFamily } = useConfig();
let initialFont;
switch (fontFamily) {
case `'Inter', sans-serif`:
initialFont = 'Inter';
break;
case `'Poppins', sans-serif`:
initialFont = 'Poppins';
break;
case `'Roboto', sans-serif`:
default:
initialFont = 'Roboto';
break;
}
// state - font family
const [font, setFont] = useState(initialFont);
const handleFont = (event) => {
setFont(event.target.value);
onChangeFontFamily(event.target.value);
};
return (
<SubCard title="Font Family">
<FormControl>
<RadioGroup aria-label="font-family" value={font} onChange={handleFont} name="row-radio-buttons-group">
<FormControlLabel
value="Roboto"
control={<Radio />}
label="Roboto"
sx={{
'& .MuiSvgIcon-root': { fontSize: 28 },
'& .MuiFormControlLabel-label': { color: theme.palette.grey[900] }
}}
/>
<FormControlLabel
value="Poppins"
control={<Radio />}
label="Poppins"
sx={{
'& .MuiSvgIcon-root': { fontSize: 28 },
'& .MuiFormControlLabel-label': { color: theme.palette.grey[900] }
}}
/>
<FormControlLabel
value="Inter"
control={<Radio />}
label="Inter"
sx={{
'& .MuiSvgIcon-root': { fontSize: 28 },
'& .MuiFormControlLabel-label': { color: theme.palette.grey[900] }
}}
/>
</RadioGroup>
</FormControl>
</SubCard>
);
};
export default FontFamily;

@ -0,0 +1,29 @@
// material-ui
import { Grid, Stack, Switch, TextField } from '@mui/material';
// project imports
import useConfig from 'hooks/useConfig';
import SubCard from 'ui-component/cards/SubCard';
const InputFilled = () => {
const { outlinedFilled, onChangeOutlinedField } = useConfig();
return (
<SubCard title="Input Outlined With Filled">
<Grid item xs={12} container spacing={2} alignItems="center">
<Grid item>
<Stack spacing={2}>
<Switch
checked={outlinedFilled}
onChange={(event) => onChangeOutlinedField(event.target.checked)}
inputProps={{ 'aria-label': 'controlled' }}
/>
<TextField fullWidth id="outlined-basic" label={outlinedFilled ? 'With Background' : 'Without Background'} />
</Stack>
</Grid>
</Grid>
</SubCard>
);
};
export default InputFilled;

@ -0,0 +1,61 @@
// material-ui
import { useTheme } from '@mui/material/styles';
import { FormControl, FormControlLabel, FormLabel, Radio, RadioGroup, Switch } from '@mui/material';
// project imports
import useConfig from 'hooks/useConfig';
import SubCard from 'ui-component/cards/SubCard';
const Layout = () => {
const theme = useTheme();
const { navType, rtlLayout, onChangeMenuType, onChangeRTL } = useConfig();
return (
<SubCard title="Layout">
<FormControl component="fieldset">
<FormLabel component="legend">Mode</FormLabel>
<RadioGroup
row
aria-label="layout"
value={navType}
onChange={(e) => onChangeMenuType(e.target.value)}
name="row-radio-buttons-group"
>
<FormControlLabel
value="light"
control={<Radio />}
label="Light"
sx={{
'& .MuiSvgIcon-root': { fontSize: 28 },
'& .MuiFormControlLabel-label': { color: theme.palette.grey[900] }
}}
/>
<FormControlLabel
value="dark"
control={<Radio />}
label="Dark"
sx={{
'& .MuiSvgIcon-root': { fontSize: 28 },
'& .MuiFormControlLabel-label': { color: theme.palette.grey[900] }
}}
/>
</RadioGroup>
</FormControl>
<FormControl component="fieldset" sx={{ mt: 2 }}>
<FormLabel component="legend">Direction</FormLabel>
<FormControlLabel
control={
<Switch
checked={rtlLayout}
onChange={(event) => onChangeRTL(event.target.checked)}
inputProps={{ 'aria-label': 'controlled-direction' }}
/>
}
label="RTL"
/>
</FormControl>
</SubCard>
);
};
export default Layout;

@ -0,0 +1,101 @@
import PropTypes from 'prop-types';
// material-ui
import { useTheme } from '@mui/material/styles';
import { Avatar, Grid } from '@mui/material';
import { IconChecks } from '@tabler/icons';
// project imports
import useConfig from 'hooks/useConfig';
import SubCard from 'ui-component/cards/SubCard';
// color import
import colors from 'assets/scss/_themes-vars.module.scss';
import theme1 from 'assets/scss/_theme1.module.scss';
import theme2 from 'assets/scss/_theme2.module.scss';
import theme3 from 'assets/scss/_theme3.module.scss';
import theme4 from 'assets/scss/_theme4.module.scss';
import theme5 from 'assets/scss/_theme5.module.scss';
import theme6 from 'assets/scss/_theme6.module.scss';
const PresetColorBox = ({ color, presetColor, setPresetColor }) => (
<Grid item>
<Avatar
variant="rounded"
color="inherit"
sx={{
background: `linear-gradient(135deg, ${color.primary} 50%, ${color.secondary} 50%)`,
opacity: presetColor === color.id ? 0.6 : 1,
cursor: 'pointer'
}}
onClick={() => setPresetColor(color?.id)}
>
{presetColor === color.id && <IconChecks color="#fff" />}
</Avatar>
</Grid>
);
PresetColorBox.propTypes = {
color: PropTypes.shape({
id: PropTypes.string,
primary: PropTypes.string,
secondary: PropTypes.string
}),
presetColor: PropTypes.string,
setPresetColor: PropTypes.func
};
const PresetColor = () => {
const theme = useTheme();
const { presetColor, onChangePresetColor } = useConfig();
const colorOptions = [
{
id: 'default',
primary: theme.palette.mode === 'dark' ? colors.darkPrimaryMain : colors.primaryMain,
secondary: theme.palette.mode === 'dark' ? colors.darkSecondaryMain : colors.secondaryMain
},
{
id: 'theme1',
primary: theme.palette.mode === 'dark' ? theme1.darkPrimaryMain : theme1.primaryMain,
secondary: theme.palette.mode === 'dark' ? theme1.darkSecondaryMain : theme1.secondaryMain
},
{
id: 'theme2',
primary: theme.palette.mode === 'dark' ? theme2.darkPrimaryMain : theme2.primaryMain,
secondary: theme.palette.mode === 'dark' ? theme2.darkSecondaryMain : theme2.secondaryMain
},
{
id: 'theme3',
primary: theme.palette.mode === 'dark' ? theme3.darkPrimaryMain : theme3.primaryMain,
secondary: theme.palette.mode === 'dark' ? theme3.darkSecondaryMain : theme3.secondaryMain
},
{
id: 'theme4',
primary: theme.palette.mode === 'dark' ? theme4.darkPrimaryMain : theme4.primaryMain,
secondary: theme.palette.mode === 'dark' ? theme4.darkSecondaryMain : theme4.secondaryMain
},
{
id: 'theme5',
primary: theme.palette.mode === 'dark' ? theme5.darkPrimaryMain : theme5.primaryMain,
secondary: theme.palette.mode === 'dark' ? theme5.darkSecondaryMain : theme5.secondaryMain
},
{
id: 'theme6',
primary: theme.palette.mode === 'dark' ? theme6.darkPrimaryMain : theme6.primaryMain,
secondary: theme.palette.mode === 'dark' ? theme6.darkSecondaryMain : theme6.secondaryMain
}
];
return (
<SubCard title="Preset Color">
<Grid item container spacing={2} alignItems="center">
{colorOptions.map((color, index) => (
<PresetColorBox key={index} color={color} presetColor={presetColor} setPresetColor={onChangePresetColor} />
))}
</Grid>
</SubCard>
);
};
export default PresetColor;

@ -0,0 +1,108 @@
import { useState } from 'react';
// material-ui
import { useTheme } from '@mui/material/styles';
import { Drawer, Fab, Grid, IconButton, Tooltip } from '@mui/material';
import { IconSettings } from '@tabler/icons';
// third-party
import PerfectScrollbar from 'react-perfect-scrollbar';
// project imports
import BorderRadius from './BorderRadius';
import Layout from './Layout';
import PresetColor from './PresetColor';
import FontFamily from './FontFamily';
import InputFilled from './InputFilled';
import BoxContainer from './BoxContainer';
import AnimateButton from 'ui-component/extended/AnimateButton';
import { gridSpacing } from 'store/constant';
// ==============================|| LIVE CUSTOMIZATION ||============================== //
const Customization = () => {
const theme = useTheme();
// drawer on/off
const [open, setOpen] = useState(false);
const handleToggle = () => {
setOpen(!open);
};
return (
<>
{/* toggle button */}
<Tooltip title="Live Customize">
<Fab
component="div"
onClick={handleToggle}
size="medium"
variant="circular"
color="secondary"
sx={{
borderRadius: 0,
borderTopLeftRadius: '50%',
borderBottomLeftRadius: '50%',
borderTopRightRadius: '50%',
borderBottomRightRadius: '4px',
top: '25%',
position: 'fixed',
right: 10,
zIndex: theme.zIndex.speedDial,
boxShadow: theme.customShadows.secondary
}}
>
<AnimateButton type="rotate">
<IconButton color="inherit" size="large" disableRipple>
<IconSettings />
</IconButton>
</AnimateButton>
</Fab>
</Tooltip>
<Drawer
anchor="right"
onClose={handleToggle}
open={open}
PaperProps={{
sx: {
width: 280
}
}}
>
{open && (
<PerfectScrollbar component="div">
<Grid container spacing={gridSpacing} sx={{ p: 3 }}>
<Grid item xs={12}>
{/* layout type */}
<Layout />
</Grid>
<Grid item xs={12}>
{/* Theme Preset Color */}
<PresetColor />
</Grid>
<Grid item xs={12}>
{/* font family */}
<FontFamily />
</Grid>
<Grid item xs={12}>
{/* border radius */}
<BorderRadius />
</Grid>
<Grid item xs={12}>
{/* filled with outline textfield */}
<InputFilled />
</Grid>
<Grid item xs={12}>
{/* box container */}
<BoxContainer />
</Grid>
</Grid>
</PerfectScrollbar>
)}
</Drawer>
</>
);
};
export default Customization;

@ -0,0 +1,203 @@
import { useEffect, useRef, useState } from 'react';
// material-ui
import { useTheme } from '@mui/material/styles';
import {
Avatar,
Box,
ClickAwayListener,
Grid,
List,
ListItemButton,
ListItemText,
Paper,
Popper,
Typography,
useMediaQuery
} from '@mui/material';
// project imports
import Transitions from 'ui-component/extended/Transitions';
// assets
import TranslateTwoToneIcon from '@mui/icons-material/TranslateTwoTone';
import useConfig from 'hooks/useConfig';
// ==============================|| LOCALIZATION ||============================== //
const LocalizationSection = () => {
const { borderRadius, locale, onChangeLocale } = useConfig();
const theme = useTheme();
const matchesXs = useMediaQuery(theme.breakpoints.down('md'));
const [open, setOpen] = useState(false);
const anchorRef = useRef(null);
const [language, setLanguage] = useState(locale);
const handleListItemClick = (event, lng) => {
setLanguage(lng);
onChangeLocale(lng);
setOpen(false);
};
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
const handleClose = (event) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
};
const prevOpen = useRef(open);
useEffect(() => {
if (prevOpen.current === true && open === false) {
anchorRef.current.focus();
}
prevOpen.current = open;
}, [open]);
useEffect(() => {
setLanguage(locale);
}, [locale]);
return (
<>
<Box
sx={{
ml: 2,
[theme.breakpoints.down('md')]: {
ml: 1
}
}}
>
<Avatar
variant="rounded"
sx={{
...theme.typography.commonAvatar,
...theme.typography.mediumAvatar,
border: '1px solid',
borderColor: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.primary.light,
background: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.primary.light,
color: theme.palette.primary.dark,
transition: 'all .2s ease-in-out',
'&[aria-controls="menu-list-grow"],&:hover': {
borderColor: theme.palette.primary.main,
background: theme.palette.primary.main,
color: theme.palette.primary.light
}
}}
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
color="inherit"
>
{language !== 'en' && (
<Typography variant="h5" sx={{ textTransform: 'uppercase' }} color="inherit">
{language}
</Typography>
)}
{language === 'en' && <TranslateTwoToneIcon sx={{ fontSize: '1.3rem' }} />}
</Avatar>
</Box>
<Popper
placement={matchesXs ? 'bottom-start' : 'bottom'}
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
popperOptions={{
modifiers: [
{
name: 'offset',
options: {
offset: [matchesXs ? 0 : 0, 20]
}
}
]
}}
>
{({ TransitionProps }) => (
<ClickAwayListener onClickAway={handleClose}>
<Transitions position={matchesXs ? 'top-left' : 'top'} in={open} {...TransitionProps}>
<Paper elevation={16}>
{open && (
<List
component="nav"
sx={{
width: '100%',
minWidth: 200,
maxWidth: 280,
bgcolor: theme.palette.background.paper,
borderRadius: `${borderRadius}px`,
[theme.breakpoints.down('md')]: {
maxWidth: 250
}
}}
>
<ListItemButton selected={language === 'en'} onClick={(event) => handleListItemClick(event, 'en')}>
<ListItemText
primary={
<Grid container>
<Typography color="textPrimary">English</Typography>
<Typography variant="caption" color="textSecondary" sx={{ ml: '8px' }}>
(UK)
</Typography>
</Grid>
}
/>
</ListItemButton>
<ListItemButton selected={language === 'fr'} onClick={(event) => handleListItemClick(event, 'fr')}>
<ListItemText
primary={
<Grid container>
<Typography color="textPrimary">français</Typography>
<Typography variant="caption" color="textSecondary" sx={{ ml: '8px' }}>
(French)
</Typography>
</Grid>
}
/>
</ListItemButton>
<ListItemButton selected={language === 'ro'} onClick={(event) => handleListItemClick(event, 'ro')}>
<ListItemText
primary={
<Grid container>
<Typography color="textPrimary">Română</Typography>
<Typography variant="caption" color="textSecondary" sx={{ ml: '8px' }}>
(Romanian)
</Typography>
</Grid>
}
/>
</ListItemButton>
<ListItemButton selected={language === 'zh'} onClick={(event) => handleListItemClick(event, 'zh')}>
<ListItemText
primary={
<Grid container>
<Typography color="textPrimary">中国人</Typography>
<Typography variant="caption" color="textSecondary" sx={{ ml: '8px' }}>
(Chinese)
</Typography>
</Grid>
}
/>
</ListItemButton>
</List>
)}
</Paper>
</Transitions>
</ClickAwayListener>
)}
</Popper>
</>
);
};
export default LocalizationSection;

File diff suppressed because it is too large Load Diff

@ -0,0 +1,279 @@
import { useEffect, useRef, useState } from 'react';
// material-ui
import { styled, useTheme } from '@mui/material/styles';
import {
useMediaQuery,
Avatar,
ClickAwayListener,
Grid,
List,
ListItemButton,
ListItemIcon,
ListSubheader,
ListItemText,
Paper,
Popper,
Typography
} from '@mui/material';
// project imports
import Banner from './Banner';
import MainCard from 'ui-component/cards/MainCard';
import Transitions from 'ui-component/extended/Transitions';
// assets
import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord';
import { IconAccessPoint } from '@tabler/icons';
import { drawerWidth, gridSpacing } from 'store/constant';
const HeaderAvatarStyle = styled(Avatar)(({ theme }) => ({
...theme.typography.commonAvatar,
...theme.typography.mediumAvatar,
background: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.secondary.light,
color: theme.palette.mode === 'dark' ? theme.palette.secondary.main : theme.palette.secondary.dark,
'&:hover': {
background: theme.palette.mode === 'dark' ? theme.palette.secondary.main : theme.palette.secondary.dark,
color: theme.palette.mode === 'dark' ? theme.palette.secondary.light : theme.palette.secondary.light
}
}));
// ==============================|| SEARCH INPUT - MEGA MENu||============================== //
const MegaMenuSection = () => {
const theme = useTheme();
const matchDownMd = useMediaQuery(theme.breakpoints.down('md'));
const [open, setOpen] = useState(false);
const anchorRef = useRef(null);
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
const handleClose = (event) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
};
useEffect(() => {
if (matchDownMd && open) setOpen(false);
// eslint-disable-next-line
}, [matchDownMd]);
return (
<>
<HeaderAvatarStyle
variant="rounded"
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
sx={{ display: { xs: 'none', md: 'flex' } }}
>
<IconAccessPoint stroke={1.5} size="1.3rem" />
</HeaderAvatarStyle>
<Popper
placement="bottom-end"
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
popperOptions={{
modifiers: [
{
name: 'offset',
options: {
offset: [150, 20]
}
}
]
}}
>
{({ TransitionProps }) => (
<ClickAwayListener onClickAway={handleClose}>
<Transitions in={open} {...TransitionProps}>
<Paper
sx={{
width: {
md: `calc(100vw - 100px)`,
lg: `calc(100vw - ${drawerWidth + 100}px)`,
xl: `calc(100vw - ${drawerWidth + 140}px)`
},
maxWidth: { xl: 900, md: 764 }
}}
>
{open && (
<MainCard
border={false}
elevation={16}
content={false}
boxShadow
shadow={theme.shadows[16]}
sx={{ p: 1, overflow: { xs: 'visible', md: 'hidden' } }}
>
<Grid container spacing={gridSpacing}>
<Grid item md={4}>
<Banner />
</Grid>
<Grid item md={8}>
<Grid
container
spacing={gridSpacing}
sx={{
pt: 3,
'& .MuiListItemButton-root:hover': {
background: 'transparent',
'& .MuiTypography-root': {
color: 'secondary.main'
}
},
'& .MuiListItemIcon-root': {
minWidth: 16
}
}}
>
<Grid item xs={4}>
<List
component="nav"
aria-labelledby="nested-list-user"
subheader={
<ListSubheader id="nested-list-user">
<Typography variant="subtitle1"> User Quick</Typography>
</ListSubheader>
}
>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Social Profile" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Account Profile" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="User Cards" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="User List" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Contact" />
</ListItemButton>
</List>
</Grid>
<Grid item xs={4}>
<List
component="nav"
aria-labelledby="nested-list-application"
subheader={
<ListSubheader id="nested-list-application">
<Typography variant="subtitle1"> Applications </Typography>
</ListSubheader>
}
>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Chat" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Kanban" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Mail" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Calendar" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="E-Commerce" />
</ListItemButton>
</List>
</Grid>
<Grid item xs={4}>
<List
component="nav"
aria-labelledby="nested-list-primitives"
subheader={
<ListSubheader component="div" id="nested-list-primitives">
<Typography variant="subtitle1"> Primitives</Typography>
</ListSubheader>
}
>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Colors" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Typography" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Shadows" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Icons" />
</ListItemButton>
<ListItemButton>
<ListItemIcon>
<FiberManualRecordIcon sx={{ fontSize: '0.5rem' }} />
</ListItemIcon>
<ListItemText primary="Elements" />
</ListItemButton>
</List>
</Grid>
</Grid>
</Grid>
</Grid>
</MainCard>
)}
</Paper>
</Transitions>
</ClickAwayListener>
)}
</Popper>
</>
);
};
export default MegaMenuSection;

@ -0,0 +1,111 @@
import { useEffect, useRef, useState } from 'react';
// material-ui
import { useTheme } from '@mui/material/styles';
import { AppBar, Box, IconButton, ClickAwayListener, Grid, Paper, Popper, Toolbar, useMediaQuery } from '@mui/material';
// project imports
import LocalizationSection from '../LocalizationSection';
import Transitions from 'ui-component/extended/Transitions';
// assets
import { IconDotsVertical } from '@tabler/icons';
// ==============================|| MOBILE HEADER ||============================== //
const MobileSection = () => {
const theme = useTheme();
const matchMobile = useMediaQuery(theme.breakpoints.down('md'));
const [open, setOpen] = useState(false);
/**
* anchorRef is used on different componets and specifying one type leads to other components throwing an error
* */
const anchorRef = useRef(null);
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
const handleClose = (event) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
};
const prevOpen = useRef(open);
useEffect(() => {
if (prevOpen.current === true && open === false) {
anchorRef.current.focus();
}
prevOpen.current = open;
}, [open]);
return (
<>
<Box component="span" ref={anchorRef} sx={{ mt: 1, ml: 1 }}>
<IconButton
sx={{ color: theme.palette.mode === 'dark' ? 'primary.main' : 'inherit', ml: 0.5, cursor: 'pointer' }}
onClick={handleToggle}
>
<IconDotsVertical
stroke={1.5}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
style={{ fontSize: '1.5rem' }}
/>
</IconButton>
</Box>
<Popper
placement="bottom-end"
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
style={{ width: '100%', zIndex: 1 }}
popperOptions={{
modifiers: [
{
name: 'offset',
options: {
offset: [0, matchMobile ? 30 : 10]
}
}
]
}}
>
{({ TransitionProps }) => (
<ClickAwayListener onClickAway={handleClose}>
<Transitions type="zoom" in={open} {...TransitionProps} sx={{ transformOrigin: 'top right' }}>
<Paper>
{open && (
<AppBar
color="inherit"
sx={{
[theme.breakpoints.down('md')]: {
background: theme.palette.mode === 'dark' ? theme.palette.dark[800] : '#fff'
}
}}
>
<Toolbar sx={{ pt: 2.75, pb: 2.75 }}>
<Grid container justifyContent={matchMobile ? 'space-between' : 'flex-end'} alignItems="center">
<LocalizationSection />
</Grid>
</Toolbar>
</AppBar>
)}
</Paper>
</Transitions>
</ClickAwayListener>
)}
</Popper>
</>
);
};
export default MobileSection;

@ -0,0 +1,282 @@
// material-ui
import { useTheme, styled } from '@mui/material/styles';
import {
Avatar,
Button,
Card,
CardContent,
Chip,
Divider,
Grid,
List,
ListItem,
ListItemAvatar,
ListItemSecondaryAction,
ListItemText,
Stack,
Typography
} from '@mui/material';
// assets
import { IconBrandTelegram, IconBuildingStore, IconMailbox, IconPhoto } from '@tabler/icons';
import User1 from 'assets/images/users/user-round.svg';
// styles
const ListItemWrapper = styled('div')(({ theme }) => ({
cursor: 'pointer',
padding: 16,
'&:hover': {
background: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.primary.light
},
'& .MuiListItem-root': {
padding: 0
}
}));
// ==============================|| NOTIFICATION LIST ITEM ||============================== //
const NotificationList = () => {
const theme = useTheme();
const chipSX = {
height: 24,
padding: '0 6px'
};
const chipErrorSX = {
...chipSX,
color: theme.palette.orange.dark,
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.orange.light,
marginRight: '5px'
};
const chipWarningSX = {
...chipSX,
color: theme.palette.warning.dark,
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.warning.light
};
const chipSuccessSX = {
...chipSX,
color: theme.palette.success.dark,
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.success.light,
height: 28
};
return (
<List
sx={{
width: '100%',
maxWidth: 330,
py: 0,
borderRadius: '10px',
[theme.breakpoints.down('md')]: {
maxWidth: 300
},
'& .MuiListItemSecondaryAction-root': {
top: 22
},
'& .MuiDivider-root': {
my: 0
},
'& .list-container': {
pl: 7
}
}}
>
<ListItemWrapper>
<ListItem alignItems="center">
<ListItemAvatar>
<Avatar alt="John Doe" src={User1} />
</ListItemAvatar>
<ListItemText primary="John Doe" />
<ListItemSecondaryAction>
<Grid container justifyContent="flex-end">
<Grid item xs={12}>
<Typography variant="caption" display="block" gutterBottom>
2 min ago
</Typography>
</Grid>
</Grid>
</ListItemSecondaryAction>
</ListItem>
<Grid container direction="column" className="list-container">
<Grid item xs={12} sx={{ pb: 2 }}>
<Typography variant="subtitle2">It is a long established fact that a reader will be distracted</Typography>
</Grid>
<Grid item xs={12}>
<Grid container>
<Grid item>
<Chip label="Unread" sx={chipErrorSX} />
</Grid>
<Grid item>
<Chip label="New" sx={chipWarningSX} />
</Grid>
</Grid>
</Grid>
</Grid>
</ListItemWrapper>
<Divider />
<ListItemWrapper>
<ListItem alignItems="center">
<ListItemAvatar>
<Avatar
sx={{
color: theme.palette.success.dark,
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.success.light,
border: theme.palette.mode === 'dark' ? '1px solid' : 'none',
borderColor: theme.palette.success.main
}}
>
<IconBuildingStore stroke={1.5} size="1.3rem" />
</Avatar>
</ListItemAvatar>
<ListItemText primary={<Typography variant="subtitle1">Store Verification Done</Typography>} />
<ListItemSecondaryAction>
<Grid container justifyContent="flex-end">
<Grid item xs={12}>
<Typography variant="caption" display="block" gutterBottom>
2 min ago
</Typography>
</Grid>
</Grid>
</ListItemSecondaryAction>
</ListItem>
<Grid container direction="column" className="list-container">
<Grid item xs={12} sx={{ pb: 2 }}>
<Typography variant="subtitle2">We have successfully received your request.</Typography>
</Grid>
<Grid item xs={12}>
<Grid container>
<Grid item>
<Chip label="Unread" sx={chipErrorSX} />
</Grid>
</Grid>
</Grid>
</Grid>
</ListItemWrapper>
<Divider />
<ListItemWrapper>
<ListItem alignItems="center">
<ListItemAvatar>
<Avatar
sx={{
color: theme.palette.primary.dark,
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.primary.light,
border: theme.palette.mode === 'dark' ? '1px solid' : 'none',
borderColor: theme.palette.primary.main
}}
>
<IconMailbox stroke={1.5} size="1.3rem" />
</Avatar>
</ListItemAvatar>
<ListItemText primary={<Typography variant="subtitle1">Check Your Mail.</Typography>} />
<ListItemSecondaryAction>
<Grid container justifyContent="flex-end">
<Grid item>
<Typography variant="caption" display="block" gutterBottom>
2 min ago
</Typography>
</Grid>
</Grid>
</ListItemSecondaryAction>
</ListItem>
<Grid container direction="column" className="list-container">
<Grid item xs={12} sx={{ pb: 2 }}>
<Typography variant="subtitle2">All done! Now check your inbox as you&apos;re in for a sweet treat!</Typography>
</Grid>
<Grid item xs={12}>
<Grid container>
<Grid item>
<Button variant="contained" disableElevation endIcon={<IconBrandTelegram stroke={1.5} size="1.3rem" />}>
Mail
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</ListItemWrapper>
<Divider />
<ListItemWrapper>
<ListItem alignItems="center">
<ListItemAvatar>
<Avatar alt="John Doe" src={User1} />
</ListItemAvatar>
<ListItemText primary={<Typography variant="subtitle1">John Doe</Typography>} />
<ListItemSecondaryAction>
<Grid container justifyContent="flex-end">
<Grid item xs={12}>
<Typography variant="caption" display="block" gutterBottom>
2 min ago
</Typography>
</Grid>
</Grid>
</ListItemSecondaryAction>
</ListItem>
<Grid container direction="column" className="list-container">
<Grid item xs={12} sx={{ pb: 2 }}>
<Typography component="span" variant="subtitle2">
Uploaded two file on &nbsp;
<Typography component="span" variant="h6">
21 Jan 2020
</Typography>
</Typography>
</Grid>
<Grid item xs={12}>
<Grid container>
<Grid item xs={12}>
<Card
sx={{
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.secondary.light
}}
>
<CardContent>
<Grid container direction="column">
<Grid item xs={12}>
<Stack direction="row" spacing={2}>
<IconPhoto stroke={1.5} size="1.3rem" />
<Typography variant="subtitle1">demo.jpg</Typography>
</Stack>
</Grid>
</Grid>
</CardContent>
</Card>
</Grid>
</Grid>
</Grid>
</Grid>
</ListItemWrapper>
<Divider />
<ListItemWrapper>
<ListItem alignItems="center">
<ListItemAvatar>
<Avatar alt="John Doe" src={User1} />
</ListItemAvatar>
<ListItemText primary={<Typography variant="subtitle1">John Doe</Typography>} />
<ListItemSecondaryAction>
<Grid container justifyContent="flex-end">
<Grid item xs={12}>
<Typography variant="caption" display="block" gutterBottom>
2 min ago
</Typography>
</Grid>
</Grid>
</ListItemSecondaryAction>
</ListItem>
<Grid container direction="column" className="list-container">
<Grid item xs={12} sx={{ pb: 2 }}>
<Typography variant="subtitle2">It is a long established fact that a reader will be distracted</Typography>
</Grid>
<Grid item xs={12}>
<Grid container>
<Grid item>
<Chip label="Confirmation of Account." sx={chipSuccessSX} />
</Grid>
</Grid>
</Grid>
</Grid>
</ListItemWrapper>
</List>
);
};
export default NotificationList;

@ -0,0 +1,217 @@
import { useEffect, useRef, useState } from 'react';
import { Link } from 'react-router-dom';
// material-ui
import { useTheme } from '@mui/material/styles';
import {
Avatar,
Box,
Button,
CardActions,
Chip,
ClickAwayListener,
Divider,
Grid,
Paper,
Popper,
Stack,
TextField,
Typography,
useMediaQuery
} from '@mui/material';
// third-party
import PerfectScrollbar from 'react-perfect-scrollbar';
// project imports
import MainCard from 'ui-component/cards/MainCard';
import Transitions from 'ui-component/extended/Transitions';
import NotificationList from './NotificationList';
// assets
import { IconBell } from '@tabler/icons';
// notification status options
const status = [
{
value: 'all',
label: 'All Notification'
},
{
value: 'new',
label: 'New'
},
{
value: 'unread',
label: 'Unread'
},
{
value: 'other',
label: 'Other'
}
];
// ==============================|| NOTIFICATION ||============================== //
const NotificationSection = () => {
const theme = useTheme();
const matchesXs = useMediaQuery(theme.breakpoints.down('md'));
const [open, setOpen] = useState(false);
const [value, setValue] = useState('');
/**
* anchorRef is used on different componets and specifying one type leads to other components throwing an error
* */
const anchorRef = useRef(null);
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
const handleClose = (event) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
};
const prevOpen = useRef(open);
useEffect(() => {
if (prevOpen.current === true && open === false) {
anchorRef.current.focus();
}
prevOpen.current = open;
}, [open]);
const handleChange = (event) => setValue(event?.target.value);
return (
<>
<Box
sx={{
ml: 2,
mr: 3,
[theme.breakpoints.down('md')]: {
mr: 2
}
}}
>
<Avatar
variant="rounded"
sx={{
...theme.typography.commonAvatar,
...theme.typography.mediumAvatar,
transition: 'all .2s ease-in-out',
background: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.secondary.light,
color: theme.palette.mode === 'dark' ? theme.palette.warning.dark : theme.palette.secondary.dark,
'&[aria-controls="menu-list-grow"],&:hover': {
background: theme.palette.mode === 'dark' ? theme.palette.warning.dark : theme.palette.secondary.dark,
color: theme.palette.mode === 'dark' ? theme.palette.grey[800] : theme.palette.secondary.light
}
}}
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
color="inherit"
>
<IconBell stroke={1.5} size="1.3rem" />
</Avatar>
</Box>
<Popper
placement={matchesXs ? 'bottom' : 'bottom-end'}
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
popperOptions={{
modifiers: [
{
name: 'offset',
options: {
offset: [matchesXs ? 5 : 0, 20]
}
}
]
}}
>
{({ TransitionProps }) => (
<ClickAwayListener onClickAway={handleClose}>
<Transitions position={matchesXs ? 'top' : 'top-right'} in={open} {...TransitionProps}>
<Paper>
{open && (
<MainCard border={false} elevation={16} content={false} boxShadow shadow={theme.shadows[16]}>
<Grid container direction="column" spacing={2}>
<Grid item xs={12}>
<Grid container alignItems="center" justifyContent="space-between" sx={{ pt: 2, px: 2 }}>
<Grid item>
<Stack direction="row" spacing={2}>
<Typography variant="subtitle1">All Notification</Typography>
<Chip
size="small"
label="01"
sx={{
color: theme.palette.background.default,
bgcolor: theme.palette.warning.dark
}}
/>
</Stack>
</Grid>
<Grid item>
<Typography component={Link} to="#" variant="subtitle2" color="primary">
Mark as all read
</Typography>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<PerfectScrollbar style={{ height: '100%', maxHeight: 'calc(100vh - 205px)', overflowX: 'hidden' }}>
<Grid container direction="column" spacing={2}>
<Grid item xs={12}>
<Box sx={{ px: 2, pt: 0.25 }}>
<TextField
id="outlined-select-currency-native"
select
fullWidth
value={value}
onChange={handleChange}
SelectProps={{
native: true
}}
>
{status.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</TextField>
</Box>
</Grid>
<Grid item xs={12} p={0}>
<Divider sx={{ my: 0 }} />
</Grid>
</Grid>
<NotificationList />
</PerfectScrollbar>
</Grid>
</Grid>
<Divider />
<CardActions sx={{ p: 1.25, justifyContent: 'center' }}>
<Button size="small" disableElevation>
View All
</Button>
</CardActions>
</MainCard>
)}
</Paper>
</Transitions>
</ClickAwayListener>
)}
</Popper>
</>
);
};
export default NotificationSection;

@ -0,0 +1,76 @@
// material-ui
import { styled, useTheme } from '@mui/material/styles';
import { Button, Card, CardContent, Grid, Stack, Typography } from '@mui/material';
// project imports
import AnimateButton from 'ui-component/extended/AnimateButton';
// styles
const CardStyle = styled(Card)(({ theme }) => ({
background: theme.palette.mode === 'dark' ? theme.palette.dark[800] : theme.palette.warning.light,
marginTop: '16px',
marginBottom: '16px',
overflow: 'hidden',
position: 'relative',
'&:after': {
content: '""',
position: 'absolute',
width: '200px',
height: '200px',
border: '19px solid ',
borderColor: theme.palette.mode === 'dark' ? theme.palette.warning.main : theme.palette.warning.main,
borderRadius: '50%',
top: '65px',
right: '-150px'
},
'&:before': {
content: '""',
position: 'absolute',
width: '200px',
height: '200px',
border: '3px solid ',
borderColor: theme.palette.mode === 'dark' ? theme.palette.warning.main : theme.palette.warning.main,
borderRadius: '50%',
top: '145px',
right: '-70px'
}
}));
// ==============================|| PROFILE MENU - UPGRADE PLAN CARD ||============================== //
const UpgradePlanCard = () => {
const theme = useTheme();
return (
<CardStyle>
<CardContent>
<Grid container direction="column" spacing={2}>
<Grid item>
<Typography variant="h4">Upgrade your plan</Typography>
</Grid>
<Grid item>
<Typography
variant="subtitle2"
color={theme.palette.mode === 'dark' ? 'textSecondary' : 'grey.900'}
sx={{ opacity: theme.palette.mode === 'dark' ? 1 : 0.6 }}
>
70% discount for 1 years <br />
subscriptions.
</Typography>
</Grid>
<Grid item>
<Stack direction="row">
<AnimateButton>
<Button variant="contained" color="warning" sx={{ boxShadow: 'none' }}>
Go Premium
</Button>
</AnimateButton>
</Stack>
</Grid>
</Grid>
</CardContent>
</CardStyle>
);
};
export default UpgradePlanCard;

@ -0,0 +1,312 @@
import { useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
// material-ui
import { useTheme } from '@mui/material/styles';
import {
Avatar,
Box,
Card,
CardContent,
Chip,
ClickAwayListener,
Divider,
Grid,
InputAdornment,
List,
ListItemButton,
ListItemIcon,
ListItemText,
OutlinedInput,
Paper,
Popper,
Stack,
Switch,
Typography
} from '@mui/material';
// third-party
import PerfectScrollbar from 'react-perfect-scrollbar';
// project imports
import MainCard from 'ui-component/cards/MainCard';
import Transitions from 'ui-component/extended/Transitions';
import UpgradePlanCard from './UpgradePlanCard';
import useAuth from 'hooks/useAuth';
import User1 from 'assets/images/users/user-round.svg';
// assets
import { IconLogout, IconSearch, IconSettings, IconUser } from '@tabler/icons';
import useConfig from 'hooks/useConfig';
// ==============================|| PROFILE MENU ||============================== //
const ProfileSection = () => {
const theme = useTheme();
const { borderRadius } = useConfig();
const navigate = useNavigate();
const [sdm, setSdm] = useState(true);
const [value, setValue] = useState('');
const [notification, setNotification] = useState(false);
const [selectedIndex, setSelectedIndex] = useState(-1);
const { logout, user } = useAuth();
const [open, setOpen] = useState(false);
/**
* anchorRef is used on different components and specifying one type leads to other components throwing an error
* */
const anchorRef = useRef(null);
const handleLogout = async () => {
try {
await logout();
} catch (err) {
console.error(err);
}
};
const handleClose = (event) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
};
const handleListItemClick = (event, index, route = '') => {
setSelectedIndex(index);
handleClose(event);
if (route && route !== '') {
navigate(route);
}
};
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
const prevOpen = useRef(open);
useEffect(() => {
if (prevOpen.current === true && open === false) {
anchorRef.current.focus();
}
prevOpen.current = open;
}, [open]);
return (
<>
<Chip
sx={{
height: '48px',
alignItems: 'center',
borderRadius: '27px',
transition: 'all .2s ease-in-out',
borderColor: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.primary.light,
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.primary.light,
'&[aria-controls="menu-list-grow"], &:hover': {
borderColor: theme.palette.primary.main,
background: `${theme.palette.primary.main}!important`,
color: theme.palette.primary.light,
'& svg': {
stroke: theme.palette.primary.light
}
},
'& .MuiChip-label': {
lineHeight: 0
}
}}
icon={
<Avatar
src={User1}
sx={{
...theme.typography.mediumAvatar,
margin: '8px 0 8px 8px !important',
cursor: 'pointer'
}}
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
color="inherit"
/>
}
label={<IconSettings stroke={1.5} size="1.5rem" color={theme.palette.primary.main} />}
variant="outlined"
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
color="primary"
/>
<Popper
placement="bottom"
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
popperOptions={{
modifiers: [
{
name: 'offset',
options: {
offset: [0, 14]
}
}
]
}}
>
{({ TransitionProps }) => (
<ClickAwayListener onClickAway={handleClose}>
<Transitions in={open} {...TransitionProps}>
<Paper>
{open && (
<MainCard border={false} elevation={16} content={false} boxShadow shadow={theme.shadows[16]}>
<Box sx={{ p: 2, pb: 0 }}>
<Stack>
<Stack direction="row" spacing={0.5} alignItems="center">
<Typography variant="h4">Good Morning,</Typography>
<Typography component="span" variant="h4" sx={{ fontWeight: 400 }}>
{user?.name}
</Typography>
</Stack>
<Typography variant="subtitle2">Project Admin</Typography>
</Stack>
<OutlinedInput
sx={{ width: '100%', pr: 1, pl: 2, my: 2 }}
id="input-search-profile"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Search profile options"
startAdornment={
<InputAdornment position="start">
<IconSearch stroke={1.5} size="1rem" color={theme.palette.grey[500]} />
</InputAdornment>
}
aria-describedby="search-helper-text"
inputProps={{
'aria-label': 'weight'
}}
/>
<Divider />
</Box>
<PerfectScrollbar style={{ height: '100%', maxHeight: 'calc(100vh - 250px)', overflowX: 'hidden' }}>
<Box sx={{ p: 2, pt: 0 }}>
<UpgradePlanCard />
<Divider />
<Card
sx={{
bgcolor: theme.palette.mode === 'dark' ? theme.palette.dark[800] : theme.palette.primary.light,
my: 2
}}
>
<CardContent>
<Grid container spacing={3} direction="column">
<Grid item>
<Grid item container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="subtitle1">Start DND Mode</Typography>
</Grid>
<Grid item>
<Switch
color="primary"
checked={sdm}
onChange={(e) => setSdm(e.target.checked)}
name="sdm"
size="small"
/>
</Grid>
</Grid>
</Grid>
<Grid item>
<Grid item container alignItems="center" justifyContent="space-between">
<Grid item>
<Typography variant="subtitle1">Allow Notifications</Typography>
</Grid>
<Grid item>
<Switch
checked={notification}
onChange={(e) => setNotification(e.target.checked)}
name="sdm"
size="small"
/>
</Grid>
</Grid>
</Grid>
</Grid>
</CardContent>
</Card>
<Divider />
<List
component="nav"
sx={{
width: '100%',
maxWidth: 350,
minWidth: 300,
backgroundColor: theme.palette.background.paper,
borderRadius: '10px',
[theme.breakpoints.down('md')]: {
minWidth: '100%'
},
'& .MuiListItemButton-root': {
mt: 0.5
}
}}
>
<ListItemButton
sx={{ borderRadius: `${borderRadius}px` }}
selected={selectedIndex === 0}
onClick={(event) => handleListItemClick(event, 0, '/user/account-profile/profile1')}
>
<ListItemIcon>
<IconSettings stroke={1.5} size="1.3rem" />
</ListItemIcon>
<ListItemText primary={<Typography variant="body2">Account Settings</Typography>} />
</ListItemButton>
<ListItemButton
sx={{ borderRadius: `${borderRadius}px` }}
selected={selectedIndex === 1}
onClick={(event) => handleListItemClick(event, 1, '/user/social-profile/posts')}
>
<ListItemIcon>
<IconUser stroke={1.5} size="1.3rem" />
</ListItemIcon>
<ListItemText
primary={
<Grid container spacing={1} justifyContent="space-between">
<Grid item>
<Typography variant="body2">Social Profile</Typography>
</Grid>
<Grid item>
<Chip
label="02"
size="small"
sx={{
bgcolor: theme.palette.mode === 'dark' ? theme.palette.dark.dark : theme.palette.warning.dark,
color: theme.palette.background.default
}}
/>
</Grid>
</Grid>
}
/>
</ListItemButton>
<ListItemButton sx={{ borderRadius: `${borderRadius}px` }} selected={selectedIndex === 4} onClick={handleLogout}>
<ListItemIcon>
<IconLogout stroke={1.5} size="1.3rem" />
</ListItemIcon>
<ListItemText primary={<Typography variant="body2">Logout</Typography>} />
</ListItemButton>
</List>
</Box>
</PerfectScrollbar>
</MainCard>
)}
</Paper>
</Transitions>
</ClickAwayListener>
)}
</Popper>
</>
);
};
export default ProfileSection;

@ -0,0 +1,184 @@
import PropTypes from 'prop-types';
import { useState } from 'react';
// material-ui
import { useTheme, styled } from '@mui/material/styles';
import { Avatar, Box, Card, Grid, InputAdornment, OutlinedInput, Popper } from '@mui/material';
// third-party
import PopupState, { bindPopper, bindToggle } from 'material-ui-popup-state';
// project imports
import Transitions from 'ui-component/extended/Transitions';
// assets
import { IconAdjustmentsHorizontal, IconSearch, IconX } from '@tabler/icons';
import { shouldForwardProp } from '@mui/system';
// styles
const PopperStyle = styled(Popper, { shouldForwardProp })(({ theme }) => ({
zIndex: 1100,
width: '99%',
top: '-55px !important',
padding: '0 12px',
[theme.breakpoints.down('sm')]: {
padding: '0 10px'
}
}));
const OutlineInputStyle = styled(OutlinedInput, { shouldForwardProp })(({ theme }) => ({
width: 434,
marginLeft: 16,
paddingLeft: 16,
paddingRight: 16,
'& input': {
background: 'transparent !important',
paddingLeft: '4px !important'
},
[theme.breakpoints.down('lg')]: {
width: 250
},
[theme.breakpoints.down('md')]: {
width: '100%',
marginLeft: 4,
background: theme.palette.mode === 'dark' ? theme.palette.dark[800] : '#fff'
}
}));
const HeaderAvatarStyle = styled(Avatar, { shouldForwardProp })(({ theme }) => ({
...theme.typography.commonAvatar,
...theme.typography.mediumAvatar,
background: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.secondary.light,
color: theme.palette.mode === 'dark' ? theme.palette.secondary.main : theme.palette.secondary.dark,
'&:hover': {
background: theme.palette.mode === 'dark' ? theme.palette.secondary.main : theme.palette.secondary.dark,
color: theme.palette.mode === 'dark' ? theme.palette.secondary.light : theme.palette.secondary.light
}
}));
// ==============================|| SEARCH INPUT - MOBILE||============================== //
const MobileSearch = ({ value, setValue, popupState }) => {
const theme = useTheme();
return (
<OutlineInputStyle
id="input-search-header"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Search"
startAdornment={
<InputAdornment position="start">
<IconSearch stroke={1.5} size="1rem" color={theme.palette.grey[500]} />
</InputAdornment>
}
endAdornment={
<InputAdornment position="end">
<HeaderAvatarStyle variant="rounded">
<IconAdjustmentsHorizontal stroke={1.5} size="1.3rem" />
</HeaderAvatarStyle>
<Box sx={{ ml: 2 }}>
<Avatar
variant="rounded"
sx={{
...theme.typography.commonAvatar,
...theme.typography.mediumAvatar,
background: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.orange.light,
color: theme.palette.orange.dark,
'&:hover': {
background: theme.palette.orange.dark,
color: theme.palette.orange.light
}
}}
{...bindToggle(popupState)}
>
<IconX stroke={1.5} size="1.3rem" />
</Avatar>
</Box>
</InputAdornment>
}
aria-describedby="search-helper-text"
inputProps={{ 'aria-label': 'weight' }}
/>
);
};
MobileSearch.propTypes = {
value: PropTypes.string,
setValue: PropTypes.func,
popupState: PopupState
};
// ==============================|| SEARCH INPUT ||============================== //
const SearchSection = () => {
const theme = useTheme();
const [value, setValue] = useState('');
return (
<>
<Box sx={{ display: { xs: 'block', md: 'none' } }}>
<PopupState variant="popper" popupId="demo-popup-popper">
{(popupState) => (
<>
<Box sx={{ ml: 2 }}>
<HeaderAvatarStyle variant="rounded" {...bindToggle(popupState)}>
<IconSearch stroke={1.5} size="1.2rem" />
</HeaderAvatarStyle>
</Box>
<PopperStyle {...bindPopper(popupState)} transition>
{({ TransitionProps }) => (
<>
<Transitions type="zoom" {...TransitionProps} sx={{ transformOrigin: 'center left' }}>
<Card
sx={{
background: theme.palette.mode === 'dark' ? theme.palette.dark[900] : '#fff',
[theme.breakpoints.down('sm')]: {
border: 0,
boxShadow: 'none'
}
}}
>
<Box sx={{ p: 2 }}>
<Grid container alignItems="center" justifyContent="space-between">
<Grid item xs>
<MobileSearch value={value} setValue={setValue} popupState={popupState} />
</Grid>
</Grid>
</Box>
</Card>
</Transitions>
</>
)}
</PopperStyle>
</>
)}
</PopupState>
</Box>
<Box sx={{ display: { xs: 'none', md: 'block' } }}>
<OutlineInputStyle
id="input-search-header"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Search"
startAdornment={
<InputAdornment position="start">
<IconSearch stroke={1.5} size="1rem" color={theme.palette.grey[500]} />
</InputAdornment>
}
endAdornment={
<InputAdornment position="end">
<HeaderAvatarStyle variant="rounded">
<IconAdjustmentsHorizontal stroke={1.5} size="1.3rem" />
</HeaderAvatarStyle>
</InputAdornment>
}
aria-describedby="search-helper-text"
inputProps={{ 'aria-label': 'weight' }}
/>
</Box>
</>
);
};
export default SearchSection;

@ -0,0 +1,90 @@
// material-ui
import { useTheme } from '@mui/material/styles';
import { Avatar, Box } from '@mui/material';
// project imports
import LogoSection from '../LogoSection';
import SearchSection from './SearchSection';
import MobileSection from './MobileSection';
import ProfileSection from './ProfileSection';
import LocalizationSection from './LocalizationSection';
import MegaMenuSection from './MegaMenuSection';
import NotificationSection from './NotificationSection';
import { useDispatch, useSelector } from 'store';
import { openDrawer } from 'store/slices/menu';
// assets
import { IconMenu2 } from '@tabler/icons';
// ==============================|| MAIN NAVBAR / HEADER ||============================== //
const Header = () => {
const theme = useTheme();
const dispatch = useDispatch();
const { drawerOpen } = useSelector((state) => state.menu);
return (
<>
{/* logo & toggler button */}
<Box
sx={{
width: 228,
display: 'flex',
[theme.breakpoints.down('md')]: {
width: 'auto'
}
}}
>
<Box component="span" sx={{ display: { xs: 'none', md: 'block' }, flexGrow: 1 }}>
<LogoSection />
</Box>
<Avatar
variant="rounded"
sx={{
...theme.typography.commonAvatar,
...theme.typography.mediumAvatar,
overflow: 'hidden',
transition: 'all .2s ease-in-out',
background: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.secondary.light,
color: theme.palette.mode === 'dark' ? theme.palette.secondary.main : theme.palette.secondary.dark,
'&:hover': {
background: theme.palette.mode === 'dark' ? theme.palette.secondary.main : theme.palette.secondary.dark,
color: theme.palette.mode === 'dark' ? theme.palette.secondary.light : theme.palette.secondary.light
}
}}
onClick={() => dispatch(openDrawer(!drawerOpen))}
color="inherit"
>
<IconMenu2 stroke={1.5} size="1.3rem" />
</Avatar>
</Box>
{/* header search */}
<SearchSection />
<Box sx={{ flexGrow: 1 }} />
<Box sx={{ flexGrow: 1 }} />
{/* mega-menu */}
<Box sx={{ display: { xs: 'none', sm: 'block' } }}>
<MegaMenuSection />
</Box>
{/* live customization & localization */}
<Box sx={{ display: { xs: 'none', sm: 'block' } }}>
<LocalizationSection />
</Box>
{/* notification & profile */}
<NotificationSection />
<ProfileSection />
{/* mobile header */}
<Box sx={{ display: { xs: 'block', sm: 'none' } }}>
<MobileSection />
</Box>
</>
);
};
export default Header;

@ -0,0 +1,18 @@
import { Link as RouterLink } from 'react-router-dom';
// material-ui
import { Link } from '@mui/material';
// project imports
import { DASHBOARD_PATH } from 'config';
import Logo from 'ui-component/Logo';
// ==============================|| MAIN LOGO ||============================== //
const LogoSection = () => (
<Link component={RouterLink} to={DASHBOARD_PATH}>
<Logo />
</Link>
);
export default LogoSection;

@ -0,0 +1,129 @@
import PropTypes from 'prop-types';
import { memo } from 'react';
// material-ui
import { styled, useTheme } from '@mui/material/styles';
import {
Avatar,
Card,
CardContent,
Grid,
LinearProgress,
List,
ListItem,
ListItemAvatar,
ListItemText,
Typography,
linearProgressClasses
} from '@mui/material';
// assets
import TableChartOutlinedIcon from '@mui/icons-material/TableChartOutlined';
// styles
const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({
height: 10,
borderRadius: 30,
[`&.${linearProgressClasses.colorPrimary}`]: {
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.dark.light : '#fff'
},
[`& .${linearProgressClasses.bar}`]: {
borderRadius: 5,
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.primary.dark : theme.palette.primary.main
}
}));
const CardStyle = styled(Card)(({ theme }) => ({
background: theme.palette.mode === 'dark' ? theme.palette.dark.main : theme.palette.primary.light,
marginBottom: '22px',
overflow: 'hidden',
position: 'relative',
'&:after': {
content: '""',
position: 'absolute',
width: '157px',
height: '157px',
background: theme.palette.mode === 'dark' ? theme.palette.dark.dark : theme.palette.primary[200],
borderRadius: '50%',
top: '-105px',
right: '-96px'
}
}));
// ==============================|| PROGRESS BAR WITH LABEL ||============================== //
function LinearProgressWithLabel({ value, ...others }) {
const theme = useTheme();
return (
<Grid container direction="column" spacing={1} sx={{ mt: 1.5 }}>
<Grid item>
<Grid container justifyContent="space-between">
<Grid item>
<Typography variant="h6" sx={{ color: theme.palette.mode === 'dark' ? theme.palette.dark.light : theme.palette.primary[800] }}>
Progress
</Typography>
</Grid>
<Grid item>
<Typography variant="h6" color="inherit">{`${Math.round(value)}%`}</Typography>
</Grid>
</Grid>
</Grid>
<Grid item>
<BorderLinearProgress variant="determinate" value={value} {...others} />
</Grid>
</Grid>
);
}
LinearProgressWithLabel.propTypes = {
value: PropTypes.number
};
// ==============================|| SIDEBAR - MENU CARD ||============================== //
const MenuCard = () => {
const theme = useTheme();
return (
<CardStyle>
<CardContent sx={{ p: 2 }}>
<List sx={{ p: 0, m: 0 }}>
<ListItem alignItems="flex-start" disableGutters sx={{ p: 0 }}>
<ListItemAvatar sx={{ mt: 0 }}>
<Avatar
variant="rounded"
sx={{
...theme.typography.commonAvatar,
...theme.typography.largeAvatar,
color: theme.palette.primary.main,
border: theme.palette.mode === 'dark' ? '1px solid' : 'none',
borderColor: theme.palette.primary.main,
background: theme.palette.mode === 'dark' ? theme.palette.dark.dark : '#fff',
marginRight: '12px'
}}
>
<TableChartOutlinedIcon fontSize="inherit" />
</Avatar>
</ListItemAvatar>
<ListItemText
sx={{ mt: 0 }}
primary={
<Typography
variant="subtitle1"
sx={{ color: theme.palette.mode === 'dark' ? theme.palette.dark.light : theme.palette.primary[800] }}
>
Get Extra Space
</Typography>
}
secondary={<Typography variant="caption"> 28/23 GB</Typography>}
/>
</ListItem>
</List>
<LinearProgressWithLabel value={80} />
</CardContent>
</CardStyle>
);
};
export default memo(MenuCard);

@ -0,0 +1,143 @@
import PropTypes from 'prop-types';
import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
// material-ui
import { useTheme } from '@mui/material/styles';
import { Collapse, List, ListItemButton, ListItemIcon, ListItemText, Typography } from '@mui/material';
import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord';
// project imports
import NavItem from '../NavItem';
import useConfig from 'hooks/useConfig';
// assets
import { IconChevronDown, IconChevronUp } from '@tabler/icons';
// ==============================|| SIDEBAR MENU LIST COLLAPSE ITEMS ||============================== //
const NavCollapse = ({ menu, level }) => {
const theme = useTheme();
const { borderRadius } = useConfig();
const [open, setOpen] = useState(false);
const [selected, setSelected] = useState(null);
const handleClick = () => {
setOpen(!open);
setSelected(!selected ? menu.id : null);
};
const { pathname } = useLocation();
useEffect(() => {
const childrens = menu.children ? menu.children : [];
childrens.forEach((item) => {
if (pathname && pathname.includes('product-details')) {
if (item.url && item.url.includes('product-details')) {
setOpen(true);
}
}
if (item.url === pathname) {
setOpen(true);
}
});
}, [pathname, menu.children]);
// menu collapse & item
const menus = menu.children?.map((item) => {
switch (item.type) {
case 'collapse':
return <NavCollapse key={item.id} menu={item} level={level + 1} />;
case 'item':
return <NavItem key={item.id} item={item} level={level + 1} />;
default:
return (
<Typography key={item.id} variant="h6" color="error" align="center">
Menu Items Error
</Typography>
);
}
});
const Icon = menu.icon;
const menuIcon = menu.icon ? (
<Icon strokeWidth={1.5} size="1.3rem" style={{ marginTop: 'auto', marginBottom: 'auto' }} />
) : (
<FiberManualRecordIcon
sx={{
width: selected === menu.id ? 8 : 6,
height: selected === menu.id ? 8 : 6
}}
fontSize={level > 0 ? 'inherit' : 'medium'}
/>
);
return (
<>
<ListItemButton
sx={{
borderRadius: `${borderRadius}px`,
mb: 0.5,
alignItems: 'flex-start',
backgroundColor: level > 1 ? 'transparent !important' : 'inherit',
py: level > 1 ? 1 : 1.25,
pl: `${level * 24}px`
}}
selected={selected === menu.id}
onClick={handleClick}
>
<ListItemIcon sx={{ my: 'auto', minWidth: !menu.icon ? 18 : 36 }}>{menuIcon}</ListItemIcon>
<ListItemText
primary={
<Typography variant={selected === menu.id ? 'h5' : 'body1'} color="inherit" sx={{ my: 'auto' }}>
{menu.title}
</Typography>
}
secondary={
menu.caption && (
<Typography variant="caption" sx={{ ...theme.typography.subMenuCaption }} display="block" gutterBottom>
{menu.caption}
</Typography>
)
}
/>
{open ? (
<IconChevronUp stroke={1.5} size="1rem" style={{ marginTop: 'auto', marginBottom: 'auto' }} />
) : (
<IconChevronDown stroke={1.5} size="1rem" style={{ marginTop: 'auto', marginBottom: 'auto' }} />
)}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
{open && (
<List
component="div"
disablePadding
sx={{
position: 'relative',
'&:after': {
content: "''",
position: 'absolute',
left: '32px',
top: 0,
height: '100%',
width: '1px',
opacity: theme.palette.mode === 'dark' ? 0.2 : 1,
background: theme.palette.mode === 'dark' ? theme.palette.dark.light : theme.palette.primary.light
}
}}
>
{menus}
</List>
)}
</Collapse>
</>
);
};
NavCollapse.propTypes = {
menu: PropTypes.object,
level: PropTypes.number
};
export default NavCollapse;

@ -0,0 +1,61 @@
import PropTypes from 'prop-types';
// material-ui
import { useTheme } from '@mui/material/styles';
import { Divider, List, Typography } from '@mui/material';
// project imports
import NavItem from '../NavItem';
import NavCollapse from '../NavCollapse';
// ==============================|| SIDEBAR MENU LIST GROUP ||============================== //
const NavGroup = ({ item }) => {
const theme = useTheme();
// menu list collapse & items
const items = item.children?.map((menu) => {
switch (menu.type) {
case 'collapse':
return <NavCollapse key={menu.id} menu={menu} level={1} />;
case 'item':
return <NavItem key={menu.id} item={menu} level={1} />;
default:
return (
<Typography key={menu.id} variant="h6" color="error" align="center">
Menu Items Error
</Typography>
);
}
});
return (
<>
<List
subheader={
item.title && (
<Typography variant="caption" sx={{ ...theme.typography.menuCaption }} display="block" gutterBottom>
{item.title}
{item.caption && (
<Typography variant="caption" sx={{ ...theme.typography.subMenuCaption }} display="block" gutterBottom>
{item.caption}
</Typography>
)}
</Typography>
)
}
>
{items}
</List>
{/* group divider */}
<Divider sx={{ mt: 0.25, mb: 1.25 }} />
</>
);
};
NavGroup.propTypes = {
item: PropTypes.object
};
export default NavGroup;

@ -0,0 +1,115 @@
import PropTypes from 'prop-types';
import { forwardRef, useEffect } from 'react';
import { Link } from 'react-router-dom';
// material-ui
import { useTheme } from '@mui/material/styles';
import { Avatar, Chip, ListItemButton, ListItemIcon, ListItemText, Typography, useMediaQuery } from '@mui/material';
// project imports
import useConfig from 'hooks/useConfig';
import { useDispatch, useSelector } from 'store';
import { activeItem, openDrawer } from 'store/slices/menu';
// assets
import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord';
// ==============================|| SIDEBAR MENU LIST ITEMS ||============================== //
const NavItem = ({ item, level }) => {
const theme = useTheme();
const matchesSM = useMediaQuery(theme.breakpoints.down('lg'));
const { borderRadius } = useConfig();
const dispatch = useDispatch();
const { openItem } = useSelector((state) => state.menu);
const Icon = item?.icon;
const itemIcon = item?.icon ? (
<Icon stroke={1.5} size="1.3rem" />
) : (
<FiberManualRecordIcon
sx={{
width: openItem.findIndex((id) => id === item?.id) > -1 ? 8 : 6,
height: openItem.findIndex((id) => id === item?.id) > -1 ? 8 : 6
}}
fontSize={level > 0 ? 'inherit' : 'medium'}
/>
);
let itemTarget = '_self';
if (item.target) {
itemTarget = '_blank';
}
let listItemProps = { component: forwardRef((props, ref) => <Link ref={ref} {...props} to={item.url} target={itemTarget} />) };
if (item?.external) {
listItemProps = { component: 'a', href: item.url, target: itemTarget };
}
const itemHandler = (id) => {
dispatch(activeItem([id]));
if (matchesSM) dispatch(openDrawer(false));
};
// active menu item on page load
useEffect(() => {
const currentIndex = document.location.pathname
.toString()
.split('/')
.findIndex((id) => id === item.id);
if (currentIndex > -1) {
dispatch(activeItem([item.id]));
}
// eslint-disable-next-line
}, []);
return (
<ListItemButton
{...listItemProps}
disabled={item.disabled}
sx={{
borderRadius: `${borderRadius}px`,
mb: 0.5,
alignItems: 'flex-start',
backgroundColor: level > 1 ? 'transparent !important' : 'inherit',
py: level > 1 ? 1 : 1.25,
pl: `${level * 24}px`
}}
selected={openItem?.findIndex((id) => id === item.id) > -1}
onClick={() => itemHandler(item.id)}
>
<ListItemIcon sx={{ my: 'auto', minWidth: !item?.icon ? 18 : 36 }}>{itemIcon}</ListItemIcon>
<ListItemText
primary={
<Typography variant={openItem?.findIndex((id) => id === item.id) > -1 ? 'h5' : 'body1'} color="inherit">
{item.title}
</Typography>
}
secondary={
item.caption && (
<Typography variant="caption" sx={{ ...theme.typography.subMenuCaption }} display="block" gutterBottom>
{item.caption}
</Typography>
)
}
/>
{item.chip && (
<Chip
color={item.chip.color}
variant={item.chip.variant}
size={item.chip.size}
label={item.chip.label}
avatar={item.chip.avatar && <Avatar>{item.chip.avatar}</Avatar>}
/>
)}
</ListItemButton>
);
};
NavItem.propTypes = {
item: PropTypes.object,
level: PropTypes.number
};
export default NavItem;

@ -0,0 +1,29 @@
import { memo } from 'react';
// material-ui
import { Typography } from '@mui/material';
// project imports
import NavGroup from './NavGroup';
import menuItem from 'menu-items';
// ==============================|| SIDEBAR MENU LIST ||============================== //
const MenuList = () => {
const navItems = menuItem.items.map((item) => {
switch (item.type) {
case 'group':
return <NavGroup key={item.id} item={item} />;
default:
return (
<Typography key={item.id} variant="h6" color="error" align="center">
Menu Items Error
</Typography>
);
}
});
return <>{navItems}</>;
};
export default memo(MenuList);

@ -0,0 +1,96 @@
import PropTypes from 'prop-types';
import { memo, useMemo } from 'react';
// material-ui
import { useTheme } from '@mui/material/styles';
import { Box, Drawer, Stack, useMediaQuery } from '@mui/material';
// third-party
import PerfectScrollbar from 'react-perfect-scrollbar';
// project imports
import MenuList from './MenuList';
import LogoSection from '../LogoSection';
import MenuCard from './MenuCard';
import { openDrawer } from 'store/slices/menu';
import { useDispatch, useSelector } from 'store';
import { drawerWidth } from 'store/constant';
import Chip from 'ui-component/extended/Chip';
// ==============================|| SIDEBAR DRAWER ||============================== //
const Sidebar = ({ window }) => {
const theme = useTheme();
const matchUpMd = useMediaQuery(theme.breakpoints.up('md'));
const dispatch = useDispatch();
const { drawerOpen } = useSelector((state) => state.menu);
const logo = useMemo(
() => (
<Box sx={{ display: { xs: 'block', md: 'none' } }}>
<Box sx={{ display: 'flex', p: 2, mx: 'auto' }}>
<LogoSection />
</Box>
</Box>
),
[]
);
const drawer = useMemo(
() => (
<PerfectScrollbar
component="div"
style={{
height: !matchUpMd ? 'calc(100vh - 56px)' : 'calc(100vh - 88px)',
paddingLeft: '16px',
paddingRight: '16px'
}}
>
<MenuList />
<MenuCard />
<Stack direction="row" justifyContent="center" sx={{ mb: 2 }}>
<Chip label={process.env.REACT_APP_VERSION} disabled chipcolor="secondary" size="small" sx={{ cursor: 'pointer' }} />
</Stack>
</PerfectScrollbar>
),
// eslint-disable-next-line react-hooks/exhaustive-deps
[matchUpMd]
);
const container = window !== undefined ? () => window.document.body : undefined;
return (
<Box component="nav" sx={{ flexShrink: { md: 0 }, width: matchUpMd ? drawerWidth : 'auto' }} aria-label="mailbox folders">
<Drawer
container={container}
variant={matchUpMd ? 'persistent' : 'temporary'}
anchor="left"
open={drawerOpen}
onClose={() => dispatch(openDrawer(!drawerOpen))}
sx={{
'& .MuiDrawer-paper': {
width: drawerWidth,
background: theme.palette.background.default,
color: theme.palette.text.primary,
borderRight: 'none',
[theme.breakpoints.up('md')]: {
top: '88px'
}
}
}}
ModalProps={{ keepMounted: true }}
color="inherit"
>
{drawerOpen && logo}
{drawerOpen && drawer}
</Drawer>
</Box>
);
};
Sidebar.propTypes = {
window: PropTypes.object
};
export default memo(Sidebar);

@ -0,0 +1,129 @@
import React, { useMemo } from 'react';
import { Outlet } from 'react-router-dom';
// material-ui
import { styled, useTheme } from '@mui/material/styles';
import { AppBar, Box, Container, CssBaseline, Toolbar, useMediaQuery } from '@mui/material';
// project imports
import Breadcrumbs from 'ui-component/extended/Breadcrumbs';
import Header from './Header';
import Sidebar from './Sidebar';
import navigation from 'menu-items';
import useConfig from 'hooks/useConfig';
import { drawerWidth } from 'store/constant';
import { openDrawer } from 'store/slices/menu';
import { useDispatch, useSelector } from 'store';
// assets
import { IconChevronRight } from '@tabler/icons';
// styles
const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })(({ theme, open }) => ({
...theme.typography.mainContent,
...(!open && {
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.shorter
}),
[theme.breakpoints.up('md')]: {
marginLeft: -(drawerWidth - 20),
width: `calc(100% - ${drawerWidth}px)`
},
[theme.breakpoints.down('md')]: {
marginLeft: '20px',
width: `calc(100% - ${drawerWidth}px)`,
padding: '16px'
},
[theme.breakpoints.down('sm')]: {
marginLeft: '10px',
width: `calc(100% - ${drawerWidth}px)`,
padding: '16px',
marginRight: '10px'
}
}),
...(open && {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.shorter
}),
marginLeft: 0,
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
width: `calc(100% - ${drawerWidth}px)`,
[theme.breakpoints.down('md')]: {
marginLeft: '20px'
},
[theme.breakpoints.down('sm')]: {
marginLeft: '10px'
}
})
}));
// ==============================|| MAIN LAYOUT ||============================== //
const MainLayout = () => {
const theme = useTheme();
const matchDownMd = useMediaQuery(theme.breakpoints.down('lg'));
const dispatch = useDispatch();
const { drawerOpen } = useSelector((state) => state.menu);
const { container } = useConfig();
React.useEffect(() => {
dispatch(openDrawer(!matchDownMd));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [matchDownMd]);
const header = useMemo(
() => (
<Toolbar>
<Header />
</Toolbar>
),
[]
);
return (
<Box sx={{ display: 'flex' }}>
<CssBaseline />
{/* header */}
<AppBar
enableColorOnDark
position="fixed"
color="inherit"
elevation={0}
sx={{
bgcolor: theme.palette.background.default,
transition: drawerOpen ? theme.transitions.create('width') : 'none'
}}
>
{header}
</AppBar>
{/* drawer */}
<Sidebar />
{/* main content */}
<Main theme={theme} open={drawerOpen}>
{/* breadcrumb */}
{container && (
<Container maxWidth="lg">
<Breadcrumbs separator={IconChevronRight} navigation={navigation} icon title rightAlign />
<Outlet />
</Container>
)}
{!container && (
<>
<Breadcrumbs separator={IconChevronRight} navigation={navigation} icon title rightAlign />
<Outlet />
</>
)}
</Main>
</Box>
);
};
export default MainLayout;

@ -0,0 +1,11 @@
import { Outlet } from 'react-router-dom';
// ==============================|| MINIMAL LAYOUT ||============================== //
const MinimalLayout = () => (
<>
<Outlet />
</>
);
export default MinimalLayout;

@ -0,0 +1,41 @@
import PropTypes from 'prop-types';
// third-party
import { motion } from 'framer-motion';
// ==============================|| ANIMATION FOR CONTENT ||============================== //
const NavMotion = ({ children }) => {
const motionVariants = {
initial: {
opacity: 0,
scale: 0.99
},
in: {
opacity: 1,
scale: 1
},
out: {
opacity: 0,
scale: 1.01
}
};
const motionTransition = {
type: 'tween',
ease: 'anticipate',
duration: 0.4
};
return (
<motion.div initial="initial" animate="in" exit="out" variants={motionVariants} transition={motionTransition}>
{children}
</motion.div>
);
};
NavMotion.propTypes = {
children: PropTypes.node
};
export default NavMotion;

@ -0,0 +1,25 @@
import PropTypes from 'prop-types';
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
// ==============================|| NAVIGATION SCROLL TO TOP ||============================== //
const NavigationScroll = ({ children }) => {
const { pathname } = useLocation();
useEffect(() => {
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});
}, [pathname]);
return children || null;
};
NavigationScroll.propTypes = {
children: PropTypes.node
};
export default NavigationScroll;

@ -0,0 +1,9 @@
import other from './other';
// ==============================|| MENU ITEMS ||============================== //
const menuItems = {
items: [other]
};
export default menuItems;

@ -0,0 +1,49 @@
// third-party
import { FormattedMessage } from 'react-intl';
// assets
import { IconBrandChrome, IconHelp, IconSitemap } from '@tabler/icons';
// constant
const icons = {
IconBrandChrome,
IconHelp,
IconSitemap
};
// ==============================|| SAMPLE PAGE & DOCUMENTATION MENU ITEMS ||============================== //
const other = {
id: 'sample-docs-roadmap',
type: 'group',
children: [
{
id: 'sample-page',
title: <FormattedMessage id="sample-page" />,
type: 'item',
url: '/sample-page',
icon: icons.IconBrandChrome,
breadcrumbs: false
},
{
id: 'documentation',
title: <FormattedMessage id="documentation" />,
type: 'item',
url: 'https://codedthemes.gitbook.io/berry/',
icon: icons.IconHelp,
external: true,
target: true
},
{
id: 'roadmap',
title: <FormattedMessage id="roadmap" />,
type: 'item',
url: 'https://codedthemes.gitbook.io/berry/roadmap',
icon: icons.IconSitemap,
external: true,
target: true
}
]
};
export default other;

@ -0,0 +1 @@
/// <reference types="react-scripts" />

@ -0,0 +1,13 @@
const reportWebVitals = (onPerfEntry) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

@ -0,0 +1,12 @@
// project imports
import MinimalLayout from 'layout/MinimalLayout';
// ==============================|| AUTHENTICATION ROUTING ||============================== //
const AuthenticationRoutes = {
path: '/',
element: <MinimalLayout />,
children: []
};
export default AuthenticationRoutes;

@ -0,0 +1,41 @@
import { lazy } from 'react';
// project imports
import GuestGuard from 'utils/route-guard/GuestGuard';
import MinimalLayout from 'layout/MinimalLayout';
import NavMotion from 'layout/NavMotion';
import Loadable from 'ui-component/Loadable';
// login routing
const AuthLogin = Loadable(lazy(() => import('views/pages/authentication/authentication3/Login3')));
const AuthRegister = Loadable(lazy(() => import('views/pages/authentication/authentication3/Register3')));
const AuthForgotPassword = Loadable(lazy(() => import('views/pages/authentication/authentication3/ForgotPassword3')));
// ==============================|| AUTH ROUTING ||============================== //
const LoginRoutes = {
path: '/',
element: (
<NavMotion>
<GuestGuard>
<MinimalLayout />
</GuestGuard>
</NavMotion>
),
children: [
{
path: '/login',
element: <AuthLogin />
},
{
path: '/register',
element: <AuthRegister />
},
{
path: '/forgot',
element: <AuthForgotPassword />
}
]
};
export default LoginRoutes;

@ -0,0 +1,32 @@
import { lazy } from 'react';
// project imports
import MainLayout from 'layout/MainLayout';
import Loadable from 'ui-component/Loadable';
import AuthGuard from 'utils/route-guard/AuthGuard';
// sample page routing
const SamplePage = Loadable(lazy(() => import('views/sample-page')));
// ==============================|| MAIN ROUTING ||============================== //
const MainRoutes = {
path: '/',
element: (
<AuthGuard>
<MainLayout />
</AuthGuard>
),
children: [
{
path: '/',
element: <SamplePage />
},
{
path: '/sample-page',
element: <SamplePage />
}
]
};
export default MainRoutes;

@ -0,0 +1,12 @@
import { useRoutes } from 'react-router-dom';
// routes
import MainRoutes from './MainRoutes';
import LoginRoutes from './LoginRoutes';
import AuthenticationRoutes from './AuthenticationRoutes';
// ==============================|| ROUTING RENDER ||============================== //
export default function ThemeRoutes() {
return useRoutes([MainRoutes, LoginRoutes, AuthenticationRoutes]);
}

@ -0,0 +1,128 @@
// This optional code is used to register a service worker.
// register() is not called by default.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on subsequent visits to a page, after all the
// existing tabs open on the page have been closed, since previously cached
// resources are updated in the background.
// To learn more about the benefits of this model and instructions on how to
// opt-in, read https://bit.ly/CRA-PWA
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.0/8 are considered localhost for IPv4.
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
);
function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
.then((registration) => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
console.log('New content is available and will be used when all tabs for this page are closed. See https://bit.ly/CRA-PWA.');
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
.catch((error) => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl, config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl, {
headers: { 'Service-Worker': 'script' }
})
.then((response) => {
// Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type');
if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then((registration) => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
}
})
.catch(() => {
console.log('No internet connection found. App is running in offline mode.');
});
}
export function register(config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log('This web app is being served cache-first by a service worker. To learn more, visit https://bit.ly/CRA-PWA');
});
} else {
// Is not localhost. Just register service worker
registerValidSW(swUrl, config);
}
});
}
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready
.then((registration) => {
registration.unregister();
})
.catch((error) => {
console.error(error.message);
});
}
}

@ -0,0 +1,44 @@
// action - state management
import { LOGIN, LOGOUT, REGISTER } from './actions';
// ==============================|| ACCOUNT REDUCER ||============================== //
const initialState = {
isLoggedIn: false,
isInitialized: false,
user: null
};
const accountReducer = (state = initialState, action) => {
switch (action.type) {
case REGISTER: {
const { user } = action.payload;
return {
...state,
user
};
}
case LOGIN: {
const { user } = action.payload;
return {
...state,
isLoggedIn: true,
isInitialized: true,
user
};
}
case LOGOUT: {
return {
...state,
isInitialized: true,
isLoggedIn: false,
user: null
};
}
default: {
return { ...state };
}
}
};
export default accountReducer;

@ -0,0 +1,5 @@
// action - account reducer
export const LOGIN = 'LOGIN';
export const LOGOUT = 'LOGOUT';
export const REGISTER = 'REGISTER';
export const FIREBASE_STATE_CHANGED = 'FIREBASE_STATE_CHANGED';

@ -0,0 +1,4 @@
// theme constant
export const gridSpacing = 3;
export const drawerWidth = 260;
export const appDrawerWidth = 320;

@ -0,0 +1,24 @@
// third-party
import { configureStore } from '@reduxjs/toolkit';
import { useDispatch as useAppDispatch, useSelector as useAppSelector } from 'react-redux';
import { persistStore } from 'redux-persist';
// project imports
import rootReducer from './reducer';
// ==============================|| REDUX - MAIN STORE ||============================== //
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false, immutableCheck: false })
});
const persister = persistStore(store);
const { dispatch } = store;
const useDispatch = () => useAppDispatch();
const useSelector = useAppSelector;
export { store, persister, dispatch, useSelector, useDispatch };

@ -0,0 +1,42 @@
// third-party
import { combineReducers } from 'redux';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
// project imports
import snackbarReducer from './slices/snackbar';
import customerReducer from './slices/customer';
import contactReducer from './slices/contact';
import productReducer from './slices/product';
import chatReducer from './slices/chat';
import calendarReducer from './slices/calendar';
import mailReducer from './slices/mail';
import userReducer from './slices/user';
import cartReducer from './slices/cart';
import kanbanReducer from './slices/kanban';
import menuReducer from './slices/menu';
// ==============================|| COMBINE REDUCER ||============================== //
const reducer = combineReducers({
snackbar: snackbarReducer,
cart: persistReducer(
{
key: 'cart',
storage,
keyPrefix: 'berry-'
},
cartReducer
),
kanban: kanbanReducer,
customer: customerReducer,
contact: contactReducer,
product: productReducer,
chat: chatReducer,
calendar: calendarReducer,
mail: mailReducer,
user: userReducer,
menu: menuReducer
});
export default reducer;

@ -0,0 +1,93 @@
// third-party
import { createSlice } from '@reduxjs/toolkit';
// project imports
import axios from 'utils/axios';
import { dispatch } from '../index';
// ----------------------------------------------------------------------
const initialState = {
error: null,
events: []
};
const slice = createSlice({
name: 'calendar',
initialState,
reducers: {
// HAS ERROR
hasError(state, action) {
state.error = action.payload;
},
// GET EVENTS
getEventsSuccess(state, action) {
state.events = action.payload;
},
// ADD EVENT
addEventSuccess(state, action) {
state.events = action.payload;
},
// UPDATE EVENT
updateEventSuccess(state, action) {
state.events = action.payload;
},
// REMOVE EVENT
removeEventSuccess(state, action) {
state.events = action.payload;
}
}
});
// Reducer
export default slice.reducer;
// ----------------------------------------------------------------------
export function getEvents() {
return async () => {
try {
const response = await axios.get('/api/calendar/events');
dispatch(slice.actions.getEventsSuccess(response.data.events));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function addEvent(event) {
return async () => {
try {
const response = await axios.post('/api/calendar/events/new', event);
dispatch(slice.actions.addEventSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function updateEvent(event) {
return async () => {
try {
const response = await axios.post('/api/calendar/events/update', event);
dispatch(slice.actions.updateEventSuccess(response.data.events));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function removeEvent(eventId) {
return async () => {
try {
const response = await axios.post('/api/calendar/events/remove', { eventId });
dispatch(slice.actions.removeEventSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}

@ -0,0 +1,242 @@
// third-party
import { createSlice } from '@reduxjs/toolkit';
// project imports
import axios from 'utils/axios';
import { dispatch } from '../index';
// ----------------------------------------------------------------------
const initialState = {
error: null,
checkout: {
step: 0,
products: [],
subtotal: 0,
total: 0,
discount: 0,
shipping: 0,
billing: null,
payment: {
type: 'free',
method: 'cod',
card: ''
}
}
};
const slice = createSlice({
name: 'cart',
initialState,
reducers: {
// HAS ERROR
hasError(state, action) {
state.error = action.payload;
},
// ADD PRODUCT
addProductSuccess(state, action) {
state.checkout.products = action.payload.products;
state.checkout.subtotal += action.payload.subtotal;
state.checkout.total += action.payload.subtotal;
},
// REMOVE PRODUCT
removeProductSuccess(state, action) {
state.checkout.products = action.payload.products;
state.checkout.subtotal += -action.payload.subtotal;
state.checkout.total += -action.payload.subtotal;
},
// UPDATE PRODUCT
updateProductSuccess(state, action) {
state.checkout.products = action.payload.products;
state.checkout.subtotal = state.checkout.subtotal - action.payload.oldSubTotal + action.payload.subtotal;
state.checkout.total = state.checkout.total - action.payload.oldSubTotal + action.payload.subtotal;
},
// SET STEP
setStepSuccess(state, action) {
state.checkout.step = action.payload;
},
// SET NEXT STEP
setNextStepSuccess(state) {
state.checkout.step += 1;
},
// SET BACK STEP
setBackStepSuccess(state) {
state.checkout.step -= 1;
},
// SET BILLING ADDRESS
setBillingAddressSuccess(state, action) {
state.checkout.billing = action.payload.billing;
},
// SET DISCOUNT
setDiscountSuccess(state, action) {
let difference = 0;
if (state.checkout.discount > 0) {
difference = state.checkout.discount;
}
state.checkout.discount = action.payload.amount;
state.checkout.total = state.checkout.total + difference - action.payload.amount;
},
// SET SHIPPING CHARGE
setShippingChargeSuccess(state, action) {
state.checkout.shipping = action.payload.shipping;
state.checkout.total += action.payload.newShipping;
state.checkout.payment = {
...state.checkout.payment,
type: action.payload.type
};
},
// SET PAYMENT METHOD
setPaymentMethodSuccess(state, action) {
state.checkout.payment = {
...state.checkout.payment,
method: action.payload.method
};
},
// SET PAYMENT CARD
setPaymentCardSuccess(state, action) {
state.checkout.payment = {
...state.checkout.payment,
card: action.payload.card
};
},
// RESET CART
resetCardSuccess(state) {
state.checkout = initialState.checkout;
}
}
});
// Reducer
export default slice.reducer;
// ----------------------------------------------------------------------
export function addProduct(product, products) {
return async () => {
try {
const response = await axios.post('/api/cart/add', { product, products });
dispatch(slice.actions.addProductSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function removeProduct(id, products) {
return async () => {
try {
const response = await axios.post('/api/cart/remove', { id, products });
dispatch(slice.actions.removeProductSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function updateProduct(id, quantity, products) {
return async () => {
try {
const response = await axios.post('/api/cart/update', { id, quantity, products });
dispatch(slice.actions.updateProductSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function setStep(step) {
return () => {
dispatch(slice.actions.setStepSuccess(step));
};
}
export function setNextStep() {
return () => {
dispatch(slice.actions.setNextStepSuccess({}));
};
}
export function setBackStep() {
return () => {
dispatch(slice.actions.setBackStepSuccess({}));
};
}
export function setBillingAddress(address) {
return async () => {
try {
const response = await axios.post('/api/cart/billing-address', { address });
dispatch(slice.actions.setBillingAddressSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function setDiscount(code, total) {
return async () => {
try {
const response = await axios.post('/api/cart/discount', { code, total });
dispatch(slice.actions.setDiscountSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function setShippingCharge(charge, shipping) {
return async () => {
try {
const response = await axios.post('/api/cart/shipping-charge', { charge, shipping });
dispatch(slice.actions.setShippingChargeSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function setPaymentMethod(method) {
return async () => {
try {
const response = await axios.post('/api/cart/payment-method', { method });
dispatch(slice.actions.setPaymentMethodSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function setPaymentCard(card) {
return async () => {
try {
const response = await axios.post('/api/cart/payment-card', { card });
dispatch(slice.actions.setPaymentCardSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function resetCart() {
return async () => {
try {
const response = await axios.post('/api/cart/reset');
dispatch(slice.actions.resetCardSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}

@ -0,0 +1,89 @@
// third-party
import { createSlice } from '@reduxjs/toolkit';
// project imports
import axios from 'utils/axios';
import { dispatch } from '../index';
// ----------------------------------------------------------------------
const initialState = {
error: null,
chats: [],
user: {},
users: []
};
const slice = createSlice({
name: 'chat',
initialState,
reducers: {
// HAS ERROR
hasError(state, action) {
state.error = action.payload;
},
// GET USER
getUserSuccess(state, action) {
state.user = action.payload;
},
// GET USER CHATS
getUserChatsSuccess(state, action) {
state.chats = action.payload;
},
// GET USERS
getUsersSuccess(state, action) {
state.users = action.payload;
}
}
});
// Reducer
export default slice.reducer;
// ----------------------------------------------------------------------
export function getUser(id) {
return async () => {
try {
const response = await axios.post('/api/chat/users/id', { id });
dispatch(slice.actions.getUserSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getUserChats(user) {
return async () => {
try {
const response = await axios.post('/api/chat/filter', { user });
dispatch(slice.actions.getUserChatsSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function insertChat(chat) {
return async () => {
try {
await axios.post('/api/chat/insert', chat);
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getUsers() {
return async () => {
try {
const response = await axios.get('/api/chat/users');
dispatch(slice.actions.getUsersSuccess(response.data.users));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}

@ -0,0 +1,61 @@
// third-party
import { createSlice } from '@reduxjs/toolkit';
// project imports
import axios from 'utils/axios';
import { dispatch } from '../index';
// ----------------------------------------------------------------------
const initialState = {
error: null,
contacts: []
};
const slice = createSlice({
name: 'contact',
initialState,
reducers: {
// HAS ERROR
hasError(state, action) {
state.error = action.payload;
},
// GET CONTACTS
getContactsSuccess(state, action) {
state.contacts = action.payload;
},
// MODIFY CONTACT
modifyContactSuccess(state, action) {
state.contacts = action.payload;
}
}
});
// Reducer
export default slice.reducer;
// ----------------------------------------------------------------------
export function getContacts() {
return async () => {
try {
const response = await axios.get('/api/contact/list');
dispatch(slice.actions.getContactsSuccess(response.data.contacts));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function modifyContact(contact) {
return async () => {
try {
const response = await axios.post('/api/contact/modify', contact);
dispatch(slice.actions.modifyContactSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}

@ -0,0 +1,96 @@
// third-party
import { createSlice } from '@reduxjs/toolkit';
// project imports
import axios from 'utils/axios';
import { dispatch } from '../index';
// ----------------------------------------------------------------------
const initialState = {
error: null,
customers: [],
orders: [],
products: [],
productreviews: []
};
const slice = createSlice({
name: 'customer',
initialState,
reducers: {
// HAS ERROR
hasError(state, action) {
state.error = action.payload;
},
// GET CUSTOMERS
getCustomersSuccess(state, action) {
state.customers = action.payload;
},
// GET ORDERS
getOrdersSuccess(state, action) {
state.orders = action.payload;
},
// GET PRODUCTS
getProductsSuccess(state, action) {
state.products = action.payload;
},
// GET PRODUCT REVIEWS
getProductReviewsSuccess(state, action) {
state.productreviews = action.payload;
}
}
});
// Reducer
export default slice.reducer;
// ----------------------------------------------------------------------
export function getCustomers() {
return async () => {
try {
const response = await axios.get('/api/customer/list');
dispatch(slice.actions.getCustomersSuccess(response.data.customers));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getOrders() {
return async () => {
try {
const response = await axios.get('/api/customer/order/list');
dispatch(slice.actions.getOrdersSuccess(response.data.orders));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getProducts() {
return async () => {
try {
const response = await axios.get('/api/customer/product/list');
dispatch(slice.actions.getProductsSuccess(response.data.products));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getProductReviews() {
return async () => {
try {
const response = await axios.get('/api/customer/product/reviews');
dispatch(slice.actions.getProductReviewsSuccess(response.data.productreviews));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}

@ -0,0 +1,416 @@
// third-party
import { createSlice } from '@reduxjs/toolkit';
// project imports
import axios from 'utils/axios';
import { dispatch } from '../index';
// ----------------------------------------------------------------------
const initialState = {
error: null,
columns: [],
columnsOrder: [],
comments: [],
items: [],
profiles: [],
selectedItem: false,
userStory: [],
userStoryOrder: []
};
const slice = createSlice({
name: 'kanban',
initialState,
reducers: {
// HAS ERROR
hasError(state, action) {
state.error = action.payload;
},
// ADD COLUMN
addColumnSuccess(state, action) {
state.columns = action.payload.columns;
state.columnsOrder = action.payload.columnsOrder;
},
// EDIT COLUMN
editColumnSuccess(state, action) {
state.columns = action.payload.columns;
},
// UPDATE COLUMN ORDER
updateColumnOrderSuccess(state, action) {
state.columnsOrder = action.payload.columnsOrder;
},
// DELETE COLUMN
deleteColumnSuccess(state, action) {
state.columns = action.payload.columns;
state.columnsOrder = action.payload.columnsOrder;
},
// ADD ITEM
addItemSuccess(state, action) {
state.items = action.payload.items;
state.columns = action.payload.columns;
state.userStory = action.payload.userStory;
},
// EDIT ITEM
editItemSuccess(state, action) {
state.items = action.payload.items;
state.columns = action.payload.columns;
state.userStory = action.payload.userStory;
},
// UPDATE COLUMN ITEM ORDER
updateColumnItemOrderSuccess(state, action) {
state.columns = action.payload.columns;
},
// SELECT ITEM
selectItemSuccess(state, action) {
state.selectedItem = action.payload.selectedItem;
},
// ADD ITEM COMMENT
addItemCommentSuccess(state, action) {
state.items = action.payload.items;
state.comments = action.payload.comments;
},
// DELETE ITEM
deleteItemSuccess(state, action) {
state.items = action.payload.items;
state.columns = action.payload.columns;
state.userStory = action.payload.userStory;
},
// ADD STORY
addStorySuccess(state, action) {
state.userStory = action.payload.userStory;
state.userStoryOrder = action.payload.userStoryOrder;
},
// EDIT STORY
editStorySuccess(state, action) {
state.userStory = action.payload.userStory;
},
// UPDATE STORY ORDER
updateStoryOrderSuccess(state, action) {
state.userStoryOrder = action.payload.userStoryOrder;
},
// UPDATE STORY ITEM ORDER
updateStoryItemOrderSuccess(state, action) {
state.userStory = action.payload.userStory;
},
// ADD STORY COMMENT
addStoryCommentSuccess(state, action) {
state.userStory = action.payload.userStory;
state.comments = action.payload.comments;
},
// DELETE STORY
deleteStorySuccess(state, action) {
state.userStory = action.payload.userStory;
state.userStoryOrder = action.payload.userStoryOrder;
},
// GET COLUMNS
getColumnsSuccess(state, action) {
state.columns = action.payload;
},
// GET COLUMNS ORDER
getColumnsOrderSuccess(state, action) {
state.columnsOrder = action.payload;
},
// GET COMMENTS
getCommentsSuccess(state, action) {
state.comments = action.payload;
},
// GET PROFILES
getProfilesSuccess(state, action) {
state.profiles = action.payload;
},
// GET ITEMS
getItemsSuccess(state, action) {
state.items = action.payload;
},
// GET USER STORY
getUserStorySuccess(state, action) {
state.userStory = action.payload;
},
// GET USER STORY ORDER
getUserStoryOrderSuccess(state, action) {
state.userStoryOrder = action.payload;
}
}
});
// Reducer
export default slice.reducer;
// ----------------------------------------------------------------------
export function getColumns() {
return async () => {
try {
const response = await axios.get('/api/kanban/columns');
dispatch(slice.actions.getColumnsSuccess(response.data.columns));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getColumnsOrder() {
return async () => {
try {
const response = await axios.get('/api/kanban/columns-order');
dispatch(slice.actions.getColumnsOrderSuccess(response.data.columnsOrder));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getComments() {
return async () => {
try {
const response = await axios.get('/api/kanban/comments');
dispatch(slice.actions.getCommentsSuccess(response.data.comments));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getProfiles() {
return async () => {
try {
const response = await axios.get('/api/kanban/profiles');
dispatch(slice.actions.getProfilesSuccess(response.data.profiles));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getItems() {
return async () => {
try {
const response = await axios.get('/api/kanban/items');
dispatch(slice.actions.getItemsSuccess(response.data.items));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getUserStory() {
return async () => {
try {
const response = await axios.get('/api/kanban/userstory');
dispatch(slice.actions.getUserStorySuccess(response.data.userStory));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getUserStoryOrder() {
return async () => {
try {
const response = await axios.get('/api/kanban/userstory-order');
dispatch(slice.actions.getUserStoryOrderSuccess(response.data.userStoryOrder));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function addColumn(column, columns, columnsOrder) {
return async () => {
try {
const response = await axios.post('/api/kanban/add-column', { column, columns, columnsOrder });
dispatch(slice.actions.addColumnSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function editColumn(column, columns) {
return async () => {
try {
const response = await axios.post('/api/kanban/edit-column', { column, columns });
dispatch(slice.actions.editColumnSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function updateColumnOrder(columnsOrder) {
return async () => {
try {
const response = await axios.post('/api/kanban/update-column-order', { columnsOrder });
dispatch(slice.actions.updateColumnOrderSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function deleteColumn(columnId, columnsOrder, columns) {
return async () => {
try {
const response = await axios.post('/api/kanban/delete-column', { columnId, columnsOrder, columns });
dispatch(slice.actions.deleteColumnSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function addItem(columnId, columns, item, items, storyId, userStory) {
return async () => {
try {
const response = await axios.post('/api/kanban/add-item', { columnId, columns, item, items, storyId, userStory });
dispatch(slice.actions.addItemSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function editItem(columnId, columns, item, items, storyId, userStory) {
return async () => {
try {
const response = await axios.post('/api/kanban/edit-item', { items, item, userStory, storyId, columns, columnId });
dispatch(slice.actions.editItemSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function updateColumnItemOrder(columns) {
return async () => {
try {
const response = await axios.post('/api/kanban/update-item-order', { columns });
dispatch(slice.actions.updateColumnItemOrderSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function selectItem(selectedItem) {
return async () => {
try {
const response = await axios.post('/api/kanban/select-item', { selectedItem });
dispatch(slice.actions.selectItemSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function addItemComment(itemId, comment, items, comments) {
return async () => {
try {
const response = await axios.post('/api/kanban/add-item-comment', { items, itemId, comment, comments });
dispatch(slice.actions.addItemCommentSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function deleteItem(itemId, items, columns, userStory) {
return async () => {
try {
const response = await axios.post('/api/kanban/delete-item', { columns, itemId, userStory, items });
dispatch(slice.actions.deleteItemSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function addStory(story, userStory, userStoryOrder) {
return async () => {
try {
const response = await axios.post('/api/kanban/add-story', { userStory, story, userStoryOrder });
dispatch(slice.actions.addStorySuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function editStory(story, userStory) {
return async () => {
try {
const response = await axios.post('/api/kanban/edit-story', { userStory, story });
dispatch(slice.actions.editStorySuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function updateStoryOrder(userStoryOrder) {
return async () => {
try {
const response = await axios.post('/api/kanban/update-story-order', { userStoryOrder });
dispatch(slice.actions.updateStoryOrderSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function updateStoryItemOrder(userStory) {
return async () => {
try {
const response = await axios.post('/api/kanban/update-storyitem-order', { userStory });
dispatch(slice.actions.updateStoryItemOrderSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function addStoryComment(storyId, comment, comments, userStory) {
return async () => {
try {
const response = await axios.post('/api/kanban/add-story-comment', { userStory, storyId, comment, comments });
dispatch(slice.actions.addStoryCommentSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function deleteStory(storyId, userStory, userStoryOrder) {
return async () => {
try {
const response = await axios.post('/api/kanban/delete-story', { userStory, storyId, userStoryOrder });
dispatch(slice.actions.deleteStorySuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}

@ -0,0 +1,93 @@
// third-party
import { createSlice } from '@reduxjs/toolkit';
// project imports
import axios from 'utils/axios';
import { dispatch } from '../index';
// ----------------------------------------------------------------------
const initialState = {
error: null,
mails: [],
unreadCount: undefined
};
const slice = createSlice({
name: 'mail',
initialState,
reducers: {
// HAS ERROR
hasError(state, action) {
state.error = action.payload;
},
// GET MAILS
getMailsSuccess(state, action) {
state.mails = action.payload.mails;
state.unreadCount = action.payload.unreadCount;
},
// FILTER MAILS
filterMailsSuccess(state, action) {
state.mails = action.payload;
}
}
});
// Reducer
export default slice.reducer;
// ----------------------------------------------------------------------
export function getMails() {
return async () => {
try {
const response = await axios.get('/api/mails/list');
dispatch(slice.actions.getMailsSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function filterMails(filter) {
return async () => {
try {
const response = await axios.post('/api/mails/filter', { filter });
dispatch(slice.actions.filterMailsSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function setImportant(id) {
return async () => {
try {
await axios.post('/api/mails/setImportant', { id });
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function setStarred(id) {
return async () => {
try {
await axios.post('/api/mails/setStarred', { id });
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function setRead(id) {
return async () => {
try {
await axios.post('/api/mails/setRead', { id });
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}

@ -0,0 +1,27 @@
import { createSlice } from '@reduxjs/toolkit';
// initial state
const initialState = {
openItem: ['dashboard'],
drawerOpen: false
};
// ==============================|| SLICE - MENU ||============================== //
const menu = createSlice({
name: 'menu',
initialState,
reducers: {
activeItem(state, action) {
state.openItem = action.payload;
},
openDrawer(state, action) {
state.drawerOpen = action.payload;
}
}
});
export default menu.reducer;
export const { activeItem, openDrawer } = menu.actions;

@ -0,0 +1,161 @@
// third-party
import { createSlice } from '@reduxjs/toolkit';
// project imports
import axios from 'utils/axios';
import { dispatch } from '../index';
// ----------------------------------------------------------------------
const initialState = {
error: null,
products: [],
product: null,
relatedProducts: [],
reviews: [],
addresses: []
};
const slice = createSlice({
name: 'product',
initialState,
reducers: {
// HAS ERROR
hasError(state, action) {
state.error = action.payload;
},
// GET PRODUCTS
getProductsSuccess(state, action) {
state.products = action.payload;
},
// FILTER PRODUCTS
filterProductsSuccess(state, action) {
state.products = action.payload;
},
// GET PRODUCT
getProductSuccess(state, action) {
state.product = action.payload;
},
// GET RELATED PRODUCTS
getRelatedProductsSuccess(state, action) {
state.relatedProducts = action.payload;
},
// GET PRODUCT REVIEWS
getProductReviewsSuccess(state, action) {
state.reviews = action.payload;
},
// GET ADDRESSES
getAddressesSuccess(state, action) {
state.addresses = action.payload;
},
// ADD ADDRESS
addAddressSuccess(state, action) {
state.addresses = action.payload;
},
// EDIT ADDRESS
editAddressSuccess(state, action) {
state.addresses = action.payload;
}
}
});
// Reducer
export default slice.reducer;
// ----------------------------------------------------------------------
export function getProducts() {
return async () => {
try {
const response = await axios.get('/api/products/list');
dispatch(slice.actions.getProductsSuccess(response.data.products));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function filterProducts(filter) {
return async () => {
try {
const response = await axios.post('/api/products/filter', { filter });
dispatch(slice.actions.filterProductsSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getProduct(id) {
return async () => {
try {
const response = await axios.post('/api/product/details', { id });
dispatch(slice.actions.getProductSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getRelatedProducts(id) {
return async () => {
try {
const response = await axios.post('/api/product/related', { id });
dispatch(slice.actions.getRelatedProductsSuccess(response.data));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getProductReviews() {
return async () => {
try {
const response = await axios.get('/api/review/list');
dispatch(slice.actions.getProductReviewsSuccess(response.data.productReviews));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getAddresses() {
return async () => {
try {
const response = await axios.get('/api/address/list');
dispatch(slice.actions.getAddressesSuccess(response.data.address));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function addAddress(address) {
return async () => {
try {
const response = await axios.post('/api/address/new', address);
dispatch(slice.actions.addAddressSuccess(response.data.address));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function editAddress(address) {
return async () => {
try {
const response = await axios.post('/api/address/edit', address);
dispatch(slice.actions.editAddressSuccess(response.data.address));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}

@ -0,0 +1,52 @@
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
action: false,
open: false,
message: 'Note archived',
anchorOrigin: {
vertical: 'bottom',
horizontal: 'right'
},
variant: 'default',
alert: {
color: 'primary',
variant: 'filled'
},
transition: 'Fade',
close: true,
actionButton: false
};
// ==============================|| SLICE - SNACKBAR ||============================== //
const snackbar = createSlice({
name: 'snackbar',
initialState,
reducers: {
openSnackbar(state, action) {
const { open, message, anchorOrigin, variant, alert, transition, close, actionButton } = action.payload;
state.action = !state.action;
state.open = open || initialState.open;
state.message = message || initialState.message;
state.anchorOrigin = anchorOrigin || initialState.anchorOrigin;
state.variant = variant || initialState.variant;
state.alert = {
color: alert?.color || initialState.alert.color,
variant: alert?.variant || initialState.alert.variant
};
state.transition = transition || initialState.transition;
state.close = close === false ? close : initialState.close;
state.actionButton = actionButton || initialState.actionButton;
},
closeSnackbar(state) {
state.open = false;
}
}
});
export default snackbar.reducer;
export const { closeSnackbar, openSnackbar } = snackbar.actions;

@ -0,0 +1,390 @@
// third-party
import { createSlice } from '@reduxjs/toolkit';
// project imports
import axios from 'utils/axios';
import { dispatch } from '../index';
// ----------------------------------------------------------------------
const initialState = {
error: null,
usersS1: [],
usersS2: [],
followers: [],
friendRequests: [],
friends: [],
gallery: [],
posts: [],
detailCards: [],
simpleCards: [],
profileCards: []
};
const slice = createSlice({
name: 'user',
initialState,
reducers: {
// HAS ERROR
hasError(state, action) {
state.error = action.payload;
},
// GET USERS STYLE 1
getUsersListStyle1Success(state, action) {
state.usersS1 = action.payload;
},
// GET USERS STYLE 2
getUsersListStyle2Success(state, action) {
state.usersS2 = action.payload;
},
// GET FOLLOWERS
getFollowersSuccess(state, action) {
state.followers = action.payload;
},
// FILTER FOLLOWERS
filterFollowersSuccess(state, action) {
state.followers = action.payload;
},
// GET FRIEND REQUESTS
getFriendRequestsSuccess(state, action) {
state.friendRequests = action.payload;
},
// FILTER FRIEND REQUESTS
filterFriendRequestsSuccess(state, action) {
state.friendRequests = action.payload;
},
// GET FRIENDS
getFriendsSuccess(state, action) {
state.friends = action.payload;
},
// FILTER FRIENDS
filterFriendsSuccess(state, action) {
state.friends = action.payload;
},
// GET GALLERY
getGallerySuccess(state, action) {
state.gallery = action.payload;
},
// GET POSTS
getPostsSuccess(state, action) {
state.posts = action.payload;
},
// EDIT COMMENT
editCommentSuccess(state, action) {
state.posts = action.payload;
},
// ADD COMMENT
addCommentSuccess(state, action) {
state.posts = action.payload;
},
// ADD REPLY
addReplySuccess(state, action) {
state.posts = action.payload;
},
// LIKE POST
likePostSuccess(state, action) {
state.posts = action.payload;
},
// LIKE COMMENT
likeCommentSuccess(state, action) {
state.posts = action.payload;
},
// LIKE REPLY
likeReplySuccess(state, action) {
state.posts = action.payload;
},
// GET DETAIL CARDS
getDetailCardsSuccess(state, action) {
state.detailCards = action.payload;
},
// FILTER DETAIL CARDS
filterDetailCardsSuccess(state, action) {
state.detailCards = action.payload;
},
// GET SIMPLE CARDS
getSimpleCardsSuccess(state, action) {
state.simpleCards = action.payload;
},
// FILTER SIMPLE CARDS
filterSimpleCardsSuccess(state, action) {
state.simpleCards = action.payload;
},
// GET PROFILE CARDS
getProfileCardsSuccess(state, action) {
state.profileCards = action.payload;
},
// FILTER PROFILE CARDS
filterProfileCardsSuccess(state, action) {
state.profileCards = action.payload;
}
}
});
// Reducer
export default slice.reducer;
// ----------------------------------------------------------------------
export function getUsersListStyle1() {
return async () => {
try {
const response = await axios.get('/api/user-list/s1/list');
dispatch(slice.actions.getUsersListStyle1Success(response.data.users_s1));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getUsersListStyle2() {
return async () => {
try {
const response = await axios.get('/api/user-list/s2/list');
dispatch(slice.actions.getUsersListStyle2Success(response.data.users_s2));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getFollowers() {
return async () => {
try {
const response = await axios.get('/api/followers/list');
dispatch(slice.actions.getFollowersSuccess(response.data.followers));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function filterFollowers(key) {
return async () => {
try {
const response = await axios.post('/api/followers/filter', { key });
dispatch(slice.actions.filterFollowersSuccess(response.data.results));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getFriendRequests() {
return async () => {
try {
const response = await axios.get('/api/friend-request/list');
dispatch(slice.actions.getFriendRequestsSuccess(response.data.friends));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function filterFriendRequests(key) {
return async () => {
try {
const response = await axios.post('/api/friend-request/filter', { key });
dispatch(slice.actions.filterFriendRequestsSuccess(response.data.results));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getFriends() {
return async () => {
try {
const response = await axios.get('/api/friends/list');
dispatch(slice.actions.getFriendsSuccess(response.data.friends));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function filterFriends(key) {
return async () => {
try {
const response = await axios.post('/api/friends/filter', { key });
dispatch(slice.actions.filterFriendsSuccess(response.data.results));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getGallery() {
return async () => {
try {
const response = await axios.get('/api/gallery/list');
dispatch(slice.actions.getGallerySuccess(response.data.gallery));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getPosts() {
return async () => {
try {
const response = await axios.get('/api/posts/list');
dispatch(slice.actions.getPostsSuccess(response.data.posts));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function editComment(key, id) {
return async () => {
try {
const response = await axios.post('/api/posts/editComment', { key, id });
dispatch(slice.actions.editCommentSuccess(response.data.posts));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function addComment(postId, comment) {
return async () => {
try {
const response = await axios.post('/api/comments/add', { postId, comment });
dispatch(slice.actions.addCommentSuccess(response.data.posts));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function addReply(postId, commentId, reply) {
return async () => {
try {
const response = await axios.post('/api/replies/add', { postId, commentId, reply });
dispatch(slice.actions.addReplySuccess(response.data.posts));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function likePost(postId) {
return async () => {
try {
const response = await axios.post('/api/posts/list/like', { postId });
dispatch(slice.actions.likePostSuccess(response.data.posts));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function likeComment(postId, commentId) {
return async () => {
try {
const response = await axios.post('/api/comments/list/like', { postId, commentId });
dispatch(slice.actions.likeCommentSuccess(response.data.posts));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function likeReply(postId, commentId, replayId) {
return async () => {
try {
const response = await axios.post('/api/replies/list/like', { postId, commentId, replayId });
dispatch(slice.actions.likeReplySuccess(response.data.posts));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getDetailCards() {
return async () => {
try {
const response = await axios.get('/api/details-card/list');
dispatch(slice.actions.getDetailCardsSuccess(response.data.users));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function filterDetailCards(key) {
return async () => {
try {
const response = await axios.post('/api/details-card/filter', { key });
dispatch(slice.actions.filterDetailCardsSuccess(response.data.results));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getSimpleCards() {
return async () => {
try {
const response = await axios.get('/api/simple-card/list');
dispatch(slice.actions.getSimpleCardsSuccess(response.data.users));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function filterSimpleCards(key) {
return async () => {
try {
const response = await axios.post('/api/simple-card/filter', { key });
dispatch(slice.actions.filterSimpleCardsSuccess(response.data.results));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function getProfileCards() {
return async () => {
try {
const response = await axios.get('/api/profile-card/list');
dispatch(slice.actions.getProfileCardsSuccess(response.data.users));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}
export function filterProfileCards(key) {
return async () => {
try {
const response = await axios.post('/api/profile-card/filter', { key });
dispatch(slice.actions.filterProfileCardsSuccess(response.data.results));
} catch (error) {
dispatch(slice.actions.hasError(error));
}
};
}

@ -0,0 +1,315 @@
export default function componentStyleOverrides(theme, borderRadius, outlinedFilled) {
const mode = theme.palette.mode;
const bgColor = mode === 'dark' ? theme.palette.dark[800] : theme.palette.grey[50];
const menuSelectedBack = mode === 'dark' ? theme.palette.secondary.main + 15 : theme.palette.secondary.light;
const menuSelected = mode === 'dark' ? theme.palette.secondary.main : theme.palette.secondary.dark;
return {
MuiButton: {
styleOverrides: {
root: {
fontWeight: 500,
borderRadius: '4px'
}
}
},
MuiPaper: {
defaultProps: {
elevation: 0
},
styleOverrides: {
root: {
backgroundImage: 'none'
},
rounded: {
borderRadius: `${borderRadius}px`
}
}
},
MuiCardHeader: {
styleOverrides: {
root: {
color: theme.palette.text.dark,
padding: '24px'
},
title: {
fontSize: '1.125rem'
}
}
},
MuiCardContent: {
styleOverrides: {
root: {
padding: '24px'
}
}
},
MuiCardActions: {
styleOverrides: {
root: {
padding: '24px'
}
}
},
MuiAlert: {
styleOverrides: {
root: {
alignItems: 'center'
},
outlined: {
border: '1px dashed'
}
}
},
MuiListItemButton: {
styleOverrides: {
root: {
color: theme.palette.text.primary,
paddingTop: '10px',
paddingBottom: '10px',
'&.Mui-selected': {
color: menuSelected,
backgroundColor: menuSelectedBack,
'&:hover': {
backgroundColor: menuSelectedBack
},
'& .MuiListItemIcon-root': {
color: menuSelected
}
},
'&:hover': {
backgroundColor: menuSelectedBack,
color: menuSelected,
'& .MuiListItemIcon-root': {
color: menuSelected
}
}
}
}
},
MuiListItemIcon: {
styleOverrides: {
root: {
color: theme.palette.text.primary,
minWidth: '36px'
}
}
},
MuiListItemText: {
styleOverrides: {
primary: {
color: theme.palette.text.dark
}
}
},
MuiInputBase: {
styleOverrides: {
input: {
color: theme.palette.text.dark,
'&::placeholder': {
color: theme.palette.text.secondary,
fontSize: '0.875rem'
}
}
}
},
MuiOutlinedInput: {
styleOverrides: {
root: {
background: outlinedFilled ? bgColor : 'transparent',
borderRadius: `${borderRadius}px`,
'& .MuiOutlinedInput-notchedOutline': {
borderColor: mode === 'dark' ? theme.palette.text.primary + 28 : theme.palette.grey[400]
},
'&:hover $notchedOutline': {
borderColor: theme.palette.primary.light
},
'&.MuiInputBase-multiline': {
padding: 1
}
},
input: {
fontWeight: 500,
background: outlinedFilled ? bgColor : 'transparent',
padding: '15.5px 14px',
borderRadius: `${borderRadius}px`,
'&.MuiInputBase-inputSizeSmall': {
padding: '10px 14px',
'&.MuiInputBase-inputAdornedStart': {
paddingLeft: 0
}
}
},
inputAdornedStart: {
paddingLeft: 4
},
notchedOutline: {
borderRadius: `${borderRadius}px`
}
}
},
MuiSlider: {
styleOverrides: {
root: {
'&.Mui-disabled': {
color: mode === 'dark' ? theme.palette.text.primary + 50 : theme.palette.grey[300]
}
},
mark: {
backgroundColor: theme.palette.background.paper,
width: '4px'
},
valueLabel: {
color: mode === 'dark' ? theme.palette.primary.main : theme.palette.primary.light
}
}
},
MuiAutocomplete: {
styleOverrides: {
root: {
'& .MuiAutocomplete-tag': {
background: mode === 'dark' ? theme.palette.text.primary + 20 : theme.palette.secondary.light,
borderRadius: 4,
color: theme.palette.text.dark,
'.MuiChip-deleteIcon': {
color: mode === 'dark' ? theme.palette.text.primary + 80 : theme.palette.secondary[200]
}
}
},
popper: {
borderRadius: `${borderRadius}px`,
boxShadow: '0px 8px 10px -5px rgb(0 0 0 / 20%), 0px 16px 24px 2px rgb(0 0 0 / 14%), 0px 6px 30px 5px rgb(0 0 0 / 12%)'
}
}
},
MuiDivider: {
styleOverrides: {
root: {
borderColor: theme.palette.divider,
opacity: mode === 'dark' ? 0.2 : 1
}
}
},
MuiSelect: {
styleOverrides: {
select: {
'&:focus': {
backgroundColor: 'transparent'
}
}
}
},
MuiCheckbox: {
styleOverrides: {
root: {
/** checked not prop
*"&.Mui-checked": {
* fontSize: "28px"
*}
*/
}
}
},
MuiAvatar: {
styleOverrides: {
root: {
color: mode === 'dark' ? theme.palette.dark.main : theme.palette.primary.dark,
background: mode === 'dark' ? theme.palette.text.primary : theme.palette.primary[200]
}
}
},
MuiChip: {
styleOverrides: {
root: {
'&.MuiChip-deletable .MuiChip-deleteIcon': {
color: 'inherit'
}
}
}
},
MuiTimelineContent: {
styleOverrides: {
root: {
color: theme.palette.text.dark,
fontSize: '16px'
}
}
},
MuiTreeItem: {
styleOverrides: {
label: {
marginTop: 14,
marginBottom: 14
}
}
},
MuiTimelineDot: {
styleOverrides: {
root: {
boxShadow: 'none'
}
}
},
MuiInternalDateTimePickerTabs: {
styleOverrides: {
tabs: {
backgroundColor: mode === 'dark' ? theme.palette.dark[900] : theme.palette.primary.light,
'& .MuiTabs-flexContainer': {
borderColor: mode === 'dark' ? theme.palette.text.primary + 20 : theme.palette.primary[200]
},
'& .MuiTab-root': {
color: mode === 'dark' ? theme.palette.text.secondary : theme.palette.grey[900]
},
'& .MuiTabs-indicator': {
backgroundColor: theme.palette.primary.dark
},
'& .Mui-selected': {
color: theme.palette.primary.dark
}
}
}
},
MuiTabs: {
styleOverrides: {
flexContainer: {
borderBottom: '1px solid',
borderColor: mode === 'dark' ? theme.palette.text.primary + 20 : theme.palette.grey[200]
}
}
},
MuiDialog: {
styleOverrides: {
paper: {
padding: '12px 0 12px 0'
}
}
},
MuiTableCell: {
styleOverrides: {
root: {
borderColor: mode === 'dark' ? theme.palette.text.primary + 15 : theme.palette.grey[200],
'&.MuiTableCell-head': {
fontSize: '0.875rem',
color: theme.palette.grey[600],
fontWeight: 500
}
}
}
},
MuiTooltip: {
styleOverrides: {
tooltip: {
color: theme.palette.background.paper,
background: theme.palette.text.primary
}
}
},
MuiDialogTitle: {
styleOverrides: {
root: {
fontSize: '1.25rem'
}
}
}
};
}

@ -0,0 +1,59 @@
import PropTypes from 'prop-types';
import { useMemo } from 'react';
// material-ui
import { CssBaseline, StyledEngineProvider } from '@mui/material';
import { createTheme, ThemeProvider } from '@mui/material/styles';
// project import
import useConfig from 'hooks/useConfig';
import Palette from './palette';
import Typography from './typography';
import componentStyleOverrides from './compStyleOverride';
import customShadows from './shadows';
export default function ThemeCustomization({ children }) {
const { borderRadius, fontFamily, navType, outlinedFilled, presetColor, rtlLayout } = useConfig();
const theme = useMemo(() => Palette(navType, presetColor), [navType, presetColor]);
// eslint-disable-next-line react-hooks/exhaustive-deps
const themeTypography = useMemo(() => Typography(theme, borderRadius, fontFamily), [theme, borderRadius, fontFamily]);
const themeCustomShadows = useMemo(() => customShadows(navType, theme), [navType, theme]);
const themeOptions = useMemo(
() => ({
direction: rtlLayout ? 'rtl' : 'ltr',
palette: theme.palette,
mixins: {
toolbar: {
minHeight: '48px',
padding: '16px',
'@media (min-width: 600px)': {
minHeight: '48px'
}
}
},
typography: themeTypography,
customShadows: themeCustomShadows
}),
[rtlLayout, theme, themeCustomShadows, themeTypography]
);
const themes = createTheme(themeOptions);
themes.components = useMemo(() => componentStyleOverrides(themes, borderRadius, outlinedFilled), [themes, borderRadius, outlinedFilled]);
return (
<StyledEngineProvider injectFirst>
<ThemeProvider theme={themes}>
<CssBaseline />
{children}
</ThemeProvider>
</StyledEngineProvider>
);
}
ThemeCustomization.propTypes = {
children: PropTypes.node
};

@ -0,0 +1,112 @@
// material-ui
import { createTheme } from '@mui/material/styles';
// assets
import defaultColor from 'assets/scss/_themes-vars.module.scss';
import theme1 from 'assets/scss/_theme1.module.scss';
import theme2 from 'assets/scss/_theme2.module.scss';
import theme3 from 'assets/scss/_theme3.module.scss';
import theme4 from 'assets/scss/_theme4.module.scss';
import theme5 from 'assets/scss/_theme5.module.scss';
import theme6 from 'assets/scss/_theme6.module.scss';
// ==============================|| DEFAULT THEME - PALETTE ||============================== //
const Palette = (navType, presetColor) => {
let colors;
switch (presetColor) {
case 'theme1':
colors = theme1;
break;
case 'theme2':
colors = theme2;
break;
case 'theme3':
colors = theme3;
break;
case 'theme4':
colors = theme4;
break;
case 'theme5':
colors = theme5;
break;
case 'theme6':
colors = theme6;
break;
case 'default':
default:
colors = defaultColor;
}
return createTheme({
palette: {
mode: navType,
common: {
black: colors.darkPaper
},
primary: {
light: navType === 'dark' ? colors.darkPrimaryLight : colors.primaryLight,
main: navType === 'dark' ? colors.darkPrimaryMain : colors.primaryMain,
dark: navType === 'dark' ? colors.darkPrimaryDark : colors.primaryDark,
200: navType === 'dark' ? colors.darkPrimary200 : colors.primary200,
800: navType === 'dark' ? colors.darkPrimary800 : colors.primary800
},
secondary: {
light: navType === 'dark' ? colors.darkSecondaryLight : colors.secondaryLight,
main: navType === 'dark' ? colors.darkSecondaryMain : colors.secondaryMain,
dark: navType === 'dark' ? colors.darkSecondaryDark : colors.secondaryDark,
200: navType === 'dark' ? colors.darkSecondary200 : colors.secondary200,
800: navType === 'dark' ? colors.darkSecondary800 : colors.secondary800
},
error: {
light: colors.errorLight,
main: colors.errorMain,
dark: colors.errorDark
},
orange: {
light: colors.orangeLight,
main: colors.orangeMain,
dark: colors.orangeDark
},
warning: {
light: colors.warningLight,
main: colors.warningMain,
dark: colors.warningDark
},
success: {
light: colors.successLight,
200: colors.success200,
main: colors.successMain,
dark: colors.successDark
},
grey: {
50: colors.grey50,
100: colors.grey100,
500: navType === 'dark' ? colors.darkTextSecondary : colors.grey500,
600: navType === 'dark' ? colors.darkTextTitle : colors.grey900,
700: navType === 'dark' ? colors.darkTextPrimary : colors.grey700,
900: navType === 'dark' ? colors.darkTextPrimary : colors.grey900
},
dark: {
light: colors.darkTextPrimary,
main: colors.darkLevel1,
dark: colors.darkLevel2,
800: colors.darkBackground,
900: colors.darkPaper
},
text: {
primary: navType === 'dark' ? colors.darkTextPrimary : colors.grey700,
secondary: navType === 'dark' ? colors.darkTextSecondary : colors.grey500,
dark: navType === 'dark' ? colors.darkTextPrimary : colors.grey900,
hint: colors.grey100
},
divider: navType === 'dark' ? colors.darkTextPrimary : colors.grey200,
background: {
paper: navType === 'dark' ? colors.darkLevel2 : colors.paper,
default: navType === 'dark' ? colors.darkPaper : colors.paper
}
}
});
};
export default Palette;

@ -0,0 +1,24 @@
import { alpha } from '@mui/material/styles';
const createCustomShadow = (theme, color) => {
const transparent = alpha(color, 0.24);
return {
z1: `0 1px 2px 0 ${transparent}`,
z8: `0 8px 16px 0 ${transparent}`,
z12: `0 12px 24px 0 ${transparent} 0 10px 20px 0 ${transparent}`,
z16: `0 0 3px 0 ${transparent} 0 14px 28px -5px ${transparent}`,
z20: `0 0 3px 0 ${transparent} 0 18px 36px -5px ${transparent}`,
z24: `0 0 6px 0 ${transparent} 0 21px 44px 0 ${transparent}`,
primary: `0px 12px 14px 0px ${alpha(theme.palette.primary.main, 0.3)}`,
secondary: `0px 12px 14px 0px ${alpha(theme.palette.secondary.main, 0.3)}`,
orange: `0px 12px 14px 0px ${alpha(theme.palette.orange.main, 0.3)}`,
success: `0px 12px 14px 0px ${alpha(theme.palette.success.main, 0.3)}`,
warning: `0px 12px 14px 0px ${alpha(theme.palette.warning.main, 0.3)}`,
error: `0px 12px 14px 0px ${alpha(theme.palette.error.main, 0.3)}`
};
};
export default function customShadows(navType, theme) {
return navType === 'dark' ? createCustomShadow(theme, theme.palette.dark.main) : createCustomShadow(theme, theme.palette.grey[600]);
}

@ -0,0 +1,128 @@
const Typography = (theme, borderRadius, fontFamily) => ({
fontFamily,
h6: {
fontWeight: 500,
color: theme.palette.grey[600],
fontSize: '0.75rem'
},
h5: {
fontSize: '0.875rem',
color: theme.palette.grey[600],
fontWeight: 500
},
h4: {
fontSize: '1rem',
color: theme.palette.grey[600],
fontWeight: 600
},
h3: {
fontSize: '1.25rem',
color: theme.palette.grey[600],
fontWeight: 600
},
h2: {
fontSize: '1.5rem',
color: theme.palette.grey[600],
fontWeight: 700
},
h1: {
fontSize: '2.125rem',
color: theme.palette.grey[600],
fontWeight: 700
},
subtitle1: {
fontSize: '0.875rem',
fontWeight: 500,
color: theme.palette.text.dark
},
subtitle2: {
fontSize: '0.75rem',
fontWeight: 400,
color: theme.palette.text.secondary
},
caption: {
fontSize: '0.75rem',
color: theme.palette.text.secondary,
fontWeight: 400
},
body1: {
fontSize: '0.875rem',
fontWeight: 400,
lineHeight: '1.334em'
},
body2: {
letterSpacing: '0em',
fontWeight: 400,
lineHeight: '1.5em',
color: theme.palette.text.primary
},
button: {
textTransform: 'capitalize'
},
customInput: {
marginTop: 1,
marginBottom: 1,
'& > label': {
top: 23,
left: 0,
color: theme.palette.grey[500],
'&[data-shrink="false"]': {
top: 5
}
},
'& > div > input': {
padding: '30.5px 14px 11.5px !important'
},
'& legend': {
display: 'none'
},
'& fieldset': {
top: 0
}
},
mainContent: {
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.dark[800] : theme.palette.primary.light,
width: '100%',
minHeight: 'calc(100vh - 88px)',
flexGrow: 1,
padding: '20px',
marginTop: '88px',
marginRight: '20px',
borderRadius: `${borderRadius}px`
},
menuCaption: {
fontSize: '0.875rem',
fontWeight: 500,
color: theme.palette.grey[600],
padding: '6px',
textTransform: 'capitalize',
marginTop: '10px'
},
subMenuCaption: {
fontSize: '0.6875rem',
fontWeight: 500,
color: theme.palette.text.secondary,
textTransform: 'capitalize'
},
commonAvatar: {
cursor: 'pointer',
borderRadius: '8px'
},
smallAvatar: {
width: '22px',
height: '22px',
fontSize: '1rem'
},
mediumAvatar: {
width: '34px',
height: '34px',
fontSize: '1.2rem'
},
largeAvatar: {
width: '44px',
height: '44px',
fontSize: '1.5rem'
}
});
export default Typography;

@ -0,0 +1,15 @@
import { Suspense } from 'react';
// project imports
import Loader from './Loader';
// ==============================|| LOADABLE - LAZY LOADING ||============================== //
const Loadable = (Component) => (props) =>
(
<Suspense fallback={<Loader />}>
<Component {...props} />
</Suspense>
);
export default Loadable;

@ -0,0 +1,22 @@
// material-ui
import LinearProgress from '@mui/material/LinearProgress';
import { styled } from '@mui/material/styles';
// styles
const LoaderWrapper = styled('div')({
position: 'fixed',
top: 0,
left: 0,
zIndex: 1301,
width: '100%'
});
// ==============================|| LOADER ||============================== //
const Loader = () => (
<LoaderWrapper>
<LinearProgress color="primary" />
</LoaderWrapper>
);
export default Loader;

@ -0,0 +1,49 @@
import PropTypes from 'prop-types';
import { useState, useEffect } from 'react';
// third-party
import { IntlProvider } from 'react-intl';
import useConfig from 'hooks/useConfig';
// load locales files
const loadLocaleData = (locale) => {
switch (locale) {
case 'fr':
return import('utils/locales/fr.json');
case 'ro':
return import('utils/locales/ro.json');
case 'zh':
return import('utils/locales/zh.json');
default:
return import('utils/locales/en.json');
}
};
// ==============================|| LOCALIZATION ||============================== //
const Locales = ({ children }) => {
const { locale } = useConfig();
const [messages, setMessages] = useState();
useEffect(() => {
loadLocaleData(locale).then((d) => {
setMessages(d.default);
});
}, [locale]);
return (
<>
{messages && (
<IntlProvider locale={locale} defaultLocale="en" messages={messages}>
{children}
</IntlProvider>
)}
</>
);
};
Locales.propTypes = {
children: PropTypes.node
};
export default Locales;

@ -0,0 +1,69 @@
// material-ui
import { useTheme } from '@mui/material/styles';
/**
* if you want to use image instead of <svg> uncomment following.
*
* import logoDark from 'assets/images/logo-dark.svg';
* import logo from 'assets/images/logo.svg';
*
*/
// ==============================|| LOGO SVG ||============================== //
const Logo = () => {
const theme = useTheme();
return (
/**
* if you want to use image instead of svg uncomment following, and comment out <svg> element.
*
* <img src={theme.palette.mode === 'dark' ? logoDark : logo} alt="Berry" width="100" />
*
*/
<svg width="92" height="32" viewBox="0 0 92 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M33.085 26.4841V12.3839H37.9541C39.6408 12.3839 40.9202 12.7131 41.7922 13.3717C42.6642 14.0237 43.1002 14.9825 43.1002 16.2478C43.1002 16.9387 42.9251 17.5488 42.5751 18.0782C42.225 18.6011 41.7381 18.9853 41.1143 19.2306C41.8272 19.4114 42.3873 19.7761 42.7947 20.3249C43.2084 20.8737 43.4152 21.5452 43.4152 22.3392C43.4152 23.695 42.9888 24.7215 42.1359 25.4188C41.283 26.1161 40.0673 26.4712 38.4888 26.4841H33.085ZM35.9492 20.3443V24.1502H38.4028C39.0775 24.1502 39.6026 23.9888 39.9781 23.666C40.36 23.3367 40.551 22.8848 40.551 22.3102C40.551 21.0189 39.8922 20.3637 38.5747 20.3443H35.9492ZM35.9492 18.2912H38.0687C39.5135 18.2654 40.236 17.6811 40.236 16.5384C40.236 15.8992 40.0514 15.4408 39.6822 15.1632C39.3194 14.8792 38.7434 14.7371 37.9541 14.7371H35.9492V18.2912ZM53.9365 20.3733H48.4371V24.1502H54.8913V26.4841H45.573V12.3839H54.8723V14.7371H48.4371V18.0976H53.9365V20.3733ZM61.7175 21.3224H59.436V26.4841H56.5717V12.3839H61.7365C63.379 12.3839 64.6455 12.7551 65.5365 13.4975C66.4276 14.24 66.8734 15.2891 66.8734 16.6449C66.8734 17.6069 66.6661 18.4107 66.2527 19.0563C65.8455 19.6954 65.2248 20.2055 64.3907 20.5864L67.3985 26.3485V26.4841H64.3242L61.7175 21.3224ZM59.436 18.9691H61.746C62.4656 18.9691 63.0226 18.7851 63.417 18.4172C63.8114 18.0427 64.0092 17.5294 64.0092 16.8773C64.0092 16.2124 63.8214 15.6894 63.4455 15.3085C63.0768 14.9276 62.5069 14.7371 61.7365 14.7371H59.436V18.9691ZM74.2058 21.3224H71.9237V26.4841H69.0594V12.3839H74.2248C75.8667 12.3839 77.1337 12.7551 78.0248 13.4975C78.9159 14.24 79.3611 15.2891 79.3611 16.6449C79.3611 17.6069 79.1544 18.4107 78.7404 19.0563C78.3332 19.6954 77.7125 20.2055 76.879 20.5864L79.8863 26.3485V26.4841H76.8119L74.2058 21.3224ZM71.9237 18.9691H74.2343C74.9533 18.9691 75.5103 18.7851 75.9052 18.4172C76.2997 18.0427 76.4969 17.5294 76.4969 16.8773C76.4969 16.2124 76.3092 15.6894 75.9337 15.3085C75.5645 14.9276 74.9946 14.7371 74.2248 14.7371H71.9237V18.9691ZM85.8823 18.7367L88.7751 12.3839H91.9064L87.3427 21.3708V26.4841H84.4309V21.3708L79.8673 12.3839H83.008L85.8823 18.7367Z"
fill={theme.palette.mode === 'dark' ? theme.palette.common.white : theme.palette.grey[900]}
/>
<path
d="M10.987 31.5841C4.92849 31.5841 0 26.626 0 20.5323C0 14.4385 4.92899 9.48041 10.987 9.48041C17.045 9.48041 21.974 14.4385 21.974 20.5323C21.974 26.626 17.0459 31.5841 10.987 31.5841ZM10.987 10.536C5.50765 10.536 1.04938 15.0196 1.04938 20.5318C1.04938 26.044 5.50765 30.5275 10.987 30.5275C16.4663 30.5275 20.9251 26.0429 20.9251 20.5308C20.9251 15.0186 16.4673 10.536 10.987 10.536Z"
fill={theme.palette.primary.main}
/>
<path
d="M18.96 21.0225C18.6182 19.7483 15.4851 19.6108 13.6203 20.0779C12.6437 20.3235 11.6456 20.6428 10.6162 20.8265C11.3697 21.4989 12.1788 22.135 13.34 22.2932C16.2211 22.6842 18.0112 21.775 18.96 21.0225Z"
fill={theme.palette.primary.main}
/>
<path
d="M13.34 22.2932C12.1764 22.135 11.3697 21.4989 10.6162 20.8265C9.45013 19.7857 8.41298 18.6579 6.37723 19.0823C3.14069 19.7572 2.71488 23.6081 5.21404 26.0828C6.28706 27.2131 7.66455 28.0041 9.17779 28.3586C10.691 28.7132 12.2742 28.616 13.7333 28.079C15.1924 27.5419 16.4641 26.5883 17.3925 25.3352C18.3209 24.0819 18.8656 22.5835 18.96 21.0235C18.0112 21.775 16.221 22.6842 13.34 22.2932Z"
fill={theme.palette.secondary.main}
/>
<path
d="M15.034 13.9586C14.6301 14.8295 18.2304 15.7957 18.6611 18.6879C18.8687 15.8409 15.5335 12.882 15.034 13.9586Z"
fill={theme.palette.primary.main}
/>
<path
d="M7.46619 17.5935C8.11524 17.3231 8.42345 16.5746 8.15463 15.9217C7.8858 15.2688 7.14167 14.9587 6.49262 15.2292C5.84357 15.4996 5.53536 16.2481 5.80418 16.9011C6.07306 17.5539 6.81714 17.8639 7.46619 17.5935Z"
fill={theme.palette.secondary.main}
/>
<path
d="M10.3549 14.08C10.6585 13.7746 10.6585 13.2795 10.3549 12.9741C10.0513 12.6687 9.55909 12.6687 9.25551 12.9741C8.95194 13.2795 8.95194 13.7746 9.25551 14.08C9.55909 14.3854 10.0513 14.3854 10.3549 14.08Z"
fill={theme.palette.primary.main}
/>
<path
d="M13.1014 9.05206C14.2245 5.7149 13.4696 3.04871 11.1614 1.78241C9.58359 2.10513 8.647 2.87335 8.12549 3.93383C11.2204 3.68185 13.1844 5.63041 13.1014 9.05206Z"
fill={theme.palette.primary.main}
/>
<path
d="M25.6983 6.13641C20.1389 4.1294 16.6304 4.81756 16.0786 9.39055C19.2648 12.6973 22.474 11.1146 25.6983 6.13641Z"
fill={theme.palette.primary.main}
/>
<path
d="M21.2765 4.32541C21.5343 3.21728 21.6681 1.90776 21.6881 0.41748C15.9226 1.70883 13.3224 4.17658 15.2839 8.33846C15.3816 8.36203 15.4754 8.38119 15.5696 8.40085C16.0281 5.14422 18.0463 3.93835 21.2765 4.32541Z"
fill={theme.palette.primary.main}
/>
</svg>
);
};
export default Logo;

@ -0,0 +1,34 @@
import PropTypes from 'prop-types';
import { useEffect } from 'react';
// material-ui
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
// third-party
import rtlPlugin from 'stylis-plugin-rtl';
import useConfig from 'hooks/useConfig';
// ==============================|| RTL LAYOUT ||============================== //
const RTLLayout = ({ children }) => {
const { rtlLayout } = useConfig();
useEffect(() => {
document.dir = rtlLayout ? 'rtl' : 'ltr';
}, [rtlLayout]);
const cacheRtl = createCache({
key: rtlLayout ? 'rtl' : 'css',
prepend: true,
stylisPlugins: rtlLayout ? [rtlPlugin] : []
});
return <CacheProvider value={cacheRtl}>{children}</CacheProvider>;
};
RTLLayout.propTypes = {
children: PropTypes.node
};
export default RTLLayout;

@ -0,0 +1,127 @@
import PropTypes from 'prop-types';
import { useState } from 'react';
// material-ui
import { Box, Button, Grid, Menu, MenuItem, Typography } from '@mui/material';
// third party
import Chart from 'react-apexcharts';
// project imports
import MainCard from './MainCard';
// assets
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
// ==========================|| ANALYTICS CHART CARD ||========================== //
const AnalyticsChartCard = ({ title, chartData, dropData, listData }) => {
const [anchorEl, setAnchorEl] = useState(null);
let dropHtml;
if (dropData) {
const handleClick = (event) => {
setAnchorEl(event?.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
dropHtml = (
<>
<Button variant="text" disableElevation size="small" aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
{dropData.title}
</Button>
<Menu
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right'
}}
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
{dropData?.options.map((option, index) => (
<MenuItem key={index} onClick={handleClose}>
{option.label}
</MenuItem>
))}
</Menu>
</>
);
}
let listItem;
if (listData) {
listItem = listData.map((item, index) => (
<Grid item key={index} sm={12}>
<Box
sx={{
color: item.color
}}
>
<Grid container spacing={2} justifyContent="center">
<Grid item>{item.icon}</Grid>
<Grid item>
<Typography variant="subtitle1">{item.value}%</Typography>
</Grid>
<Grid item>
{item.state === 1 && <ArrowUpwardIcon fontSize="inherit" color="inherit" />}
{item.state === 0 && <ArrowDownwardIcon fontSize="inherit" color="inherit" />}
</Grid>
<Grid item>
<Typography variant="subtitle1" color="inherit">
{item.percentage}%
</Typography>
</Grid>
</Grid>
</Box>
</Grid>
));
}
return (
<MainCard>
<Grid container justifyContent="space-between" alignItems="center">
{title && (
<Grid item>
<Typography variant="subtitle1">{title}</Typography>
</Grid>
)}
<Grid item>{dropHtml}</Grid>
</Grid>
<Grid container justifyContent="center" alignItems="center">
<Grid item container direction="column" spacing={1} xs={12} sm={6}>
<Box
sx={{
mt: 3,
display: 'block'
}}
>
{listItem}
</Box>
</Grid>
<Grid item xs={12} sm={6}>
<Chart {...chartData} />
</Grid>
</Grid>
</MainCard>
);
};
AnalyticsChartCard.propTypes = {
title: PropTypes.string,
chartData: PropTypes.object,
dropData: PropTypes.object,
listData: PropTypes.array
};
export default AnalyticsChartCard;

@ -0,0 +1,43 @@
import PropTypes from 'prop-types';
// material-ui
import { useTheme } from '@mui/material/styles';
import { Card, CardContent, CardMedia, Grid, Typography } from '@mui/material';
import { gridSpacing } from 'store/constant';
// assets
import DownloadForOfflineTwoToneIcon from '@mui/icons-material/DownloadForOfflineTwoTone';
const backImage = require.context('assets/images/profile', true);
// ==============================|| ATTACHMENT CARD ||============================== //
const AttachmentCard = ({ title, image }) => {
const theme = useTheme();
const backProfile = image && backImage(`./${image}`).default;
return (
<Card sx={{ bgcolor: theme.palette.mode === 'dark' ? 'dark.dark' : 'grey.100' }}>
<CardMedia component="img" image={backProfile} title="Slider5 image" />
<CardContent sx={{ p: 2, pb: '16px !important' }}>
<Grid container spacing={gridSpacing}>
<Grid item xs zeroMinWidth>
<Typography variant="h5" component="div" sx={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{title}
</Typography>
</Grid>
<Grid item>
<DownloadForOfflineTwoToneIcon sx={{ cursor: 'pointer' }} />
</Grid>
</Grid>
</CardContent>
</Card>
);
};
AttachmentCard.propTypes = {
image: PropTypes.string,
title: PropTypes.oneOfType([PropTypes.node, PropTypes.string, PropTypes.object])
};
export default AttachmentCard;

@ -0,0 +1,17 @@
// material-ui
import { Link, Typography, Stack } from '@mui/material';
// ==============================|| FOOTER - AUTHENTICATION 2 & 3 ||============================== //
const AuthFooter = () => (
<Stack direction="row" justifyContent="space-between">
<Typography variant="subtitle2" component={Link} href="https://berrydashboard.io" target="_blank" underline="hover">
berrydashboard.io
</Typography>
<Typography variant="subtitle2" component={Link} href="https://codedthemes.com" target="_blank" underline="hover">
&copy; codedthemes.com
</Typography>
</Stack>
);
export default AuthFooter;

@ -0,0 +1,40 @@
import PropTypes from 'prop-types';
// material-ui
import { Grid, Typography } from '@mui/material';
// third-party
import Slider from 'react-slick';
const AuthSlider = ({ items }) => {
const settings = {
autoplay: true,
arrows: false,
dots: true,
infinite: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1
};
return (
<Slider {...settings}>
{items.map((item, i) => (
<Grid key={i} container direction="column" alignItems="center" spacing={3} textAlign="center">
<Grid item>
<Typography variant="h1">{item.title}</Typography>
</Grid>
<Grid item>
<Typography variant="subtitle2">{item.description}</Typography>
</Grid>
</Grid>
))}
</Slider>
);
};
AuthSlider.propTypes = {
items: PropTypes.array.isRequired
};
export default AuthSlider;

@ -0,0 +1,43 @@
import PropTypes from 'prop-types';
// material-ui
import { useTheme } from '@mui/material/styles';
import { Box } from '@mui/material';
// assets
import AuthPattern from 'assets/images/auth/auth-pattern.svg';
import AuthPatternDark from 'assets/images/auth/auth-pattern-dark.svg';
// ===========================|| BACKGROUND GRID PATTERN 1 ||=========================== //
const BackgroundPattern1 = ({ children }) => {
const theme = useTheme();
return (
<Box
component="span"
sx={{
display: 'flex',
minHeight: '100vh',
bgcolor: theme.palette.mode === 'dark' ? theme.palette.dark.dark : '#fff',
backgroundImage: theme.palette.mode === 'dark' ? `url(${AuthPatternDark})` : `url(${AuthPattern})`,
position: 'absolute',
backgroundPosition: '0 0',
overflow: 'hidden',
m: '0 0 0 auto',
top: 0,
left: 0,
right: 0,
bottom: 0,
opacity: theme.palette.mode === 'dark' ? 0.85 : 0.9
}}
>
{children}
</Box>
);
};
BackgroundPattern1.propTypes = {
children: PropTypes.node
};
export default BackgroundPattern1;

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

Loading…
Cancel
Save