├── .env ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md └── workflows │ └── prod.yml ├── .gitignore ├── .prettierrc ├── .yarnrc.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── eslint.config.mjs ├── favicon.svg ├── index.html ├── jsconfig.json ├── jsconfig.node.json ├── package.json ├── src ├── App.jsx ├── api │ └── menu.js ├── assets │ ├── images │ │ └── users │ │ │ ├── avatar-1.png │ │ │ ├── avatar-2.png │ │ │ ├── avatar-3.png │ │ │ ├── avatar-4.png │ │ │ ├── avatar-5.png │ │ │ └── avatar-group.png │ ├── style.css │ └── third-party │ │ ├── apex-chart.css │ │ └── react-table.css ├── components │ ├── @extended │ │ ├── AnimateButton.jsx │ │ ├── Avatar.jsx │ │ ├── Breadcrumbs.jsx │ │ ├── Dot.jsx │ │ ├── IconButton.jsx │ │ └── Transitions.jsx │ ├── Loadable.jsx │ ├── Loader.jsx │ ├── MainCard.jsx │ ├── ScrollTop.jsx │ ├── cards │ │ ├── AuthFooter.jsx │ │ └── statistics │ │ │ └── AnalyticEcommerce.jsx │ ├── logo │ │ ├── LogoIcon.jsx │ │ ├── LogoMain.jsx │ │ └── index.jsx │ └── third-party │ │ └── SimpleBar.jsx ├── config.js ├── contexts │ └── README.md ├── data │ └── README.md ├── hooks │ └── README.md ├── index.jsx ├── layout │ ├── Auth │ │ └── index.jsx │ └── Dashboard │ │ ├── Drawer │ │ ├── DrawerContent │ │ │ ├── NavCard.jsx │ │ │ ├── Navigation │ │ │ │ ├── NavGroup.jsx │ │ │ │ ├── NavItem.jsx │ │ │ │ └── index.jsx │ │ │ └── index.jsx │ │ ├── DrawerHeader │ │ │ ├── DrawerHeaderStyled.js │ │ │ └── index.jsx │ │ ├── MiniDrawerStyled.js │ │ └── index.jsx │ │ ├── Footer.jsx │ │ ├── Header │ │ ├── AppBarStyled.jsx │ │ ├── HeaderContent │ │ │ ├── MobileSection.jsx │ │ │ ├── Notification.jsx │ │ │ ├── Profile │ │ │ │ ├── ProfileTab.jsx │ │ │ │ ├── SettingTab.jsx │ │ │ │ └── index.jsx │ │ │ ├── Search.jsx │ │ │ └── index.jsx │ │ └── index.jsx │ │ └── index.jsx ├── menu-items │ ├── dashboard.jsx │ ├── index.jsx │ ├── page.jsx │ ├── support.jsx │ └── utilities.jsx ├── pages │ ├── auth │ │ ├── Login.jsx │ │ └── Register.jsx │ ├── component-overview │ │ ├── color.jsx │ │ ├── shadows.jsx │ │ └── typography.jsx │ ├── dashboard │ │ └── default.jsx │ └── extra-pages │ │ └── sample-page.jsx ├── reportWebVitals.js ├── routes │ ├── LoginRoutes.jsx │ ├── MainRoutes.jsx │ └── index.jsx ├── sections │ ├── auth │ │ ├── AuthBackground.jsx │ │ ├── AuthCard.jsx │ │ ├── AuthLogin.jsx │ │ ├── AuthRegister.jsx │ │ └── AuthWrapper.jsx │ └── dashboard │ │ ├── SalesChart.jsx │ │ └── default │ │ ├── IncomeAreaChart.jsx │ │ ├── MonthlyBarChart.jsx │ │ ├── OrdersTable.jsx │ │ ├── ReportAreaChart.jsx │ │ ├── SaleReportCard.jsx │ │ └── UniqueVisitorCard.jsx ├── themes │ ├── index.jsx │ ├── overrides │ │ ├── Badge.js │ │ ├── Button.js │ │ ├── ButtonBase.js │ │ ├── CardContent.js │ │ ├── Checkbox.jsx │ │ ├── Chip.js │ │ ├── Drawer.js │ │ ├── FormHelperText.js │ │ ├── IconButton.js │ │ ├── InputLabel.js │ │ ├── LinearProgress.js │ │ ├── Link.js │ │ ├── ListItemButton.jsx │ │ ├── ListItemIcon.jsx │ │ ├── OutlinedInput.js │ │ ├── Tab.js │ │ ├── TableBody.js │ │ ├── TableCell.js │ │ ├── TableHead.js │ │ ├── TableRow.js │ │ ├── Tabs.js │ │ ├── Tooltip.js │ │ ├── Typography.js │ │ └── index.js │ ├── palette.js │ ├── shadows.jsx │ ├── theme │ │ └── index.js │ └── typography.js ├── utils │ ├── getColors.js │ ├── getShadow.js │ ├── password-strength.js │ └── password-validation.js └── vite-env.d.js ├── vite.config.mjs └── yarn.lock /.env: -------------------------------------------------------------------------------- 1 | VITE_APP_VERSION = v1.5.0 2 | GENERATE_SOURCEMAP = false 3 | 4 | ## Public URL 5 | PUBLIC_URL = https://mantisdashboard.io 6 | VITE_APP_BASE_NAME = /free 7 | 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Version [e.g. 22] 31 | 32 | **Smartphone (please complete the following information):** 33 | 34 | - Device: [e.g. iPhone6] 35 | - OS: [e.g. iOS8.1] 36 | - Browser [e.g. stock browser, safari] 37 | - Version [e.g. 22] 38 | 39 | **Additional context** 40 | Add any other context about the problem here. 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/workflows/prod.yml: -------------------------------------------------------------------------------- 1 | name: Prod deploy 2 | 3 | # Controls when the action will run. 4 | on: 5 | # Triggers the workflow on push or pull request events but only for the master branch 6 | push: 7 | branches: 8 | - master 9 | pull_request: 10 | types: 11 | - closed 12 | branches: 13 | - master 14 | 15 | jobs: 16 | if_merged: 17 | if: github.event.pull_request.merged == true 18 | name: 🎉 Deploy 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: 🚚 Get latest code 23 | uses: actions/checkout@v4 24 | 25 | - name: Use Node.js 20 26 | uses: actions/setup-node@v4 27 | with: 28 | node-version: '20' 29 | 30 | - name: 🔨 Build Project 31 | run: | 32 | corepack enable 33 | yarn set version 4.6.0 34 | yarn 35 | yarn build 36 | 37 | - name: 📂 Deploy to Server 38 | uses: easingthemes/ssh-deploy@v4 39 | env: 40 | SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }} 41 | # ARGS: "-rltgoDzvO --delete" 42 | SOURCE: 'dist/' 43 | REMOTE_HOST: 192.34.62.123 44 | REMOTE_USER: mantis 45 | TARGET: public_html/free 46 | EXCLUDE: '/build/, /node_modules/' 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | build 40 | dist 41 | 42 | # Dependency directories 43 | node_modules/ 44 | jspm_packages/ 45 | 46 | # TypeScript v1 declaration files 47 | typings/ 48 | 49 | # TypeScript cache 50 | *.tsbuildinfo 51 | 52 | # Optional npm cache directory 53 | .npm 54 | 55 | # Optional eslint cache 56 | .eslintcache 57 | 58 | # Microbundle cache 59 | .rpt2_cache/ 60 | .rts2_cache_cjs/ 61 | .rts2_cache_es/ 62 | .rts2_cache_umd/ 63 | 64 | # Optional REPL history 65 | .node_repl_history 66 | 67 | # Output of 'npm pack' 68 | *.tgz 69 | 70 | # Yarn Integrity file 71 | .yarn-integrity 72 | .yarn 73 | 74 | # dotenv environment variables file 75 | # .env 76 | .env.test 77 | 78 | # parcel-bundler cache (https://parceljs.org/) 79 | .cache 80 | 81 | # Next.js build output 82 | .next 83 | 84 | # Nuxt.js build / generate output 85 | .nuxt 86 | dist 87 | 88 | # Gatsby files 89 | .cache/ 90 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 91 | # https://nextjs.org/blog/next-9-1#public-directory-support 92 | # public 93 | 94 | # vuepress build output 95 | .vuepress/dist 96 | 97 | # Serverless directories 98 | .serverless/ 99 | 100 | # FuseBox cache 101 | .fusebox/ 102 | 103 | # DynamoDB Local files 104 | .dynamodb/ 105 | 106 | # TernJS port file 107 | .tern-port 108 | 109 | # wincompare file 110 | .bak 111 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": true, 3 | "printWidth": 140, 4 | "singleQuote": true, 5 | "trailingComma": "none", 6 | "tabWidth": 2, 7 | "useTabs": false 8 | } 9 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | codedthemes@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 CodedThemes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { fixupConfigRules } from '@eslint/compat'; 2 | import prettier from 'eslint-plugin-prettier'; 3 | import react from 'eslint-plugin-react'; 4 | import reactHooks from 'eslint-plugin-react-hooks'; 5 | import jsxA11y from 'eslint-plugin-jsx-a11y'; 6 | import js from '@eslint/js'; 7 | import path from 'node:path'; 8 | import { fileURLToPath } from 'node:url'; 9 | import { FlatCompat } from '@eslint/eslintrc'; 10 | 11 | const __filename = fileURLToPath(import.meta.url); 12 | const __dirname = path.dirname(__filename); 13 | const compat = new FlatCompat({ 14 | baseDirectory: __dirname, 15 | recommendedConfig: js.configs.recommended, 16 | allConfig: js.configs.all 17 | }); 18 | 19 | export default [ 20 | ...fixupConfigRules(compat.extends('prettier')), 21 | 22 | { 23 | plugins: { 24 | prettier, 25 | react, 26 | 'react-hooks': reactHooks, 27 | 'jsx-a11y': jsxA11y 28 | }, 29 | 30 | languageOptions: { 31 | ecmaVersion: 2020, 32 | sourceType: 'module', 33 | parserOptions: { 34 | ecmaFeatures: { 35 | jsx: true // ✅ Enable JSX parsing 36 | } 37 | } 38 | }, 39 | 40 | settings: { 41 | react: { 42 | version: 'detect' // ✅ Detect the installed React version 43 | } 44 | }, 45 | 46 | rules: { 47 | 'react/jsx-filename-extension': ['error', { extensions: ['.js', '.jsx'] }], 48 | 'react/react-in-jsx-scope': 'off', 49 | 'react/prop-types': 'off', 50 | 'react/jsx-props-no-spreading': 'off', 51 | 'react-hooks/rules-of-hooks': 'error', 52 | 'react-hooks/exhaustive-deps': 'warn', 53 | 'jsx-a11y/label-has-associated-control': 'off', 54 | 'jsx-a11y/no-autofocus': 'off', 55 | 56 | 'prettier/prettier': [ 57 | 'warn', 58 | { 59 | bracketSpacing: true, 60 | printWidth: 140, 61 | singleQuote: true, 62 | trailingComma: 'none', 63 | tabWidth: 2, 64 | useTabs: false 65 | } 66 | ] 67 | } 68 | }, 69 | { 70 | ignores: ['node_modules/**'], 71 | files: ['src/**/*.{js,jsx}'] 72 | } 73 | ]; 74 | -------------------------------------------------------------------------------- /favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Mantis React Free Admin Dashboard 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx", 18 | "baseUrl": "src" 19 | }, 20 | "exclude": ["node_modules"], 21 | "include": ["src", "**/*.js", "**/*.jsx", "src/**/*"], 22 | "references": [{ "path": "./jsconfig.node.json" }] 23 | } 24 | -------------------------------------------------------------------------------- /jsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.mjs"] 9 | } 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mantis-material-free-react", 3 | "version": "1.5.0", 4 | "homepage": "https://mantisdashboard.io/free", 5 | "author": { 6 | "name": "CodedThemes", 7 | "email": "codedthemes@gmail.com", 8 | "url": "https://codedthemes.com/" 9 | }, 10 | "scripts": { 11 | "start": "vite", 12 | "build": "vite build", 13 | "build-stage": "env-cmd -f .env.qa vite build", 14 | "preview": "vite preview", 15 | "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", 16 | "lint:fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\"", 17 | "prettier": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"", 18 | "knip": "knip" 19 | }, 20 | "dependencies": { 21 | "@ant-design/colors": "8.0.0", 22 | "@ant-design/icons": "6.0.0", 23 | "@emotion/cache": "11.14.0", 24 | "@emotion/react": "11.14.0", 25 | "@emotion/styled": "11.14.0", 26 | "@fontsource/inter": "5.2.5", 27 | "@fontsource/poppins": "5.2.5", 28 | "@fontsource/public-sans": "5.2.5", 29 | "@fontsource/roboto": "5.2.5", 30 | "@mui/base": "5.0.0-beta.70", 31 | "@mui/lab": "7.0.0-beta.10", 32 | "@mui/material": "7.0.2", 33 | "@mui/system": "7.0.2", 34 | "@mui/x-charts": "8.1.0", 35 | "@vitejs/plugin-react": "4.4.1", 36 | "formik": "2.4.6", 37 | "framer-motion": "12.8.2", 38 | "lodash-es": "4.17.21", 39 | "react": "19.1.0", 40 | "react-device-detect": "2.2.3", 41 | "react-dom": "19.1.0", 42 | "react-number-format": "5.4.4", 43 | "react-router": "7.5.1", 44 | "react-router-dom": "7.5.1", 45 | "simplebar-react": "3.3.0", 46 | "swr": "2.3.3", 47 | "vite": "6.3.1", 48 | "vite-jsconfig-paths": "2.0.1", 49 | "web-vitals": "4.2.4", 50 | "yup": "1.6.1" 51 | }, 52 | "eslintConfig": { 53 | "extends": [ 54 | "react-app", 55 | "react-app/jest" 56 | ] 57 | }, 58 | "browserslist": { 59 | "production": [ 60 | ">0.2%", 61 | "not dead", 62 | "not op_mini all" 63 | ], 64 | "development": [ 65 | "last 1 chrome version", 66 | "last 1 firefox version", 67 | "last 1 safari version" 68 | ] 69 | }, 70 | "devDependencies": { 71 | "@eslint/compat": "1.2.8", 72 | "@eslint/eslintrc": "3.3.1", 73 | "@eslint/js": "9.25.1", 74 | "eslint": "9.25.1", 75 | "eslint-config-prettier": "10.1.2", 76 | "eslint-plugin-jsx-a11y": "6.10.2", 77 | "eslint-plugin-prettier": "5.2.6", 78 | "eslint-plugin-react": "7.37.4", 79 | "eslint-plugin-react-hooks": "5.2.0", 80 | "immutable": "4.3.7", 81 | "knip": "5.45.0", 82 | "prettier": "3.5.3", 83 | "prettier-eslint-cli": "8.0.1" 84 | }, 85 | "packageManager": "yarn@4.9.1" 86 | } 87 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import { RouterProvider } from 'react-router-dom'; 2 | 3 | // project imports 4 | import router from 'routes'; 5 | import ThemeCustomization from 'themes'; 6 | 7 | import ScrollTop from 'components/ScrollTop'; 8 | 9 | // ==============================|| APP - THEME, ROUTER, LOCAL ||============================== // 10 | 11 | export default function App() { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /src/api/menu.js: -------------------------------------------------------------------------------- 1 | import useSWR, { mutate } from 'swr'; 2 | import { useMemo } from 'react'; 3 | 4 | const initialState = { 5 | isDashboardDrawerOpened: false 6 | }; 7 | 8 | const endpoints = { 9 | key: 'api/menu', 10 | master: 'master', 11 | dashboard: '/dashboard' // server URL 12 | }; 13 | 14 | export function useGetMenuMaster() { 15 | const { data, isLoading } = useSWR(endpoints.key + endpoints.master, () => initialState, { 16 | revalidateIfStale: false, 17 | revalidateOnFocus: false, 18 | revalidateOnReconnect: false 19 | }); 20 | 21 | const memoizedValue = useMemo( 22 | () => ({ 23 | menuMaster: data, 24 | menuMasterLoading: isLoading 25 | }), 26 | [data, isLoading] 27 | ); 28 | 29 | return memoizedValue; 30 | } 31 | 32 | export function handlerDrawerOpen(isDashboardDrawerOpened) { 33 | // to update local state based on key 34 | 35 | mutate( 36 | endpoints.key + endpoints.master, 37 | (currentMenuMaster) => { 38 | return { ...currentMenuMaster, isDashboardDrawerOpened }; 39 | }, 40 | false 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /src/assets/images/users/avatar-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codedthemes/mantis-free-react-admin-template/d5312a2899cfa159aefd384b4357aaecaba4c4fe/src/assets/images/users/avatar-1.png -------------------------------------------------------------------------------- /src/assets/images/users/avatar-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codedthemes/mantis-free-react-admin-template/d5312a2899cfa159aefd384b4357aaecaba4c4fe/src/assets/images/users/avatar-2.png -------------------------------------------------------------------------------- /src/assets/images/users/avatar-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codedthemes/mantis-free-react-admin-template/d5312a2899cfa159aefd384b4357aaecaba4c4fe/src/assets/images/users/avatar-3.png -------------------------------------------------------------------------------- /src/assets/images/users/avatar-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codedthemes/mantis-free-react-admin-template/d5312a2899cfa159aefd384b4357aaecaba4c4fe/src/assets/images/users/avatar-4.png -------------------------------------------------------------------------------- /src/assets/images/users/avatar-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codedthemes/mantis-free-react-admin-template/d5312a2899cfa159aefd384b4357aaecaba4c4fe/src/assets/images/users/avatar-5.png -------------------------------------------------------------------------------- /src/assets/images/users/avatar-group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codedthemes/mantis-free-react-admin-template/d5312a2899cfa159aefd384b4357aaecaba4c4fe/src/assets/images/users/avatar-group.png -------------------------------------------------------------------------------- /src/assets/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-tap-highlight-color: transparent; 3 | } 4 | -------------------------------------------------------------------------------- /src/assets/third-party/apex-chart.css: -------------------------------------------------------------------------------- 1 | .apexcharts-legend-series { 2 | gap: 8px; 3 | } 4 | 5 | .apexcharts-tooltip-series-group.apexcharts-active, 6 | .apexcharts-tooltip-series-group:last-child { 7 | padding-bottom: 0 !important; 8 | } 9 | -------------------------------------------------------------------------------- /src/assets/third-party/react-table.css: -------------------------------------------------------------------------------- 1 | .cursor-pointer { 2 | cursor: pointer; 3 | } 4 | 5 | .prevent-select { 6 | -webkit-user-select: none; /* Safari */ 7 | -ms-user-select: none; /* IE 10 and IE 11 */ 8 | user-select: none; /* Standard syntax */ 9 | } 10 | 11 | .sticky-header { 12 | margin: 0; 13 | position: sticky; 14 | top: -1px; 15 | z-index: 1; 16 | } 17 | 18 | .resizer { 19 | position: absolute; 20 | right: 0; 21 | top: 0; 22 | height: 100%; 23 | width: 5px; 24 | cursor: col-resize; 25 | user-select: none; 26 | touch-action: none; 27 | } 28 | 29 | .resizer.isResizing { 30 | opacity: 1; 31 | } 32 | 33 | .MuiTableContainer-root { 34 | border-radius: 0px !important; 35 | } 36 | -------------------------------------------------------------------------------- /src/components/@extended/AnimateButton.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | // third-party 4 | import { motion, useCycle } from 'framer-motion'; 5 | 6 | export default function AnimateButton({ children, type = 'scale', direction = 'right', offset = 10, scale = { hover: 1.05, tap: 0.954 } }) { 7 | let offset1; 8 | let offset2; 9 | switch (direction) { 10 | case 'up': 11 | case 'left': 12 | offset1 = offset; 13 | offset2 = 0; 14 | break; 15 | case 'right': 16 | case 'down': 17 | default: 18 | offset1 = 0; 19 | offset2 = offset; 20 | break; 21 | } 22 | 23 | const [x, cycleX] = useCycle(offset1, offset2); 24 | const [y, cycleY] = useCycle(offset1, offset2); 25 | 26 | switch (type) { 27 | case 'rotate': 28 | return ( 29 | 38 | {children} 39 | 40 | ); 41 | case 'slide': 42 | if (direction === 'up' || direction === 'down') { 43 | return ( 44 | cycleY()} onHoverStart={() => cycleY()}> 45 | {children} 46 | 47 | ); 48 | } 49 | return ( 50 | cycleX()} onHoverStart={() => cycleX()}> 51 | {children} 52 | 53 | ); 54 | 55 | case 'scale': 56 | default: 57 | if (typeof scale === 'number') { 58 | scale = { 59 | hover: scale, 60 | tap: scale 61 | }; 62 | } 63 | return ( 64 | 65 | {children} 66 | 67 | ); 68 | } 69 | } 70 | 71 | AnimateButton.propTypes = { 72 | children: PropTypes.node, 73 | type: PropTypes.oneOf(['slide', 'scale', 'rotate']), 74 | direction: PropTypes.oneOf(['up', 'down', 'left', 'right']), 75 | offset: PropTypes.number, 76 | scale: PropTypes.object 77 | }; 78 | -------------------------------------------------------------------------------- /src/components/@extended/Avatar.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | // material-ui 4 | import { styled } from '@mui/material/styles'; 5 | import MuiAvatar from '@mui/material/Avatar'; 6 | 7 | // project imports 8 | import getColors from 'utils/getColors'; 9 | 10 | function getColorStyle({ theme, color, type }) { 11 | const colors = getColors(theme, color); 12 | const { lighter, light, main, contrastText } = colors; 13 | 14 | switch (type) { 15 | case 'filled': 16 | return { 17 | color: contrastText, 18 | background: main 19 | }; 20 | case 'outlined': 21 | return { 22 | color: main, 23 | border: '1px solid', 24 | borderColor: main, 25 | background: 'transparent' 26 | }; 27 | case 'combined': 28 | return { 29 | color: main, 30 | border: '1px solid', 31 | borderColor: light, 32 | background: lighter 33 | }; 34 | default: 35 | return { 36 | color: main, 37 | background: lighter 38 | }; 39 | } 40 | } 41 | 42 | // ==============================|| AVATAR - SIZE STYLE ||============================== // 43 | 44 | function getSizeStyle(size) { 45 | switch (size) { 46 | case 'badge': 47 | return { 48 | border: '2px solid', 49 | fontSize: '0.675rem', 50 | width: 20, 51 | height: 20 52 | }; 53 | case 'xs': 54 | return { 55 | fontSize: '0.75rem', 56 | width: 24, 57 | height: 24 58 | }; 59 | case 'sm': 60 | return { 61 | fontSize: '0.875rem', 62 | width: 32, 63 | height: 32 64 | }; 65 | case 'lg': 66 | return { 67 | fontSize: '1.2rem', 68 | width: 52, 69 | height: 52 70 | }; 71 | case 'xl': 72 | return { 73 | fontSize: '1.5rem', 74 | width: 64, 75 | height: 64 76 | }; 77 | case 'md': 78 | default: 79 | return { 80 | fontSize: '1rem', 81 | width: 40, 82 | height: 40 83 | }; 84 | } 85 | } 86 | 87 | const AvatarStyle = styled(MuiAvatar, { shouldForwardProp: (prop) => prop !== 'color' && prop !== 'type' && prop !== 'size' })( 88 | ({ theme, size, color, type }) => ({ 89 | ...getSizeStyle(size), 90 | ...getColorStyle({ theme, color, type }), 91 | variants: [ 92 | { 93 | props: { size: 'badge' }, 94 | style: { 95 | borderColor: theme.palette.background.default 96 | } 97 | } 98 | ] 99 | }) 100 | ); 101 | 102 | export default function Avatar({ children, color = 'primary', type, size = 'md', ...others }) { 103 | return ( 104 | 105 | {children} 106 | 107 | ); 108 | } 109 | 110 | getColorStyle.propTypes = { theme: PropTypes.any, color: PropTypes.any, type: PropTypes.any }; 111 | 112 | Avatar.propTypes = { 113 | children: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), 114 | color: PropTypes.string, 115 | type: PropTypes.any, 116 | size: PropTypes.string, 117 | others: PropTypes.any 118 | }; 119 | -------------------------------------------------------------------------------- /src/components/@extended/Dot.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // material-ui 3 | import { useTheme } from '@mui/material/styles'; 4 | import Box from '@mui/material/Box'; 5 | 6 | // project imports 7 | import getColors from 'utils/getColors'; 8 | 9 | export default function Dot({ color, size, variant, sx }) { 10 | const theme = useTheme(); 11 | const colors = getColors(theme, color || 'primary'); 12 | const { main } = colors; 13 | 14 | return ( 15 | 24 | ); 25 | } 26 | 27 | Dot.propTypes = { color: PropTypes.any, size: PropTypes.number, variant: PropTypes.string, sx: PropTypes.any }; 28 | -------------------------------------------------------------------------------- /src/components/@extended/IconButton.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | // material-ui 4 | import MuiIconButton from '@mui/material/IconButton'; 5 | import { alpha, styled } from '@mui/material/styles'; 6 | 7 | // project imports 8 | import getColors from 'utils/getColors'; 9 | import getShadow from 'utils/getShadow'; 10 | 11 | function getColorStyle({ variant, theme, color }) { 12 | const colors = getColors(theme, color); 13 | const { lighter, light, dark, main, contrastText } = colors; 14 | 15 | const buttonShadow = `${color}Button`; 16 | const shadows = getShadow(theme, buttonShadow); 17 | 18 | const commonShadow = { 19 | '&::after': { 20 | boxShadow: `0 0 6px 6px ${alpha(main, 0.9)}` 21 | }, 22 | '&:active::after': { 23 | boxShadow: `0 0 0 0 ${alpha(main, 0.9)}` 24 | }, 25 | '&:focus-visible': { 26 | outline: `2px solid ${dark}`, 27 | outlineOffset: 2 28 | } 29 | }; 30 | 31 | switch (variant) { 32 | case 'contained': 33 | return { 34 | color: contrastText, 35 | background: main, 36 | '&:hover': { 37 | background: dark 38 | }, 39 | ...commonShadow 40 | }; 41 | case 'light': 42 | return { 43 | color: main, 44 | background: lighter, 45 | '&:hover': { 46 | background: alpha(light, 0.5) 47 | }, 48 | ...commonShadow 49 | }; 50 | case 'shadow': 51 | return { 52 | boxShadow: shadows, 53 | color: contrastText, 54 | background: main, 55 | '&:hover': { 56 | boxShadow: 'none', 57 | background: dark 58 | }, 59 | ...commonShadow 60 | }; 61 | case 'outlined': 62 | return { 63 | '&:hover': { 64 | background: 'transparent', 65 | color: dark, 66 | borderColor: dark 67 | }, 68 | ...commonShadow 69 | }; 70 | case 'dashed': 71 | return { 72 | background: lighter, 73 | '&:hover': { 74 | color: dark, 75 | borderColor: dark 76 | }, 77 | ...commonShadow 78 | }; 79 | case 'text': 80 | default: 81 | return { 82 | '&:hover': { 83 | color: dark, 84 | background: color === 'secondary' ? alpha(light, 0.1) : lighter 85 | }, 86 | ...commonShadow 87 | }; 88 | } 89 | } 90 | 91 | const IconButtonStyle = styled(MuiIconButton, { shouldForwardProp: (prop) => prop !== 'variant' && prop !== 'shape' })( 92 | ({ theme, color, variant }) => ({ 93 | position: 'relative', 94 | '::after': { 95 | content: '""', 96 | display: 'block', 97 | position: 'absolute', 98 | left: 0, 99 | top: 0, 100 | width: '100%', 101 | height: '100%', 102 | borderRadius: 4, 103 | opacity: 0, 104 | transition: 'all 0.5s' 105 | }, 106 | 107 | ':active::after': { 108 | position: 'absolute', 109 | borderRadius: 4, 110 | left: 0, 111 | top: 0, 112 | opacity: 1, 113 | transition: '0s' 114 | }, 115 | 116 | ...getColorStyle({ variant, theme, color }), 117 | 118 | variants: [ 119 | { 120 | props: { shape: 'rounded' }, 121 | style: { 122 | borderRadius: '50%', 123 | '::after': { borderRadius: '50%' }, 124 | ':active::after': { borderRadius: '50%' } 125 | } 126 | }, 127 | { 128 | props: { variant: 'outlined' }, 129 | style: { 130 | border: '1px solid', 131 | borderColor: 'inherit' 132 | } 133 | }, 134 | { 135 | props: { variant: 'dashed' }, 136 | style: { 137 | border: '1px dashed', 138 | borderColor: 'inherit' 139 | } 140 | }, 141 | { 142 | props: ({ variant }) => variant !== 'text', 143 | style: { 144 | '&.Mui-disabled': { 145 | background: theme.palette.grey[200], 146 | '&:hover': { 147 | background: theme.palette.grey[200], 148 | color: theme.palette.grey[300], 149 | borderColor: 'inherit' 150 | } 151 | } 152 | } 153 | } 154 | ] 155 | }) 156 | ); 157 | 158 | function IconButton({ variant = 'text', shape = 'square', children, color = 'primary', ref, ...others }) { 159 | return ( 160 | 161 | {children} 162 | 163 | ); 164 | } 165 | 166 | IconButton.displayName = 'IconButton'; 167 | 168 | export default IconButton; 169 | 170 | getColorStyle.propTypes = { variant: PropTypes.any, theme: PropTypes.any, color: PropTypes.any }; 171 | 172 | IconButton.propTypes = { 173 | variant: PropTypes.string, 174 | shape: PropTypes.string, 175 | children: PropTypes.node, 176 | color: PropTypes.string, 177 | ref: PropTypes.any, 178 | others: PropTypes.any 179 | }; 180 | -------------------------------------------------------------------------------- /src/components/@extended/Transitions.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | // material-ui 4 | import Collapse from '@mui/material/Collapse'; 5 | import Fade from '@mui/material/Fade'; 6 | import Grow from '@mui/material/Grow'; 7 | import Slide from '@mui/material/Slide'; 8 | import Zoom from '@mui/material/Zoom'; 9 | import Box from '@mui/material/Box'; 10 | 11 | export default function Transitions({ children, position = 'top-left', type = 'grow', direction = 'up', ref, ...others }) { 12 | let positionSX = { 13 | transformOrigin: '0 0 0' 14 | }; 15 | 16 | switch (position) { 17 | case 'top-right': 18 | positionSX = { 19 | transformOrigin: 'top right' 20 | }; 21 | break; 22 | case 'top': 23 | positionSX = { 24 | transformOrigin: 'top' 25 | }; 26 | break; 27 | case 'bottom-left': 28 | positionSX = { 29 | transformOrigin: 'bottom left' 30 | }; 31 | break; 32 | case 'bottom-right': 33 | positionSX = { 34 | transformOrigin: 'bottom right' 35 | }; 36 | break; 37 | case 'bottom': 38 | positionSX = { 39 | transformOrigin: 'bottom' 40 | }; 41 | break; 42 | case 'top-left': 43 | default: 44 | positionSX = { 45 | transformOrigin: '0 0 0' 46 | }; 47 | break; 48 | } 49 | 50 | return ( 51 | 52 | {type === 'grow' && ( 53 | 61 | {children} 62 | 63 | )} 64 | 65 | {type === 'collapse' && ( 66 | 67 | {children} 68 | 69 | )} 70 | 71 | {type === 'fade' && ( 72 | 80 | {children} 81 | 82 | )} 83 | 84 | {type === 'slide' && ( 85 | 94 | {children} 95 | 96 | )} 97 | 98 | {type === 'zoom' && ( 99 | 100 | {children} 101 | 102 | )} 103 | 104 | ); 105 | } 106 | 107 | export function PopupTransition({ ref, ...props }) { 108 | return ; 109 | } 110 | 111 | Transitions.propTypes = { 112 | children: PropTypes.node, 113 | position: PropTypes.string, 114 | type: PropTypes.string, 115 | ref: PropTypes.any, 116 | direction: PropTypes.oneOf(['up', 'right', 'left', 'down']), 117 | others: PropTypes.any 118 | }; 119 | 120 | PopupTransition.propTypes = { ref: PropTypes.any, props: PropTypes.any }; 121 | -------------------------------------------------------------------------------- /src/components/Loadable.jsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from 'react'; 2 | 3 | // project imports 4 | import Loader from './Loader'; 5 | 6 | // ==============================|| LOADABLE - LAZY LOADING ||============================== // 7 | 8 | const Loadable = (Component) => (props) => { 9 | return ( 10 | }> 11 | 12 | 13 | ); 14 | }; 15 | 16 | export default Loadable; 17 | -------------------------------------------------------------------------------- /src/components/Loader.jsx: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import LinearProgress from '@mui/material/LinearProgress'; 3 | import Box from '@mui/material/Box'; 4 | 5 | // ==============================|| Loader ||============================== // 6 | 7 | export default function Loader() { 8 | return ( 9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/components/MainCard.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | // material-ui 4 | import Card from '@mui/material/Card'; 5 | import CardContent from '@mui/material/CardContent'; 6 | import CardHeader from '@mui/material/CardHeader'; 7 | import Divider from '@mui/material/Divider'; 8 | 9 | // header style 10 | const headerSX = { 11 | p: 2.5, 12 | '& .MuiCardHeader-action': { m: '0px auto', alignSelf: 'center' } 13 | }; 14 | 15 | export default function MainCard({ 16 | border = true, 17 | boxShadow, 18 | children, 19 | subheader, 20 | content = true, 21 | contentSX = {}, 22 | darkTitle, 23 | divider = true, 24 | elevation, 25 | secondary, 26 | shadow, 27 | sx = {}, 28 | title, 29 | modal = false, 30 | ref, 31 | ...others 32 | }) { 33 | return ( 34 | ({ 38 | position: 'relative', 39 | border: border ? '1px solid' : 'none', 40 | borderRadius: 1, 41 | borderColor: 'grey.A800', 42 | boxShadow: boxShadow && !border ? shadow || theme.customShadows.z1 : 'inherit', 43 | ':hover': { 44 | boxShadow: boxShadow ? shadow || theme.customShadows.z1 : 'inherit' 45 | }, 46 | ...(modal && { 47 | position: 'absolute', 48 | top: '50%', 49 | left: '50%', 50 | transform: 'translate(-50%, -50%)', 51 | width: { xs: `calc(100% - 50px)`, sm: 'auto' }, 52 | maxWidth: 768, 53 | '& .MuiCardContent-root': { overflowY: 'auto', minHeight: 'auto', maxHeight: `calc(100vh - 200px)` } 54 | }) 55 | }), 56 | sx 57 | ]} 58 | ref={ref} 59 | {...others} 60 | > 61 | {/* card header and action */} 62 | {!darkTitle && title && ( 63 | 64 | )} 65 | 66 | {/* content & header divider */} 67 | {title && divider && } 68 | 69 | {/* card content */} 70 | {content && {children}} 71 | {!content && children} 72 | 73 | ); 74 | } 75 | 76 | MainCard.propTypes = { 77 | border: PropTypes.bool, 78 | boxShadow: PropTypes.bool, 79 | children: PropTypes.node, 80 | subheader: PropTypes.oneOfType([PropTypes.node, PropTypes.string]), 81 | content: PropTypes.bool, 82 | contentSX: PropTypes.object, 83 | darkTitle: PropTypes.bool, 84 | divider: PropTypes.bool, 85 | elevation: PropTypes.number, 86 | secondary: PropTypes.any, 87 | shadow: PropTypes.string, 88 | sx: PropTypes.object, 89 | title: PropTypes.oneOfType([PropTypes.node, PropTypes.string]), 90 | modal: PropTypes.bool, 91 | ref: PropTypes.object, 92 | others: PropTypes.any 93 | }; 94 | -------------------------------------------------------------------------------- /src/components/ScrollTop.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { useEffect } from 'react'; 3 | 4 | // ==============================|| NAVIGATION - SCROLL TO TOP ||============================== // 5 | 6 | export default function ScrollTop({ children }) { 7 | useEffect(() => { 8 | window.scrollTo({ 9 | top: 0, 10 | left: 0, 11 | behavior: 'smooth' 12 | }); 13 | }, []); 14 | 15 | return children || null; 16 | } 17 | 18 | ScrollTop.propTypes = { children: PropTypes.oneOfType([PropTypes.any, PropTypes.node]) }; 19 | -------------------------------------------------------------------------------- /src/components/cards/AuthFooter.jsx: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import Container from '@mui/material/Container'; 3 | import Link from '@mui/material/Link'; 4 | import Typography from '@mui/material/Typography'; 5 | import Stack from '@mui/material/Stack'; 6 | 7 | // ==============================|| FOOTER - AUTHENTICATION ||============================== // 8 | 9 | export default function AuthFooter() { 10 | return ( 11 | 12 | 16 | 17 | © Made with love by Team{' '} 18 | 19 | CodedThemes 20 | 21 | 22 | 23 | 24 | 32 | Terms and Conditions 33 | 34 | 42 | Privacy Policy 43 | 44 | 45 | 46 | 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /src/components/cards/statistics/AnalyticEcommerce.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // material-ui 3 | import Chip from '@mui/material/Chip'; 4 | import Grid from '@mui/material/Grid'; 5 | import Stack from '@mui/material/Stack'; 6 | import Typography from '@mui/material/Typography'; 7 | import Box from '@mui/material/Box'; 8 | 9 | // project imports 10 | import MainCard from 'components/MainCard'; 11 | 12 | // assets 13 | import RiseOutlined from '@ant-design/icons/RiseOutlined'; 14 | import FallOutlined from '@ant-design/icons/FallOutlined'; 15 | 16 | const iconSX = { fontSize: '0.75rem', color: 'inherit', marginLeft: 0, marginRight: 0 }; 17 | 18 | export default function AnalyticEcommerce({ color = 'primary', title, count, percentage, isLoss, extra }) { 19 | return ( 20 | 21 | 22 | 23 | {title} 24 | 25 | 26 | 27 | 28 | {count} 29 | 30 | 31 | {percentage && ( 32 | 33 | : } 37 | label={`${percentage}%`} 38 | sx={{ ml: 1.25, pl: 1 }} 39 | size="small" 40 | /> 41 | 42 | )} 43 | 44 | 45 | 46 | 47 | You made an extra{' '} 48 | 49 | {extra} 50 | {' '} 51 | this year 52 | 53 | 54 | 55 | ); 56 | } 57 | 58 | AnalyticEcommerce.propTypes = { 59 | color: PropTypes.string, 60 | title: PropTypes.string, 61 | count: PropTypes.string, 62 | percentage: PropTypes.number, 63 | isLoss: PropTypes.bool, 64 | extra: PropTypes.string 65 | }; 66 | -------------------------------------------------------------------------------- /src/components/logo/LogoIcon.jsx: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import { useTheme } from '@mui/material/styles'; 3 | 4 | /** 5 | * if you want to use image instead of uncomment following. 6 | * 7 | * import logoIconDark from 'assets/images/logo-icon-dark.svg'; 8 | * import logoIcon from 'assets/images/logo-icon.svg'; 9 | * import { ThemeMode } from 'config'; 10 | * 11 | */ 12 | 13 | // ==============================|| LOGO ICON SVG ||============================== // 14 | 15 | export default function LogoIcon() { 16 | const theme = useTheme(); 17 | 18 | return ( 19 | /** 20 | * if you want to use image instead of svg uncomment following, and comment out element. 21 | * 22 | * Mantis 23 | * 24 | */ 25 | 26 | 30 | 34 | 38 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /src/components/logo/LogoMain.jsx: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import { useTheme } from '@mui/material/styles'; 3 | 4 | /** 5 | * if you want to use image instead of uncomment following. 6 | * 7 | * import logoDark from 'assets/images/logo-dark.svg'; 8 | * import logo from 'assets/images/logo.svg'; 9 | * 10 | */ 11 | 12 | // ==============================|| LOGO SVG ||============================== // 13 | 14 | export default function LogoMain() { 15 | const theme = useTheme(); 16 | return ( 17 | /** 18 | * if you want to use image instead of svg uncomment following, and comment out element. 19 | * 20 | * Mantis 21 | * 22 | */ 23 | <> 24 | 25 | 29 | 33 | 37 | 41 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /src/components/logo/index.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | // material-ui 5 | import ButtonBase from '@mui/material/ButtonBase'; 6 | 7 | // project imports 8 | import Logo from './LogoMain'; 9 | import LogoIcon from './LogoIcon'; 10 | import { APP_DEFAULT_PATH } from 'config'; 11 | 12 | // ==============================|| MAIN LOGO ||============================== // 13 | 14 | export default function LogoSection({ reverse, isIcon, sx, to }) { 15 | return ( 16 | 17 | {isIcon ? : } 18 | 19 | ); 20 | } 21 | 22 | LogoSection.propTypes = { reverse: PropTypes.bool, isIcon: PropTypes.bool, sx: PropTypes.any, to: PropTypes.any }; 23 | -------------------------------------------------------------------------------- /src/components/third-party/SimpleBar.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | // material-ui 4 | import { alpha, styled, useTheme } from '@mui/material/styles'; 5 | import Box from '@mui/material/Box'; 6 | 7 | // third-party 8 | import SimpleBar from 'simplebar-react'; 9 | import { BrowserView, MobileView } from 'react-device-detect'; 10 | 11 | // root style 12 | const RootStyle = styled(BrowserView)({ 13 | flexGrow: 1, 14 | height: '100%', 15 | overflow: 'hidden' 16 | }); 17 | 18 | // scroll bar wrapper 19 | const SimpleBarStyle = styled(SimpleBar)(({ theme }) => ({ 20 | maxHeight: '100%', 21 | '& .simplebar-scrollbar': { 22 | '&:before': { 23 | background: alpha(theme.palette.grey[500], 0.48), 24 | ...theme.applyStyles('dark', { background: alpha(theme.palette.grey[200], 0.48) }) 25 | }, 26 | '&.simplebar-visible:before': { 27 | opacity: 1 28 | } 29 | }, 30 | '& .simplebar-track': { 31 | '&.simplebar-vertical': { 32 | width: 10 33 | } 34 | }, 35 | '& .simplebar-track.simplebar-horizontal .simplebar-scrollbar': { 36 | height: 6 37 | }, 38 | '& .simplebar-mask': { 39 | zIndex: 'inherit' 40 | } 41 | })); 42 | 43 | // ==============================|| SIMPLE SCROLL BAR ||============================== // 44 | 45 | export default function SimpleBarScroll({ children, sx, ...other }) { 46 | const theme = useTheme(); 47 | 48 | return ( 49 | <> 50 | 51 | 52 | {children} 53 | 54 | 55 | 56 | 57 | {children} 58 | 59 | 60 | 61 | ); 62 | } 63 | 64 | SimpleBarScroll.propTypes = { children: PropTypes.any, sx: PropTypes.any, other: PropTypes.any }; 65 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | // ==============================|| THEME CONSTANT ||============================== // 2 | 3 | export const APP_DEFAULT_PATH = '/dashboard/default'; 4 | export const DRAWER_WIDTH = 260; 5 | export const MINI_DRAWER_WIDTH = 60; 6 | -------------------------------------------------------------------------------- /src/contexts/README.md: -------------------------------------------------------------------------------- 1 | **Note:** *This README file is maintained to ensure the product structure aligns with the Pro version, making migration to Pro seamless when you choose to upgrade. This alignment aims to provide a smoother experience during the upgrade, especially regarding directory structure. You may notice these files and folders appearing throughout the project where they are part of the Pro version. While this might feel slightly inconvenient, it is intended to simplify your migration process and provide assistance. If these files are unnecessary for your use case, you can easily remove them.* 2 | 3 | Please continue reading below to explore the features of the Pro version: 4 | 5 | # Mantis Admin Panel - Unlock Premium Features with the Pro Version 6 | 7 | Elevate your project with the Pro Version of the Mantis Admin Panel! Built to cater to modern web applications, the Pro version is loaded with advanced features, intuitive design elements, and dynamic tools that ensure seamless functionality. 8 | 9 | This page (folder) is a sneak peek into the premium features available in version 3.4.0. Upgrade to the Pro version to unlock exclusive pages and components that will take your project to the next level. 10 | 11 | ## Included in the Pro Version: 12 | 13 | [🚀 Dashboards](https://mantisdashboard.io/dashboard/default) : Advanced dashboards with real-time insights and data visualizations for actionable metrics. 14 | 15 | [📦 Widgets](https://mantisdashboard.io/widget/statistics) : A curated library of pre-built widgets for enhanced functionality and faster development. 16 | 17 | [🔧 Components](https://mantisdashboard.io/components-overview/buttons) : A rich collection of reusable and customizable UI components. 18 | 19 | [📝 Forms](https://mantisdashboard.io/forms/wizard) : Dynamic and customizable forms with advanced validation features for a smooth user experience. 20 | 21 | [📊 Tables](https://mantisdashboard.io/tables/react-table/basic) : Structured, interactive tables with sorting, filtering, and pagination options. 22 | 23 | [📈 Charts](https://mantisdashboard.io/charts/apexchart) : Beautifully designed charts powered by modern data visualization libraries. 24 | 25 | [🔒 Authentication](https://mantisdashboard.io/auth/login) : Secure pages for login, registration, and password recovery, ensuring robust user management. 26 | 27 | [🛒 E-commerce App](https://mantisdashboard.io/apps/e-commerce/products) : A complete e-commerce management system for handling products, inventory, and transactions. 28 | 29 | [💬 Chat Messages](https://mantisdashboard.io/apps/chat) : An integrated chat system to enhance communication within your application. 30 | 31 | [👤 User Profile](https://mantisdashboard.io/apps/profiles/user/personal) : A sleek and customizable user profile page for managing user details and settings. 32 | 33 | ## Why Upgrade to the Pro Version? 34 | 35 | 🚀 Advanced Features : Access premium components and tools designed for modern, high-end projects.

36 | ⚡ Faster Development : Pre-designed pages, widgets, and features help you save time and effort.

37 | 📱 Fully Responsive Design : Enjoy a flawless experience across desktops, tablets, and smartphones.

38 | 🛠 Developer-Friendly : Modular code, clear documentation, and well-structured components make customization a breeze.

39 | 🎨 Customization-Ready : Personalize every aspect of your project with ease to match your branding needs. 40 | 41 | ## Get Started with the Pro Version! 42 | 43 | 👉 [Explore the Pro version now](https://codedthemes.com/item/mantis-angular-admin-template/) - and supercharge your development experience! 44 | -------------------------------------------------------------------------------- /src/data/README.md: -------------------------------------------------------------------------------- 1 | **Note:** *This README file is maintained to ensure the product structure aligns with the Pro version, making migration to Pro seamless when you choose to upgrade. This alignment aims to provide a smoother experience during the upgrade, especially regarding directory structure. You may notice these files and folders appearing throughout the project where they are part of the Pro version. While this might feel slightly inconvenient, it is intended to simplify your migration process and provide assistance. If these files are unnecessary for your use case, you can easily remove them.* 2 | 3 | Please continue reading below to explore the features of the Pro version: 4 | 5 | # Mantis Admin Panel - Unlock Premium Features with the Pro Version 6 | 7 | Elevate your project with the Pro Version of the Mantis Admin Panel! Built to cater to modern web applications, the Pro version is loaded with advanced features, intuitive design elements, and dynamic tools that ensure seamless functionality. 8 | 9 | This page (folder) is a sneak peek into the premium features available in version 3.4.0. Upgrade to the Pro version to unlock exclusive pages and components that will take your project to the next level. 10 | 11 | ## Included in the Pro Version: 12 | 13 | [🚀 Dashboards](https://mantisdashboard.io/dashboard/default) : Advanced dashboards with real-time insights and data visualizations for actionable metrics. 14 | 15 | [📦 Widgets](https://mantisdashboard.io/widget/statistics) : A curated library of pre-built widgets for enhanced functionality and faster development. 16 | 17 | [🔧 Components](https://mantisdashboard.io/components-overview/buttons) : A rich collection of reusable and customizable UI components. 18 | 19 | [📝 Forms](https://mantisdashboard.io/forms/wizard) : Dynamic and customizable forms with advanced validation features for a smooth user experience. 20 | 21 | [📊 Tables](https://mantisdashboard.io/tables/react-table/basic) : Structured, interactive tables with sorting, filtering, and pagination options. 22 | 23 | [📈 Charts](https://mantisdashboard.io/charts/apexchart) : Beautifully designed charts powered by modern data visualization libraries. 24 | 25 | [🔒 Authentication](https://mantisdashboard.io/auth/login) : Secure pages for login, registration, and password recovery, ensuring robust user management. 26 | 27 | [🛒 E-commerce App](https://mantisdashboard.io/apps/e-commerce/products) : A complete e-commerce management system for handling products, inventory, and transactions. 28 | 29 | [💬 Chat Messages](https://mantisdashboard.io/apps/chat) : An integrated chat system to enhance communication within your application. 30 | 31 | [👤 User Profile](https://mantisdashboard.io/apps/profiles/user/personal) : A sleek and customizable user profile page for managing user details and settings. 32 | 33 | ## Why Upgrade to the Pro Version? 34 | 35 | 🚀 Advanced Features : Access premium components and tools designed for modern, high-end projects.

36 | ⚡ Faster Development : Pre-designed pages, widgets, and features help you save time and effort.

37 | 📱 Fully Responsive Design : Enjoy a flawless experience across desktops, tablets, and smartphones.

38 | 🛠 Developer-Friendly : Modular code, clear documentation, and well-structured components make customization a breeze.

39 | 🎨 Customization-Ready : Personalize every aspect of your project with ease to match your branding needs. 40 | 41 | ## Get Started with the Pro Version! 42 | 43 | 👉 [Explore the Pro version now](https://codedthemes.com/item/mantis-angular-admin-template/) - and supercharge your development experience! 44 | -------------------------------------------------------------------------------- /src/hooks/README.md: -------------------------------------------------------------------------------- 1 | **Note:** *This README file is maintained to ensure the product structure aligns with the Pro version, making migration to Pro seamless when you choose to upgrade. This alignment aims to provide a smoother experience during the upgrade, especially regarding directory structure. You may notice these files and folders appearing throughout the project where they are part of the Pro version. While this might feel slightly inconvenient, it is intended to simplify your migration process and provide assistance. If these files are unnecessary for your use case, you can easily remove them.* 2 | 3 | Please continue reading below to explore the features of the Pro version: 4 | 5 | # Mantis Admin Panel - Unlock Premium Features with the Pro Version 6 | 7 | Elevate your project with the Pro Version of the Mantis Admin Panel! Built to cater to modern web applications, the Pro version is loaded with advanced features, intuitive design elements, and dynamic tools that ensure seamless functionality. 8 | 9 | This page (folder) is a sneak peek into the premium features available in version 3.4.0. Upgrade to the Pro version to unlock exclusive pages and components that will take your project to the next level. 10 | 11 | ## Included in the Pro Version: 12 | 13 | [🚀 Dashboards](https://mantisdashboard.io/dashboard/default) : Advanced dashboards with real-time insights and data visualizations for actionable metrics. 14 | 15 | [📦 Widgets](https://mantisdashboard.io/widget/statistics) : A curated library of pre-built widgets for enhanced functionality and faster development. 16 | 17 | [🔧 Components](https://mantisdashboard.io/components-overview/buttons) : A rich collection of reusable and customizable UI components. 18 | 19 | [📝 Forms](https://mantisdashboard.io/forms/wizard) : Dynamic and customizable forms with advanced validation features for a smooth user experience. 20 | 21 | [📊 Tables](https://mantisdashboard.io/tables/react-table/basic) : Structured, interactive tables with sorting, filtering, and pagination options. 22 | 23 | [📈 Charts](https://mantisdashboard.io/charts/apexchart) : Beautifully designed charts powered by modern data visualization libraries. 24 | 25 | [🔒 Authentication](https://mantisdashboard.io/auth/login) : Secure pages for login, registration, and password recovery, ensuring robust user management. 26 | 27 | [🛒 E-commerce App](https://mantisdashboard.io/apps/e-commerce/products) : A complete e-commerce management system for handling products, inventory, and transactions. 28 | 29 | [💬 Chat Messages](https://mantisdashboard.io/apps/chat) : An integrated chat system to enhance communication within your application. 30 | 31 | [👤 User Profile](https://mantisdashboard.io/apps/profiles/user/personal) : A sleek and customizable user profile page for managing user details and settings. 32 | 33 | ## Why Upgrade to the Pro Version? 34 | 35 | 🚀 Advanced Features : Access premium components and tools designed for modern, high-end projects.

36 | ⚡ Faster Development : Pre-designed pages, widgets, and features help you save time and effort.

37 | 📱 Fully Responsive Design : Enjoy a flawless experience across desktops, tablets, and smartphones.

38 | 🛠 Developer-Friendly : Modular code, clear documentation, and well-structured components make customization a breeze.

39 | 🎨 Customization-Ready : Personalize every aspect of your project with ease to match your branding needs. 40 | 41 | ## Get Started with the Pro Version! 42 | 43 | 👉 [Explore the Pro version now](https://codedthemes.com/item/mantis-angular-admin-template/) - and supercharge your development experience! 44 | -------------------------------------------------------------------------------- /src/index.jsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from 'react-dom/client'; 2 | 3 | // style.scss 4 | import 'assets/style.css'; 5 | 6 | // scroll bar 7 | import 'simplebar-react/dist/simplebar.min.css'; 8 | 9 | // apex-chart 10 | import 'assets/third-party/apex-chart.css'; 11 | import 'assets/third-party/react-table.css'; 12 | 13 | // google-fonts 14 | import '@fontsource/roboto/400.css'; 15 | import '@fontsource/roboto/500.css'; 16 | import '@fontsource/roboto/300.css'; 17 | import '@fontsource/roboto/700.css'; 18 | 19 | import '@fontsource/inter/400.css'; 20 | import '@fontsource/inter/500.css'; 21 | import '@fontsource/inter/600.css'; 22 | import '@fontsource/inter/700.css'; 23 | 24 | import '@fontsource/poppins/400.css'; 25 | import '@fontsource/poppins/500.css'; 26 | import '@fontsource/poppins/600.css'; 27 | import '@fontsource/poppins/700.css'; 28 | 29 | import '@fontsource/public-sans/400.css'; 30 | import '@fontsource/public-sans/500.css'; 31 | import '@fontsource/public-sans/600.css'; 32 | import '@fontsource/public-sans/700.css'; 33 | 34 | // project imports 35 | import App from './App'; 36 | import reportWebVitals from './reportWebVitals'; 37 | 38 | const container = document.getElementById('root'); 39 | const root = createRoot(container); 40 | 41 | // ==============================|| MAIN - REACT DOM RENDER ||============================== // 42 | 43 | root.render(); 44 | 45 | // If you want to start measuring performance in your app, pass a function 46 | // to log results (for example: reportWebVitals(console.log)) 47 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 48 | reportWebVitals(); 49 | -------------------------------------------------------------------------------- /src/layout/Auth/index.jsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from 'react-router-dom'; 2 | 3 | // ==============================|| LAYOUT - AUTH ||============================== // 4 | 5 | export default function AuthLayout() { 6 | return ( 7 | <> 8 | 9 | 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Drawer/DrawerContent/NavCard.jsx: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import Button from '@mui/material/Button'; 3 | import CardMedia from '@mui/material/CardMedia'; 4 | import Link from '@mui/material/Link'; 5 | import Stack from '@mui/material/Stack'; 6 | import Typography from '@mui/material/Typography'; 7 | 8 | // project import 9 | import MainCard from 'components/MainCard'; 10 | 11 | // assets 12 | import avatar from 'assets/images/users/avatar-group.png'; 13 | import AnimateButton from 'components/@extended/AnimateButton'; 14 | 15 | // ==============================|| DRAWER CONTENT - NAVIGATION CARD ||============================== // 16 | 17 | export default function NavCard() { 18 | return ( 19 | 20 | 21 | 22 | 23 | Mantis Pro 24 | 25 | Checkout pro features 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Drawer/DrawerContent/Navigation/NavGroup.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // material-ui 3 | import List from '@mui/material/List'; 4 | import Typography from '@mui/material/Typography'; 5 | import Box from '@mui/material/Box'; 6 | 7 | // project import 8 | import NavItem from './NavItem'; 9 | import { useGetMenuMaster } from 'api/menu'; 10 | 11 | export default function NavGroup({ item }) { 12 | const { menuMaster } = useGetMenuMaster(); 13 | const drawerOpen = menuMaster.isDashboardDrawerOpened; 14 | 15 | const navCollapse = item.children?.map((menuItem) => { 16 | switch (menuItem.type) { 17 | case 'collapse': 18 | return ( 19 | 20 | collapse - only available in paid version 21 | 22 | ); 23 | case 'item': 24 | return ; 25 | default: 26 | return ( 27 | 28 | Fix - Group Collapse or Items 29 | 30 | ); 31 | } 32 | }); 33 | 34 | return ( 35 | 40 | 41 | {item.title} 42 | 43 | {/* only available in paid version */} 44 |
45 | ) 46 | } 47 | sx={{ mb: drawerOpen ? 1.5 : 0, py: 0, zIndex: 0 }} 48 | > 49 | {navCollapse} 50 | 51 | ); 52 | } 53 | 54 | NavGroup.propTypes = { item: PropTypes.object }; 55 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Drawer/DrawerContent/Navigation/NavItem.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Link, useLocation, matchPath } from 'react-router-dom'; 3 | 4 | // material-ui 5 | import useMediaQuery from '@mui/material/useMediaQuery'; 6 | import Avatar from '@mui/material/Avatar'; 7 | import Chip from '@mui/material/Chip'; 8 | import ListItemButton from '@mui/material/ListItemButton'; 9 | import ListItemIcon from '@mui/material/ListItemIcon'; 10 | import ListItemText from '@mui/material/ListItemText'; 11 | import Typography from '@mui/material/Typography'; 12 | import Box from '@mui/material/Box'; 13 | 14 | // project imports 15 | import IconButton from 'components/@extended/IconButton'; 16 | 17 | import { handlerDrawerOpen, useGetMenuMaster } from 'api/menu'; 18 | 19 | // ==============================|| NAVIGATION - LIST ITEM ||============================== // 20 | 21 | export default function NavItem({ item, level, isParents = false, setSelectedID }) { 22 | const { menuMaster } = useGetMenuMaster(); 23 | const drawerOpen = menuMaster.isDashboardDrawerOpened; 24 | 25 | const downLG = useMediaQuery((theme) => theme.breakpoints.down('lg')); 26 | 27 | let itemTarget = '_self'; 28 | if (item.target) { 29 | itemTarget = '_blank'; 30 | } 31 | 32 | const itemHandler = () => { 33 | if (downLG) handlerDrawerOpen(false); 34 | 35 | if (isParents && setSelectedID) { 36 | setSelectedID(item.id); 37 | } 38 | }; 39 | 40 | const Icon = item.icon; 41 | const itemIcon = item.icon ? ( 42 | 48 | ) : ( 49 | false 50 | ); 51 | 52 | const { pathname } = useLocation(); 53 | const isSelected = !!matchPath({ path: item?.link ? item.link : item.url, end: false }, pathname); 54 | 55 | const textColor = 'text.primary'; 56 | const iconSelectedColor = 'primary.main'; 57 | 58 | return ( 59 | <> 60 | 61 | ({ 68 | zIndex: 1201, 69 | pl: drawerOpen ? `${level * 28}px` : 1.5, 70 | py: !drawerOpen && level === 1 ? 1.25 : 1, 71 | ...(drawerOpen && { 72 | '&:hover': { bgcolor: 'primary.lighter', ...theme.applyStyles('dark', { bgcolor: 'divider' }) }, 73 | '&.Mui-selected': { 74 | bgcolor: 'primary.lighter', 75 | ...theme.applyStyles('dark', { bgcolor: 'divider' }), 76 | borderRight: '2px solid', 77 | borderColor: 'primary.main', 78 | color: iconSelectedColor, 79 | '&:hover': { color: iconSelectedColor, bgcolor: 'primary.lighter', ...theme.applyStyles('dark', { bgcolor: 'divider' }) } 80 | } 81 | }), 82 | ...(!drawerOpen && { 83 | '&:hover': { bgcolor: 'transparent' }, 84 | '&.Mui-selected': { '&:hover': { bgcolor: 'transparent' }, bgcolor: 'transparent' } 85 | }) 86 | })} 87 | onClick={() => itemHandler()} 88 | > 89 | {itemIcon && ( 90 | ({ 92 | minWidth: 28, 93 | color: isSelected ? iconSelectedColor : textColor, 94 | ...(!drawerOpen && { 95 | borderRadius: 1.5, 96 | width: 36, 97 | height: 36, 98 | alignItems: 'center', 99 | justifyContent: 'center', 100 | '&:hover': { bgcolor: 'secondary.lighter', ...theme.applyStyles('dark', { bgcolor: 'secondary.light' }) } 101 | }), 102 | ...(!drawerOpen && 103 | isSelected && { 104 | bgcolor: 'primary.lighter', 105 | ...theme.applyStyles('dark', { bgcolor: 'primary.900' }), 106 | '&:hover': { bgcolor: 'primary.lighter', ...theme.applyStyles('dark', { bgcolor: 'primary.darker' }) } 107 | }) 108 | })} 109 | > 110 | {itemIcon} 111 | 112 | )} 113 | {(drawerOpen || (!drawerOpen && level !== 1)) && ( 114 | 117 | {item.title} 118 | 119 | } 120 | /> 121 | )} 122 | {(drawerOpen || (!drawerOpen && level !== 1)) && item.chip && ( 123 | {item.chip.avatar}} 129 | /> 130 | )} 131 | 132 | {(drawerOpen || (!drawerOpen && level !== 1)) && 133 | item?.actions && 134 | item?.actions.map((action, index) => { 135 | const ActionIcon = action.icon; 136 | const callAction = action?.function; 137 | return ( 138 | { 142 | event.stopPropagation(); 143 | callAction(); 144 | } 145 | })} 146 | {...(action.type === 'link' && { 147 | component: Link, 148 | to: action.url, 149 | target: action.target ? '_blank' : '_self' 150 | })} 151 | color="secondary" 152 | variant="outlined" 153 | sx={{ 154 | position: 'absolute', 155 | top: 12, 156 | right: 20, 157 | zIndex: 1202, 158 | width: 20, 159 | height: 20, 160 | mr: -1, 161 | ml: 1, 162 | color: 'secondary.dark', 163 | borderColor: isSelected ? 'primary.light' : 'secondary.light', 164 | '&:hover': { borderColor: isSelected ? 'primary.main' : 'secondary.main' } 165 | }} 166 | > 167 | 168 | 169 | ); 170 | })} 171 | 172 | 173 | ); 174 | } 175 | 176 | NavItem.propTypes = { 177 | item: PropTypes.any, 178 | level: PropTypes.number, 179 | isParents: PropTypes.bool, 180 | setSelectedID: PropTypes.oneOfType([PropTypes.any, PropTypes.func]) 181 | }; 182 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Drawer/DrawerContent/Navigation/index.jsx: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import Typography from '@mui/material/Typography'; 3 | import Box from '@mui/material/Box'; 4 | 5 | // project import 6 | import NavGroup from './NavGroup'; 7 | import menuItem from 'menu-items'; 8 | 9 | // ==============================|| DRAWER CONTENT - NAVIGATION ||============================== // 10 | 11 | export default function Navigation() { 12 | const navGroups = menuItem.items.map((item) => { 13 | switch (item.type) { 14 | case 'group': 15 | return ; 16 | default: 17 | return ( 18 | 19 | Fix - Navigation Group 20 | 21 | ); 22 | } 23 | }); 24 | 25 | return {navGroups}; 26 | } 27 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Drawer/DrawerContent/index.jsx: -------------------------------------------------------------------------------- 1 | // project imports 2 | import NavCard from './NavCard'; 3 | import Navigation from './Navigation'; 4 | import SimpleBar from 'components/third-party/SimpleBar'; 5 | import { useGetMenuMaster } from 'api/menu'; 6 | 7 | // ==============================|| DRAWER CONTENT ||============================== // 8 | 9 | export default function DrawerContent() { 10 | const { menuMaster } = useGetMenuMaster(); 11 | const drawerOpen = menuMaster.isDashboardDrawerOpened; 12 | 13 | return ( 14 | <> 15 | 16 | 17 | {drawerOpen && } 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Drawer/DrawerHeader/DrawerHeaderStyled.js: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import { styled } from '@mui/material/styles'; 3 | import Box from '@mui/material/Box'; 4 | 5 | // ==============================|| DRAWER HEADER - STYLED ||============================== // 6 | 7 | const DrawerHeaderStyled = styled(Box, { shouldForwardProp: (prop) => prop !== 'open' })(({ theme }) => ({ 8 | ...theme.mixins.toolbar, 9 | display: 'flex', 10 | alignItems: 'center', 11 | justifyContent: 'center', 12 | paddingLeft: theme.spacing(0), 13 | variants: [ 14 | { 15 | props: ({ open }) => open, 16 | style: { justifyContent: 'flex-start', paddingLeft: theme.spacing(3) } 17 | } 18 | ] 19 | })); 20 | 21 | export default DrawerHeaderStyled; 22 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Drawer/DrawerHeader/index.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | // project imports 4 | import DrawerHeaderStyled from './DrawerHeaderStyled'; 5 | import Logo from 'components/logo'; 6 | 7 | // ==============================|| DRAWER HEADER ||============================== // 8 | 9 | export default function DrawerHeader({ open }) { 10 | return ( 11 | 21 | 22 | 23 | ); 24 | } 25 | 26 | DrawerHeader.propTypes = { open: PropTypes.bool }; 27 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Drawer/MiniDrawerStyled.js: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import { styled } from '@mui/material/styles'; 3 | import Drawer from '@mui/material/Drawer'; 4 | 5 | // project imports 6 | import { DRAWER_WIDTH } from 'config'; 7 | 8 | const openedMixin = (theme) => ({ 9 | width: DRAWER_WIDTH, 10 | borderRight: '1px solid', 11 | borderRightColor: theme.palette.divider, 12 | 13 | transition: theme.transitions.create('width', { 14 | easing: theme.transitions.easing.sharp, 15 | duration: theme.transitions.duration.enteringScreen 16 | }), 17 | 18 | overflowX: 'hidden', 19 | boxShadow: 'none', 20 | ...theme.applyStyles('dark', { boxShadow: theme.customShadows.z1 }) 21 | }); 22 | 23 | const closedMixin = (theme) => ({ 24 | transition: theme.transitions.create('width', { 25 | easing: theme.transitions.easing.sharp, 26 | duration: theme.transitions.duration.leavingScreen 27 | }), 28 | 29 | overflowX: 'hidden', 30 | width: theme.spacing(7.5), 31 | borderRight: 'none', 32 | boxShadow: theme.customShadows.z1 33 | }); 34 | 35 | // ==============================|| DRAWER - MINI STYLED ||============================== // 36 | 37 | const MiniDrawerStyled = styled(Drawer, { shouldForwardProp: (prop) => prop !== 'open' })(({ theme }) => ({ 38 | width: DRAWER_WIDTH, 39 | flexShrink: 0, 40 | whiteSpace: 'nowrap', 41 | boxSizing: 'border-box', 42 | variants: [ 43 | { 44 | props: ({ open }) => open, 45 | style: { 46 | ...openedMixin(theme), 47 | '& .MuiDrawer-paper': openedMixin(theme) 48 | } 49 | }, 50 | { 51 | props: ({ open }) => !open, 52 | style: { 53 | ...closedMixin(theme), 54 | '& .MuiDrawer-paper': closedMixin(theme) 55 | } 56 | } 57 | ] 58 | })); 59 | 60 | export default MiniDrawerStyled; 61 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Drawer/index.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { useMemo } from 'react'; 3 | 4 | import useMediaQuery from '@mui/material/useMediaQuery'; 5 | import Drawer from '@mui/material/Drawer'; 6 | import Box from '@mui/material/Box'; 7 | 8 | // project imports 9 | import DrawerHeader from './DrawerHeader'; 10 | import DrawerContent from './DrawerContent'; 11 | import MiniDrawerStyled from './MiniDrawerStyled'; 12 | 13 | import { DRAWER_WIDTH } from 'config'; 14 | import { handlerDrawerOpen, useGetMenuMaster } from 'api/menu'; 15 | 16 | // ==============================|| MAIN LAYOUT - DRAWER ||============================== // 17 | 18 | export default function MainDrawer({ window }) { 19 | const { menuMaster } = useGetMenuMaster(); 20 | const drawerOpen = menuMaster.isDashboardDrawerOpened; 21 | const downLG = useMediaQuery((theme) => theme.breakpoints.down('lg')); 22 | 23 | // responsive drawer container 24 | const container = window !== undefined ? () => window().document.body : undefined; 25 | 26 | // header content 27 | const drawerContent = useMemo(() => , []); 28 | const drawerHeader = useMemo(() => , [drawerOpen]); 29 | 30 | return ( 31 | 32 | {!downLG ? ( 33 | 34 | {drawerHeader} 35 | {drawerContent} 36 | 37 | ) : ( 38 | handlerDrawerOpen(!drawerOpen)} 43 | ModalProps={{ keepMounted: true }} 44 | sx={{ 45 | display: { xs: drawerOpen ? 'block' : 'none', lg: 'none' }, 46 | '& .MuiDrawer-paper': { 47 | boxSizing: 'border-box', 48 | width: DRAWER_WIDTH, 49 | borderRight: '1px solid', 50 | borderRightColor: 'divider', 51 | boxShadow: 'inherit' 52 | } 53 | }} 54 | > 55 | {drawerHeader} 56 | {drawerContent} 57 | 58 | )} 59 | 60 | ); 61 | } 62 | 63 | MainDrawer.propTypes = { window: PropTypes.func }; 64 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Footer.jsx: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import Link from '@mui/material/Link'; 3 | import Stack from '@mui/material/Stack'; 4 | import Typography from '@mui/material/Typography'; 5 | 6 | export default function Footer() { 7 | return ( 8 | 9 | 10 | © All rights reserved{' '} 11 | 12 | CodedThemes 13 | 14 | 15 | 16 | 17 | About us 18 | 19 | 20 | Privacy 21 | 22 | 23 | Terms 24 | 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Header/AppBarStyled.jsx: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import { styled } from '@mui/material/styles'; 3 | import AppBar from '@mui/material/AppBar'; 4 | 5 | // project imports 6 | import { DRAWER_WIDTH } from 'config'; 7 | 8 | const AppBarStyled = styled(AppBar, { shouldForwardProp: (prop) => prop !== 'open' })(({ theme }) => ({ 9 | zIndex: theme.zIndex.drawer + 1, 10 | transition: theme.transitions.create(['width', 'margin'], { 11 | easing: theme.transitions.easing.sharp, 12 | duration: theme.transitions.duration.leavingScreen 13 | }), 14 | variants: [ 15 | { 16 | props: ({ open }) => !open, 17 | style: { 18 | width: `calc(100% - ${theme.spacing(7.5)})` 19 | } 20 | }, 21 | { 22 | props: ({ open }) => open, 23 | style: { 24 | marginLeft: DRAWER_WIDTH, 25 | width: `calc(100% - ${DRAWER_WIDTH}px)`, 26 | transition: theme.transitions.create(['width', 'margin'], { 27 | easing: theme.transitions.easing.sharp, 28 | duration: theme.transitions.duration.enteringScreen 29 | }) 30 | } 31 | } 32 | ] 33 | })); 34 | 35 | export default AppBarStyled; 36 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Header/HeaderContent/MobileSection.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef, useState } from 'react'; 2 | 3 | // material-ui 4 | import AppBar from '@mui/material/AppBar'; 5 | import ClickAwayListener from '@mui/material/ClickAwayListener'; 6 | import Paper from '@mui/material/Paper'; 7 | import Popper from '@mui/material/Popper'; 8 | import Toolbar from '@mui/material/Toolbar'; 9 | import Box from '@mui/material/Box'; 10 | 11 | // project imports 12 | import Search from './Search'; 13 | import Profile from './Profile'; 14 | import IconButton from 'components/@extended/IconButton'; 15 | import Transitions from 'components/@extended/Transitions'; 16 | 17 | // assets 18 | import MoreOutlined from '@ant-design/icons/MoreOutlined'; 19 | 20 | // ==============================|| HEADER CONTENT - MOBILE ||============================== // 21 | 22 | export default function MobileSection() { 23 | const [open, setOpen] = useState(false); 24 | const anchorRef = useRef(null); 25 | 26 | const handleToggle = () => { 27 | setOpen((prevOpen) => !prevOpen); 28 | }; 29 | 30 | const handleClose = (event) => { 31 | if (anchorRef.current && anchorRef.current.contains(event.target)) { 32 | return; 33 | } 34 | 35 | setOpen(false); 36 | }; 37 | 38 | const prevOpen = useRef(open); 39 | useEffect(() => { 40 | if (prevOpen.current === true && open === false) { 41 | anchorRef.current.focus(); 42 | } 43 | 44 | prevOpen.current = open; 45 | }, [open]); 46 | 47 | return ( 48 | <> 49 | 50 | ({ 52 | color: 'text.primary', 53 | bgcolor: open ? 'grey.300' : 'grey.100', 54 | ...theme.applyStyles('dark', { bgcolor: open ? 'grey.200' : 'background.default' }) 55 | })} 56 | aria-label="open more menu" 57 | ref={anchorRef} 58 | aria-controls={open ? 'menu-list-grow' : undefined} 59 | aria-haspopup="true" 60 | onClick={handleToggle} 61 | color="secondary" 62 | variant="light" 63 | > 64 | 65 | 66 | 67 | 86 | {({ TransitionProps }) => ( 87 | 88 | ({ boxShadow: theme.customShadows.z1 })}> 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | )} 100 | 101 | 102 | ); 103 | } 104 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Header/HeaderContent/Profile/ProfileTab.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | // material-ui 4 | import List from '@mui/material/List'; 5 | import ListItemButton from '@mui/material/ListItemButton'; 6 | import ListItemIcon from '@mui/material/ListItemIcon'; 7 | import ListItemText from '@mui/material/ListItemText'; 8 | 9 | // assets 10 | import EditOutlined from '@ant-design/icons/EditOutlined'; 11 | import ProfileOutlined from '@ant-design/icons/ProfileOutlined'; 12 | import LogoutOutlined from '@ant-design/icons/LogoutOutlined'; 13 | import UserOutlined from '@ant-design/icons/UserOutlined'; 14 | import WalletOutlined from '@ant-design/icons/WalletOutlined'; 15 | 16 | // ==============================|| HEADER PROFILE - PROFILE TAB ||============================== // 17 | 18 | export default function ProfileTab() { 19 | return ( 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ); 54 | } 55 | 56 | ProfileTab.propTypes = { handleLogout: PropTypes.func }; 57 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Header/HeaderContent/Profile/SettingTab.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { useNavigate } from 'react-router'; 3 | 4 | // material-ui 5 | import List from '@mui/material/List'; 6 | import Link from '@mui/material/Link'; 7 | import ListItemButton from '@mui/material/ListItemButton'; 8 | import ListItemIcon from '@mui/material/ListItemIcon'; 9 | import ListItemText from '@mui/material/ListItemText'; 10 | 11 | // assets 12 | import CommentOutlined from '@ant-design/icons/CommentOutlined'; 13 | import LockOutlined from '@ant-design/icons/LockOutlined'; 14 | import QuestionCircleOutlined from '@ant-design/icons/QuestionCircleOutlined'; 15 | import UserOutlined from '@ant-design/icons/UserOutlined'; 16 | import UnorderedListOutlined from '@ant-design/icons/UnorderedListOutlined'; 17 | 18 | // ==============================|| HEADER PROFILE - SETTING TAB ||============================== // 19 | 20 | export default function SettingTab() { 21 | const navigate = useNavigate(); 22 | const [selectedIndex, setSelectedIndex] = useState(0); 23 | 24 | const handleListItemClick = (event, index, route = '') => { 25 | setSelectedIndex(index); 26 | 27 | if (route && route !== '') { 28 | navigate(route); 29 | } 30 | }; 31 | 32 | return ( 33 | 34 | 35 | handleListItemClick(event, 0)}> 36 | 37 | 38 | 39 | 40 | 41 | 42 | handleListItemClick(event, 1)}> 43 | 44 | 45 | 46 | 47 | 48 | handleListItemClick(event, 2)}> 49 | 50 | 51 | 52 | 53 | 54 | 55 | handleListItemClick(event, 3)}> 56 | 57 | 58 | 59 | 60 | 61 | 62 | handleListItemClick(event, 4)}> 63 | 64 | 65 | 66 | 67 | 68 | 69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Header/HeaderContent/Profile/index.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { useRef, useState } from 'react'; 3 | 4 | // material-ui 5 | import { useTheme } from '@mui/material/styles'; 6 | import ButtonBase from '@mui/material/ButtonBase'; 7 | import CardContent from '@mui/material/CardContent'; 8 | import ClickAwayListener from '@mui/material/ClickAwayListener'; 9 | import Grid from '@mui/material/Grid'; 10 | import Paper from '@mui/material/Paper'; 11 | import Popper from '@mui/material/Popper'; 12 | import Stack from '@mui/material/Stack'; 13 | import Tab from '@mui/material/Tab'; 14 | import Tabs from '@mui/material/Tabs'; 15 | import Tooltip from '@mui/material/Tooltip'; 16 | import Typography from '@mui/material/Typography'; 17 | import Box from '@mui/material/Box'; 18 | 19 | // project imports 20 | import ProfileTab from './ProfileTab'; 21 | import SettingTab from './SettingTab'; 22 | import Avatar from 'components/@extended/Avatar'; 23 | import MainCard from 'components/MainCard'; 24 | import Transitions from 'components/@extended/Transitions'; 25 | import IconButton from 'components/@extended/IconButton'; 26 | 27 | // assets 28 | import LogoutOutlined from '@ant-design/icons/LogoutOutlined'; 29 | import SettingOutlined from '@ant-design/icons/SettingOutlined'; 30 | import UserOutlined from '@ant-design/icons/UserOutlined'; 31 | import avatar1 from 'assets/images/users/avatar-1.png'; 32 | 33 | // tab panel wrapper 34 | function TabPanel({ children, value, index, ...other }) { 35 | return ( 36 | 39 | ); 40 | } 41 | 42 | function a11yProps(index) { 43 | return { 44 | id: `profile-tab-${index}`, 45 | 'aria-controls': `profile-tabpanel-${index}` 46 | }; 47 | } 48 | 49 | // ==============================|| HEADER CONTENT - PROFILE ||============================== // 50 | 51 | export default function Profile() { 52 | const theme = useTheme(); 53 | 54 | const anchorRef = useRef(null); 55 | const [open, setOpen] = useState(false); 56 | const handleToggle = () => { 57 | setOpen((prevOpen) => !prevOpen); 58 | }; 59 | 60 | const handleClose = (event) => { 61 | if (anchorRef.current && anchorRef.current.contains(event.target)) { 62 | return; 63 | } 64 | setOpen(false); 65 | }; 66 | 67 | const [value, setValue] = useState(0); 68 | 69 | const handleChange = (event, newValue) => { 70 | setValue(newValue); 71 | }; 72 | 73 | return ( 74 | 75 | ({ 77 | p: 0.25, 78 | bgcolor: open ? 'grey.100' : 'transparent', 79 | borderRadius: 1, 80 | '&:hover': { bgcolor: 'secondary.lighter' }, 81 | '&:focus-visible': { outline: `2px solid ${theme.palette.secondary.dark}`, outlineOffset: 2 }, 82 | ...theme.applyStyles('dark', { bgcolor: open ? 'background.default' : 'transparent', '&:hover': { bgcolor: 'secondary.light' } }) 83 | })} 84 | aria-label="open profile" 85 | ref={anchorRef} 86 | aria-controls={open ? 'profile-grow' : undefined} 87 | aria-haspopup="true" 88 | onClick={handleToggle} 89 | > 90 | 91 | 92 | 93 | John Doe 94 | 95 | 96 | 97 | 115 | {({ TransitionProps }) => ( 116 | 117 | ({ boxShadow: theme.customShadows.z1, width: 290, minWidth: 240, maxWidth: { xs: 250, md: 290 } })}> 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | John Doe 127 | 128 | UI/UX Designer 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | } 158 | label="Profile" 159 | {...a11yProps(0)} 160 | /> 161 | } 174 | label="Setting" 175 | {...a11yProps(1)} 176 | /> 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | )} 190 | 191 | 192 | ); 193 | } 194 | 195 | TabPanel.propTypes = { children: PropTypes.node, value: PropTypes.number, index: PropTypes.number, other: PropTypes.any }; 196 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Header/HeaderContent/Search.jsx: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import FormControl from '@mui/material/FormControl'; 3 | import InputAdornment from '@mui/material/InputAdornment'; 4 | import OutlinedInput from '@mui/material/OutlinedInput'; 5 | import Box from '@mui/material/Box'; 6 | 7 | // assets 8 | import SearchOutlined from '@ant-design/icons/SearchOutlined'; 9 | 10 | // ==============================|| HEADER CONTENT - SEARCH ||============================== // 11 | 12 | export default function Search() { 13 | return ( 14 | 15 | 16 | 21 | 22 | 23 | } 24 | aria-describedby="header-search-text" 25 | slotProps={{ input: { 'aria-label': 'weight' } }} 26 | placeholder="Ctrl + K" 27 | /> 28 | 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Header/HeaderContent/index.jsx: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import useMediaQuery from '@mui/material/useMediaQuery'; 3 | import IconButton from '@mui/material/IconButton'; 4 | import Link from '@mui/material/Link'; 5 | import Box from '@mui/material/Box'; 6 | 7 | // project imports 8 | import Search from './Search'; 9 | import Profile from './Profile'; 10 | import Notification from './Notification'; 11 | import MobileSection from './MobileSection'; 12 | 13 | // project import 14 | import { GithubOutlined } from '@ant-design/icons'; 15 | 16 | // ==============================|| HEADER - CONTENT ||============================== // 17 | 18 | export default function HeaderContent() { 19 | const downLG = useMediaQuery((theme) => theme.breakpoints.down('lg')); 20 | 21 | return ( 22 | <> 23 | {!downLG && } 24 | {downLG && } 25 | 34 | 35 | 36 | 37 | 38 | {!downLG && } 39 | {downLG && } 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /src/layout/Dashboard/Header/index.jsx: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react'; 2 | 3 | // material-ui 4 | import useMediaQuery from '@mui/material/useMediaQuery'; 5 | import AppBar from '@mui/material/AppBar'; 6 | import Toolbar from '@mui/material/Toolbar'; 7 | 8 | // project imports 9 | import AppBarStyled from './AppBarStyled'; 10 | import HeaderContent from './HeaderContent'; 11 | import IconButton from 'components/@extended/IconButton'; 12 | 13 | import { handlerDrawerOpen, useGetMenuMaster } from 'api/menu'; 14 | import { DRAWER_WIDTH, MINI_DRAWER_WIDTH } from 'config'; 15 | 16 | // assets 17 | import MenuFoldOutlined from '@ant-design/icons/MenuFoldOutlined'; 18 | import MenuUnfoldOutlined from '@ant-design/icons/MenuUnfoldOutlined'; 19 | 20 | // ==============================|| MAIN LAYOUT - HEADER ||============================== // 21 | 22 | export default function Header() { 23 | const downLG = useMediaQuery((theme) => theme.breakpoints.down('lg')); 24 | 25 | const { menuMaster } = useGetMenuMaster(); 26 | const drawerOpen = menuMaster.isDashboardDrawerOpened; 27 | 28 | // header content 29 | const headerContent = useMemo(() => , []); 30 | 31 | // common header 32 | const mainHeader = ( 33 | 34 | handlerDrawerOpen(!drawerOpen)} 37 | edge="start" 38 | color="secondary" 39 | variant="light" 40 | sx={(theme) => ({ 41 | color: 'text.primary', 42 | bgcolor: drawerOpen ? 'transparent' : 'grey.100', 43 | ...theme.applyStyles('dark', { bgcolor: drawerOpen ? 'transparent' : 'background.default' }), 44 | ml: { xs: 0, lg: -2 } 45 | })} 46 | > 47 | {!drawerOpen ? : } 48 | 49 | {headerContent} 50 | 51 | ); 52 | 53 | // app-bar params 54 | const appBar = { 55 | position: 'fixed', 56 | color: 'inherit', 57 | elevation: 0, 58 | sx: { 59 | borderBottom: '1px solid', 60 | borderBottomColor: 'divider', 61 | zIndex: 1200, 62 | width: { xs: '100%', lg: drawerOpen ? `calc(100% - ${DRAWER_WIDTH}px)` : `calc(100% - ${MINI_DRAWER_WIDTH}px)` } 63 | } 64 | }; 65 | 66 | return ( 67 | <> 68 | {!downLG ? ( 69 | 70 | {mainHeader} 71 | 72 | ) : ( 73 | {mainHeader} 74 | )} 75 | 76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /src/layout/Dashboard/index.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { Outlet, useLocation } from 'react-router-dom'; 3 | 4 | import useMediaQuery from '@mui/material/useMediaQuery'; 5 | import Toolbar from '@mui/material/Toolbar'; 6 | import Box from '@mui/material/Box'; 7 | 8 | // project imports 9 | import Drawer from './Drawer'; 10 | import Header from './Header'; 11 | import Footer from './Footer'; 12 | import Loader from 'components/Loader'; 13 | import Breadcrumbs from 'components/@extended/Breadcrumbs'; 14 | 15 | import { handlerDrawerOpen, useGetMenuMaster } from 'api/menu'; 16 | 17 | // ==============================|| MAIN LAYOUT ||============================== // 18 | 19 | export default function DashboardLayout() { 20 | const { pathname } = useLocation(); 21 | const { menuMasterLoading } = useGetMenuMaster(); 22 | const downXL = useMediaQuery((theme) => theme.breakpoints.down('xl')); 23 | 24 | // set media wise responsive drawer 25 | useEffect(() => { 26 | handlerDrawerOpen(!downXL); 27 | }, [downXL]); 28 | 29 | if (menuMasterLoading) return ; 30 | 31 | return ( 32 | 33 |
34 | 35 | 36 | 37 | 38 | 47 | {pathname !== '/apps/profiles/account/my-account' && } 48 | 49 |