├── .eslintignore ├── .eslintrc ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── README.md ├── config-overrides.js ├── jsconfig.json ├── package-lock.json ├── package.json ├── public ├── _redirects ├── assets │ ├── avatar.png │ ├── bg_card.png │ ├── bg_gradient.jpeg │ ├── icons │ │ ├── flags │ │ │ ├── ic_flag_cn.svg │ │ │ ├── ic_flag_de.svg │ │ │ ├── ic_flag_en.svg │ │ │ ├── ic_flag_fr.svg │ │ │ ├── ic_flag_kr.svg │ │ │ ├── ic_flag_sa.svg │ │ │ ├── ic_flag_us.svg │ │ │ └── ic_flag_vn.svg │ │ └── navbar │ │ │ ├── ic_dashboard.svg │ │ │ └── ic_user.svg │ ├── illustrations │ │ ├── illustration_components.png │ │ ├── illustration_dashboard.png │ │ ├── illustration_empty_cart.svg │ │ ├── illustration_empty_content.svg │ │ ├── illustration_empty_mail.svg │ │ └── illustration_invite.png │ ├── overlay.svg │ └── placeholder.svg ├── favicon │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ └── favicon.ico ├── fonts │ ├── CircularStd-Bold.otf │ ├── CircularStd-Book.otf │ ├── CircularStd-Medium.otf │ ├── Roboto-Bold.ttf │ ├── Roboto-Regular.ttf │ └── index.css ├── index.html ├── logo │ ├── logo_full.png │ ├── logo_full.svg │ └── logo_single.svg ├── manifest.json └── robots.txt ├── src ├── App.js ├── _mock │ ├── _analytics.js │ ├── _app.js │ ├── _banking.js │ ├── _booking.js │ ├── _countries.js │ ├── _ecommerce.js │ ├── _invoice.js │ ├── _mock.js │ ├── _others.js │ ├── _plans.js │ ├── _top100Films.js │ ├── _user.js │ ├── address.js │ ├── boolean.js │ ├── company.js │ ├── email.js │ ├── funcs.js │ ├── index.js │ ├── map │ │ ├── cities.js │ │ ├── countries.js │ │ ├── map-style-basic-v8.json │ │ └── stations.js │ ├── name.js │ ├── number.js │ ├── phoneNumber.js │ ├── role.js │ └── text.js ├── assets │ ├── icon_plan_free.js │ ├── icon_plan_premium.js │ ├── icon_plan_starter.js │ ├── icon_sent.js │ ├── illustration_403.js │ ├── illustration_404.js │ ├── illustration_500.js │ ├── illustration_background.js │ ├── illustration_booking.js │ ├── illustration_checkin.js │ ├── illustration_checkout.js │ ├── illustration_coming_soon.js │ ├── illustration_doc.js │ ├── illustration_maintenance.js │ ├── illustration_motivation.js │ ├── illustration_order_complete.js │ ├── illustration_seo.js │ ├── illustration_upload.js │ └── index.js ├── components │ ├── Avatar.js │ ├── BadgeStatus.js │ ├── Breadcrumbs.js │ ├── CopyClipboard.js │ ├── EmojiPicker.js │ ├── EmptyContent.js │ ├── HeaderBreadcrumbs.js │ ├── Iconify.js │ ├── Image.js │ ├── InputStyle.js │ ├── Label.js │ ├── LightboxModal.js │ ├── LoadingScreen.js │ ├── Logo.js │ ├── Markdown.js │ ├── MenuPopover.js │ ├── MyAvatar.js │ ├── NotistackProvider.js │ ├── Page.js │ ├── ProgressBar.js │ ├── ScrollToTop.js │ ├── Scrollbar.js │ ├── SearchNotFound.js │ ├── SocialsButton.js │ ├── SvgIconStyle.js │ ├── TextIconLabel.js │ ├── TextMaxLine.js │ ├── animate │ │ ├── DialogAnimate.js │ │ ├── FabButtonAnimate.js │ │ ├── IconButtonAnimate.js │ │ ├── MotionContainer.js │ │ ├── MotionLazyContainer.js │ │ ├── MotionViewport.js │ │ ├── TextAnimate.js │ │ ├── features.js │ │ ├── index.js │ │ └── variants │ │ │ ├── actions.js │ │ │ ├── background.js │ │ │ ├── bounce.js │ │ │ ├── container.js │ │ │ ├── fade.js │ │ │ ├── flip.js │ │ │ ├── index.js │ │ │ ├── path.js │ │ │ ├── rotate.js │ │ │ ├── scale.js │ │ │ ├── slide.js │ │ │ ├── transition.js │ │ │ └── zoom.js │ ├── carousel │ │ ├── CarouselArrowIndex.js │ │ ├── CarouselArrows.js │ │ ├── CarouselDots.js │ │ └── index.js │ ├── chart │ │ ├── BaseOptionChart.js │ │ ├── ChartStyle.js │ │ └── index.js │ ├── color-utils │ │ ├── ColorManyPicker.js │ │ ├── ColorPreview.js │ │ ├── ColorSinglePicker.js │ │ └── index.js │ ├── editor │ │ ├── EditorToolbar.js │ │ ├── EditorToolbarStyle.js │ │ └── index.js │ ├── hook-form │ │ ├── FormProvider.js │ │ ├── RHFCheckbox.js │ │ ├── RHFEditor.js │ │ ├── RHFRadioGroup.js │ │ ├── RHFSelect.js │ │ ├── RHFSwitch.js │ │ ├── RHFTextField.js │ │ ├── RHFUpload.js │ │ └── index.js │ ├── map │ │ ├── MapControlFullscreen.js │ │ ├── MapControlGeolocate.js │ │ ├── MapControlMarker.js │ │ ├── MapControlNavigation.js │ │ ├── MapControlPopup.js │ │ ├── MapControlScale.js │ │ └── index.js │ ├── mega-menu │ │ ├── MegaMenuDesktopHorizon.js │ │ ├── MegaMenuDesktopVertical.js │ │ ├── MegaMenuMobile.js │ │ ├── MenuCarousel.js │ │ ├── MenuConfig.js │ │ ├── MenuHotProducts.js │ │ └── index.js │ ├── nav-section │ │ ├── horizontal │ │ │ ├── NavItem.js │ │ │ ├── NavList.js │ │ │ ├── index.js │ │ │ └── style.js │ │ ├── index.js │ │ └── vertical │ │ │ ├── NavItem.js │ │ │ ├── NavList.js │ │ │ ├── index.js │ │ │ └── style.js │ ├── settings │ │ ├── ThemeColorPresets.js │ │ ├── ThemeContrast.js │ │ ├── ThemeLocalization.js │ │ ├── ThemeRtlLayout.js │ │ ├── drawer │ │ │ ├── BoxMask.js │ │ │ ├── SettingColorPresets.js │ │ │ ├── SettingContrast.js │ │ │ ├── SettingDirection.js │ │ │ ├── SettingFullscreen.js │ │ │ ├── SettingLayout.js │ │ │ ├── SettingMode.js │ │ │ ├── SettingStretch.js │ │ │ ├── ToggleButton.js │ │ │ └── index.js │ │ └── index.js │ ├── skeleton │ │ ├── SkeletonConversationItem.js │ │ ├── SkeletonKanbanColumn.js │ │ ├── SkeletonMailSidebarItem.js │ │ ├── SkeletonMap.js │ │ ├── SkeletonPost.js │ │ ├── SkeletonPostItem.js │ │ ├── SkeletonProduct.js │ │ ├── SkeletonProductItem.js │ │ └── index.js │ ├── table │ │ ├── TableEmptyRows.js │ │ ├── TableHeadCustom.js │ │ ├── TableMoreMenu.js │ │ ├── TableNoData.js │ │ ├── TableSelectedActions.js │ │ ├── TableSkeleton.js │ │ └── index.js │ └── upload │ │ ├── BlockContent.js │ │ ├── MultiFilePreview.js │ │ ├── RejectionFiles.js │ │ ├── UploadAvatar.js │ │ ├── UploadMultiFile.js │ │ ├── UploadSingleFile.js │ │ └── index.js ├── config.js ├── contexts │ ├── Auth0Context.js │ ├── CollapseDrawerContext.js │ ├── JWTContext.js │ └── SettingsContext.js ├── guards │ ├── AuthGuard.js │ ├── GuestGuard.js │ └── RoleBasedGuard.js ├── hooks │ ├── useAuth.js │ ├── useCollapseDrawer.js │ ├── useCountdown.js │ ├── useCustomer.js │ ├── useDateRangePicker.js │ ├── useEmployee.js │ ├── useIsMountedRef.js │ ├── useLocalStorage.js │ ├── useLocales.js │ ├── useOffSetTop.js │ ├── useResponsive.js │ ├── useSettings.js │ ├── useTable.js │ ├── useTabs.js │ └── useToggle.js ├── index.js ├── layouts │ ├── LogoOnlyLayout.js │ ├── dashboard │ │ ├── header │ │ │ ├── AccountPopover.js │ │ │ └── index.js │ │ ├── index.js │ │ └── navbar │ │ │ ├── CollapseButton.js │ │ │ ├── NavConfig.js │ │ │ ├── NavbarAccount.js │ │ │ ├── NavbarHorizontal.js │ │ │ └── NavbarVertical.js │ └── main │ │ ├── MainHeader.js │ │ ├── MenuConfig.js │ │ ├── MenuDesktop.js │ │ ├── MenuMobile.js │ │ └── index.js ├── locales │ ├── ar.js │ ├── cn.js │ ├── en.js │ ├── fr.js │ ├── i18n.js │ └── vn.js ├── pages │ ├── Home.js │ ├── Page403.js │ ├── Page404.js │ ├── Page500.js │ ├── auth │ │ └── Login.js │ └── dashboard │ │ ├── bus │ │ ├── BusCreate.js │ │ ├── BusList.js │ │ └── Buses.js │ │ ├── order │ │ ├── OrderCreate.js │ │ ├── OrderList.js │ │ └── Orders.js │ │ └── user │ │ ├── UserAccount.js │ │ ├── customer │ │ ├── CustomerCreate.js │ │ ├── CustomerList.js │ │ └── Customers.js │ │ └── employee │ │ ├── EmployeeCreate.js │ │ ├── Employees.js │ │ └── EmployeesList.js ├── redux │ ├── rootReducer.js │ ├── slices │ │ ├── order.js │ │ └── user.js │ └── store.js ├── reportWebVitals.js ├── routes │ ├── index.js │ └── paths.js ├── sections │ ├── @dashboard │ │ ├── bus │ │ │ ├── BusNewEditForm.js │ │ │ └── list │ │ │ │ ├── BusTableRow.js │ │ │ │ ├── BusTableToolbar.js │ │ │ │ └── index.js │ │ ├── customer │ │ │ ├── CustomerNewEditForm.js │ │ │ └── list │ │ │ │ ├── CustomerTableRow.js │ │ │ │ ├── CustomerTableToolbar.js │ │ │ │ └── index.js │ │ ├── employee │ │ │ ├── EmployeeNewEditForm.js │ │ │ └── list │ │ │ │ ├── EmployeeTableRow.js │ │ │ │ ├── EmployeeTableToolbar.js │ │ │ │ └── index.js │ │ ├── order │ │ │ ├── OrderNewEditForm.js │ │ │ └── list │ │ │ │ ├── OrderTableRow.js │ │ │ │ ├── OrderTableToolbar.js │ │ │ │ └── index.js │ │ └── user │ │ │ └── account │ │ │ ├── AccountGeneral.js │ │ │ └── index.js │ ├── auth │ │ ├── AuthFirebaseSocial.js │ │ ├── login │ │ │ ├── LoginForm.js │ │ │ └── index.js │ │ ├── new-password │ │ │ ├── NewPasswordForm.js │ │ │ └── index.js │ │ ├── register │ │ │ ├── RegisterForm.js │ │ │ └── index.js │ │ ├── reset-password │ │ │ ├── ResetPasswordForm.js │ │ │ └── index.js │ │ └── verify-code │ │ │ ├── VerifyCodeForm.js │ │ │ └── index.js │ └── home │ │ ├── HomeAdvertisement.js │ │ ├── HomeCleanInterfaces.js │ │ ├── HomeColorPresets.js │ │ ├── HomeDarkMode.js │ │ ├── HomeHero.js │ │ ├── HomeHugePackElements.js │ │ ├── HomeLookingFor.js │ │ ├── HomeMinimal.js │ │ ├── HomePricingPlans.js │ │ └── index.js ├── service-worker.js ├── serviceWorkerRegistration.js ├── theme │ ├── breakpoints.js │ ├── index.js │ ├── overrides │ │ ├── Accordion.js │ │ ├── Alert.js │ │ ├── Autocomplete.js │ │ ├── Avatar.js │ │ ├── Backdrop.js │ │ ├── Badge.js │ │ ├── Breadcrumbs.js │ │ ├── Button.js │ │ ├── ButtonGroup.js │ │ ├── Card.js │ │ ├── Checkbox.js │ │ ├── Chip.js │ │ ├── ControlLabel.js │ │ ├── CssBaseline.js │ │ ├── CustomIcons.js │ │ ├── DataGrid.js │ │ ├── Dialog.js │ │ ├── Drawer.js │ │ ├── Fab.js │ │ ├── Input.js │ │ ├── Link.js │ │ ├── List.js │ │ ├── LoadingButton.js │ │ ├── Menu.js │ │ ├── Pagination.js │ │ ├── Paper.js │ │ ├── Popover.js │ │ ├── Progress.js │ │ ├── Radio.js │ │ ├── Rating.js │ │ ├── Select.js │ │ ├── Skeleton.js │ │ ├── Slider.js │ │ ├── Stepper.js │ │ ├── SvgIcon.js │ │ ├── Switch.js │ │ ├── Table.js │ │ ├── Tabs.js │ │ ├── Timeline.js │ │ ├── ToggleButton.js │ │ ├── Tooltip.js │ │ ├── TreeView.js │ │ ├── Typography.js │ │ └── index.js │ ├── palette.js │ ├── shadows.js │ └── typography.js └── utils │ ├── axios.js │ ├── createAvatar.js │ ├── cssStyles.js │ ├── formatNumber.js │ ├── formatTime.js │ ├── getColorName.js │ ├── getColorPresets.js │ ├── getFileData.js │ ├── getFileFormat.js │ ├── getFontValue.js │ ├── highlight.js │ ├── jwt.js │ ├── mapboxgl.js │ └── uuidv4.js └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | // .eslintignore 2 | build/* 3 | public/* 4 | src/service-worker.js 5 | src/serviceWorkerRegistration.js 6 | src/setupTests.js 7 | src/reportWebVitals.js 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | /.env 17 | /.env.local 18 | /.env.development.local 19 | /.env.test.local 20 | /.env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | .eslintcache 27 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | package-lock.json 4 | public 5 | 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "singleQuote": true, 4 | "trailingComma": "es5", 5 | "tabWidth": 2 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "javascript.validate.enable": false, 3 | "typescript.validate.enable": false, 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## 1.Install 4 | 5 | ### npm 6 | 7 | ``` 8 | npm i 9 | or 10 | npm i --legacy-peer-deps 11 | ``` 12 | 13 | ### yarn 14 | 15 | ``` 16 | yarn install 17 | ``` 18 | 19 | ## 2.Start 20 | 21 | ```sh 22 | npm start 23 | or 24 | yarn start 25 | ``` 26 | 27 | ## 3.Build 28 | 29 | ```sh 30 | npm run build or yarn build 31 | ``` 32 | 33 | Builds the app for production to the `build` folder.
34 | It correctly bundles React in production mode and optimizes the build for the best performance. 35 | 36 | The build is minified and the filenames include the hashes.
37 | 38 | Your app is ready to be deployed. 39 | 40 | ## User Guide 41 | 42 | You can find detailed instructions on using Create React App and many tips in [its documentation](https://facebook.github.io/create-react-app/). 43 | -------------------------------------------------------------------------------- /config-overrides.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | 3 | module.exports = function override(config) { 4 | config.resolve.fallback = { 5 | process: require.resolve('process/browser'), 6 | zlib: require.resolve('browserify-zlib'), 7 | stream: require.resolve('stream-browserify'), 8 | util: require.resolve('util'), 9 | buffer: require.resolve('buffer'), 10 | asset: require.resolve('assert'), 11 | }; 12 | 13 | config.plugins.push( 14 | new webpack.ProvidePlugin({ 15 | process: 'process/browser.js', 16 | Buffer: ['buffer', 'Buffer'], 17 | }) 18 | ); 19 | 20 | return config; 21 | }; 22 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "baseUrl": "." 6 | }, 7 | "include": [ 8 | "src/**/*" 9 | ], 10 | "exclude": [ 11 | "node_modules" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /public/assets/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/assets/avatar.png -------------------------------------------------------------------------------- /public/assets/bg_card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/assets/bg_card.png -------------------------------------------------------------------------------- /public/assets/bg_gradient.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/assets/bg_gradient.jpeg -------------------------------------------------------------------------------- /public/assets/icons/flags/ic_flag_cn.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | ic_flag_cn 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/assets/icons/flags/ic_flag_de.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/icons/flags/ic_flag_en.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/icons/flags/ic_flag_fr.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/icons/flags/ic_flag_vn.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | ic_flag_vn 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/assets/icons/navbar/ic_dashboard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/icons/navbar/ic_user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/illustrations/illustration_components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/assets/illustrations/illustration_components.png -------------------------------------------------------------------------------- /public/assets/illustrations/illustration_dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/assets/illustrations/illustration_dashboard.png -------------------------------------------------------------------------------- /public/assets/illustrations/illustration_invite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/assets/illustrations/illustration_invite.png -------------------------------------------------------------------------------- /public/assets/overlay.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/placeholder.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/favicon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/favicon/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/favicon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/favicon/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/favicon/favicon.ico -------------------------------------------------------------------------------- /public/fonts/CircularStd-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/fonts/CircularStd-Bold.otf -------------------------------------------------------------------------------- /public/fonts/CircularStd-Book.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/fonts/CircularStd-Book.otf -------------------------------------------------------------------------------- /public/fonts/CircularStd-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/fonts/CircularStd-Medium.otf -------------------------------------------------------------------------------- /public/fonts/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/fonts/Roboto-Bold.ttf -------------------------------------------------------------------------------- /public/fonts/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/fonts/Roboto-Regular.ttf -------------------------------------------------------------------------------- /public/fonts/index.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'CircularStd'; 3 | font-weight: 400; 4 | font-style: normal; 5 | src: local('CircularStd'), url('CircularStd-Book.otf') format('opentype'); 6 | } 7 | @font-face { 8 | font-family: 'CircularStd'; 9 | font-weight: 500; 10 | font-style: normal; 11 | src: local('CircularStd'), url('CircularStd-Medium.otf') format('opentype'); 12 | } 13 | @font-face { 14 | font-family: 'CircularStd'; 15 | font-weight: 700; 16 | font-style: normal; 17 | src: local('CircularStd'), url('CircularStd-Bold.otf') format('opentype'); 18 | } 19 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Cleaning Web Site 23 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /public/logo/logo_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/public/logo/logo_full.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MUI", 3 | "short_name": "Clening Web Site", 4 | "display": "standalone", 5 | "start_url": "/", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff", 8 | "icons": [ 9 | { 10 | "src": "favicon/android-chrome-192x192.png", 11 | "sizes": "192x192", 12 | "type": "image/png" 13 | }, 14 | { 15 | "src": "favicon/android-chrome-512x512.png", 16 | "sizes": "512x512", 17 | "type": "image/png" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | // routes 2 | import Router from './routes'; 3 | // theme 4 | import ThemeProvider from './theme'; 5 | // components 6 | import ThemeSettings from './components/settings'; 7 | import { ChartStyle } from './components/chart'; 8 | import ScrollToTop from './components/ScrollToTop'; 9 | import { ProgressBarStyle } from './components/ProgressBar'; 10 | import NotistackProvider from './components/NotistackProvider'; 11 | import MotionLazyContainer from './components/animate/MotionLazyContainer'; 12 | 13 | // ---------------------------------------------------------------------- 14 | 15 | export default function App() { 16 | return ( 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /src/_mock/_analytics.js: -------------------------------------------------------------------------------- 1 | // components 2 | import Iconify from '../components/Iconify'; 3 | // 4 | import _mock from './_mock'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | export const _analyticPost = [...Array(5)].map((_, index) => ({ 9 | id: _mock.id(index), 10 | title: _mock.text.title(index), 11 | description: _mock.text.description(index), 12 | image: _mock.image.cover(index), 13 | postedAt: _mock.time(index), 14 | })); 15 | 16 | export const _analyticOrderTimeline = [...Array(5)].map((_, index) => ({ 17 | id: _mock.id(index), 18 | title: [ 19 | '1983, orders, $4220', 20 | '12 Invoices have been paid', 21 | 'Order #37745 from September', 22 | 'New order placed #XF-2356', 23 | 'New order placed #XF-2346', 24 | ][index], 25 | type: `order${index + 1}`, 26 | time: _mock.time(index), 27 | })); 28 | 29 | export const _analyticTraffic = [ 30 | { 31 | name: 'FaceBook', 32 | value: 323234, 33 | icon: , 34 | }, 35 | { 36 | name: 'Google', 37 | value: 341212, 38 | icon: , 39 | }, 40 | { 41 | name: 'Linkedin', 42 | value: 411213, 43 | icon: , 44 | }, 45 | { 46 | name: 'Twitter', 47 | value: 443232, 48 | icon: , 49 | }, 50 | ]; 51 | -------------------------------------------------------------------------------- /src/_mock/_booking.js: -------------------------------------------------------------------------------- 1 | import _mock from './_mock'; 2 | import { randomInArray } from './funcs'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export const _bookings = [...Array(5)].map((_, index) => ({ 7 | id: _mock.id(index), 8 | name: _mock.name.fullName(index), 9 | avatar: _mock.image.avatar(index), 10 | checkIn: _mock.time(index), 11 | checkOut: _mock.time(index), 12 | phoneNumber: _mock.phoneNumber(index), 13 | status: randomInArray(['pending', 'un_paid', 'paid']), 14 | roomType: randomInArray(['double', 'king', 'single']), 15 | })); 16 | 17 | export const _bookingsOverview = [...Array(3)].map((_, index) => ({ 18 | status: ['Pending', 'Cancel', 'Done'][index], 19 | quantity: _mock.number.percent(index) * 1000, 20 | value: _mock.number.percent(index), 21 | })); 22 | 23 | export const _bookingReview = [...Array(5)].map((_, index) => ({ 24 | id: _mock.id(index), 25 | name: _mock.name.fullName(index), 26 | description: _mock.text.description(index), 27 | avatar: _mock.image.avatar(index), 28 | rating: _mock.number.rating(index), 29 | postedAt: _mock.time(index), 30 | tags: ['Great Sevice', 'Recommended', 'Best Price'], 31 | })); 32 | 33 | export const _bookingNew = [...Array(5)].map((_, index) => ({ 34 | id: _mock.id(index), 35 | name: _mock.name.fullName(index), 36 | avatar: _mock.image.avatar(index), 37 | bookdAt: _mock.time(index), 38 | roomNumber: 'A-21', 39 | roomType: randomInArray(['double', 'king', 'single']), 40 | person: '3-5', 41 | cover: `https://minimal-assets-api-dev.vercel.app/assets/images/rooms/room-${index + 1}.jpg`, 42 | })); 43 | -------------------------------------------------------------------------------- /src/_mock/boolean.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export const boolean = [ 4 | true, 5 | true, 6 | true, 7 | false, 8 | false, 9 | true, 10 | false, 11 | false, 12 | false, 13 | false, 14 | true, 15 | true, 16 | true, 17 | false, 18 | false, 19 | false, 20 | true, 21 | false, 22 | false, 23 | false, 24 | true, 25 | false, 26 | false, 27 | true, 28 | true, 29 | true, 30 | false, 31 | false, 32 | true, 33 | true, 34 | false, 35 | true, 36 | false, 37 | true, 38 | true, 39 | true, 40 | false, 41 | true, 42 | false, 43 | false 44 | ]; 45 | -------------------------------------------------------------------------------- /src/_mock/company.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export const company = [ 4 | 'Lueilwitz and Sons', 5 | 'Gleichner, Mueller and Tromp', 6 | 'Nikolaus - Leuschke', 7 | 'Hegmann, Kreiger and Bayer', 8 | 'Grimes Inc', 9 | 'Durgan - Murazik', 10 | 'Altenwerth, Medhurst and Roberts', 11 | 'Raynor Group', 12 | 'Mraz, Donnelly and Collins', 13 | 'Padberg - Bailey', 14 | 'Heidenreich, Stokes and Parker', 15 | 'Pagac and Sons', 16 | 'Rempel, Hand and Herzog', 17 | 'Dare - Treutel', 18 | 'Kihn, Marquardt and Crist', 19 | 'Nolan - Kunde', 20 | 'Wuckert Inc', 21 | 'Dibbert Inc', 22 | 'Goyette and Sons', 23 | 'Feest Group', 24 | 'Bosco and Sons', 25 | 'Bartell - Kovacek', 26 | 'Schimmel - Raynor', 27 | 'Tremblay LLC', 28 | 'Hills - Mitchell', 29 | 'Rogahn LLC', 30 | 'Kuhn, Osinski and Morar', 31 | 'Schmitt Inc', 32 | 'Breitenberg - Rosenbaum', 33 | "O'Keefe, Schneider and Mraz", 34 | 'Rohan, Langworth and Kling', 35 | 'Morar and Sons', 36 | 'Mraz LLC', 37 | 'Rowe, Parisian and Kub', 38 | 'Marquardt - Hane', 39 | 'Medhurst Group', 40 | 'Nikolaus - Lang', 41 | 'Effertz, Mohr and Olson', 42 | 'Anderson - Kris', 43 | 'Runolfsson Group' 44 | ]; 45 | -------------------------------------------------------------------------------- /src/_mock/email.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export const email = [ 4 | 'nannie_abernathy70@yahoo.com', 5 | 'ashlynn_ohara62@gmail.com', 6 | 'milo.farrell@hotmail.com', 7 | 'violet.ratke86@yahoo.com', 8 | 'letha_lubowitz24@yahoo.com', 9 | 'aditya_greenfelder31@gmail.com', 10 | 'lenna_bergnaum27@hotmail.com', 11 | 'luella.ryan33@gmail.com', 12 | 'joana.simonis84@gmail.com', 13 | 'marjolaine_white94@gmail.com', 14 | 'vergie_block82@hotmail.com', 15 | 'vito.hudson@hotmail.com', 16 | 'tyrel_greenholt@gmail.com', 17 | 'dwight.block85@yahoo.com', 18 | 'mireya13@hotmail.com', 19 | 'dasia_jenkins@hotmail.com', 20 | 'benny89@yahoo.com', 21 | 'dawn.goyette@gmail.com', 22 | 'zella_hickle4@yahoo.com', 23 | 'avery43@hotmail.com', 24 | 'olen_legros@gmail.com', 25 | 'jimmie.gerhold73@hotmail.com', 26 | 'genevieve.powlowski@hotmail.com', 27 | 'louie.kuphal39@gmail.com', 28 | 'enoch.cruickshank@gmail.com', 29 | 'arlo_mccullough@gmail.com', 30 | 'sadie18@yahoo.com', 31 | 'aric67@gmail.com', 32 | 'mack_deckow53@gmail.com', 33 | 'constantin91@yahoo.com', 34 | 'lonny84@hotmail.com', 35 | 'gus56@hotmail.com', 36 | 'brennon64@yahoo.com', 37 | 'hortense.streich@hotmail.com', 38 | 'kallie_powlowski57@hotmail.com', 39 | 'meghan.kemmer@hotmail.com', 40 | 'bella.mraz14@yahoo.com', 41 | 'barney88@gmail.com', 42 | 'diamond_johns@hotmail.com', 43 | 'gus80@hotmail.com' 44 | ]; 45 | -------------------------------------------------------------------------------- /src/_mock/funcs.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export function randomNumber(number) { 4 | return Math.floor(Math.random() * number) + 1; 5 | } 6 | 7 | export function randomNumberRange(min, max) { 8 | return Math.floor(Math.random() * (max - min + 1)) + min; 9 | } 10 | 11 | export function randomInArray(array) { 12 | return array[Math.floor(Math.random() * array.length)]; 13 | } 14 | -------------------------------------------------------------------------------- /src/_mock/index.js: -------------------------------------------------------------------------------- 1 | import _mock from './_mock'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export * from './_app'; 6 | export * from './_user'; 7 | export * from './_plans'; 8 | export * from './_others'; 9 | export * from './_booking'; 10 | export * from './_banking'; 11 | export * from './_invoice'; 12 | export * from './_ecommerce'; 13 | export * from './_analytics'; 14 | export * from './_countries'; 15 | export * from './_top100Films'; 16 | 17 | export default _mock; 18 | -------------------------------------------------------------------------------- /src/_mock/number.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export const price = [ 4 | 16.19, 35.71, 34.3, 93.1, 55.47, 89.09, 44.39, 26.92, 45.35, 26.96, 78.22, 35.54, 90.69, 63.61, 5 | 67.55, 94.75, 75.78, 39.6, 52.84, 72.8, 83.08, 85.02, 69.22, 60.96, 84.7, 16.68, 78.83, 58.07, 6 | 65.8, 55.69, 87.55, 44.74, 27.42, 84, 76.17, 43.83, 76.39, 17.42, 42.3, 12.45 7 | ]; 8 | 9 | export const rating = [ 10 | 2.5, 2, 4.9, 2, 4, 5, 4.9, 5, 3.7, 2.5, 2, 4.9, 4.8, 4, 2, 3.7, 1.4, 2.4, 1.8, 5, 2.9, 3.9, 3.9, 11 | 1.8, 5, 2.6, 3.1, 3.9, 1.2, 3.2, 4.1, 5, 4.5, 4.1, 2.3, 2.4, 5, 3.1, 4.9, 1.7 12 | ]; 13 | 14 | export const age = [ 15 | 52, 43, 56, 25, 22, 53, 38, 50, 55, 37, 16, 27, 55, 41, 52, 32, 34, 52, 31, 53, 23, 48, 43, 41, 16 | 19, 21, 17, 29, 32, 54, 38, 34, 49, 33, 55, 50, 24, 27, 23, 23 17 | ]; 18 | 19 | export const percent = [ 20 | 8.62, 86.36, 73.99, 79, 63.41, 58.79, 12.32, 88.44, 45.06, 91.64, 88.41, 73.08, 39.14, 89.34, 21 | 43.37, 34.45, 24.04, 80.96, 72.91, 47.59, 2.46, 3.33, 99.31, 47.6, 34.09, 50.61, 66.13, 46.69, 22 | 92.43, 31.41, 90.85, 36.32, 38.84, 25.6, 87.61, 1.31, 89.32, 41.23, 85.9, 62.63 23 | ]; 24 | -------------------------------------------------------------------------------- /src/_mock/phoneNumber.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export const phoneNumber = [ 4 | '365-374-4961', 5 | '904-966-2836', 6 | '399-757-9909', 7 | '692-767-2903', 8 | '990-588-5716', 9 | '955-439-2578', 10 | '226-924-4058', 11 | '552-917-1454', 12 | '285-840-9338', 13 | '306-269-2446', 14 | '883-373-6253', 15 | '476-509-8866', 16 | '201-465-1954', 17 | '538-295-9408', 18 | '531-492-6028', 19 | '981-699-7588', 20 | '500-268-4826', 21 | '205-952-3828', 22 | '222-255-5190', 23 | '408-439-8033', 24 | '272-940-8266', 25 | '812-685-8057', 26 | '353-801-5212', 27 | '606-285-8928', 28 | '202-767-8621', 29 | '222-830-0731', 30 | '964-940-3166', 31 | '262-702-2396', 32 | '886-261-9789', 33 | '352-390-5069', 34 | '343-907-8334', 35 | '575-347-2399', 36 | '749-228-5604', 37 | '774-452-2071', 38 | '607-841-0447', 39 | '395-619-2157', 40 | '233-834-0373', 41 | '586-880-2602', 42 | '746-772-0722', 43 | '638-615-3365,' 44 | ]; 45 | -------------------------------------------------------------------------------- /src/_mock/role.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export const role = [ 4 | 'ux designer', 5 | 'full stack designer', 6 | 'backend developer', 7 | 'ux designer', 8 | 'ux designer', 9 | 'project manager', 10 | 'leader', 11 | 'backend developer', 12 | 'project manager', 13 | 'ui designer', 14 | 'ui/ux designer', 15 | 'ui/ux designer', 16 | 'ui designer', 17 | 'backend developer', 18 | 'backend developer', 19 | 'front end developer', 20 | 'backend developer', 21 | 'full stack designer', 22 | 'full stack developer', 23 | 'backend developer', 24 | 'ux designer', 25 | 'ui designer', 26 | 'project manager', 27 | 'ui/ux designer', 28 | 'ui designer', 29 | 'project manager', 30 | 'full stack developer', 31 | 'hr manager', 32 | 'hr manager', 33 | 'ui/ux designer', 34 | 'project manager', 35 | 'full stack designer', 36 | 'ui designer', 37 | 'leader', 38 | 'front end developer', 39 | 'ui/ux designer', 40 | 'project manager', 41 | 'ui/ux designer', 42 | 'ui designer', 43 | 'full stack designer', 44 | ]; 45 | -------------------------------------------------------------------------------- /src/assets/icon_plan_free.js: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | // @mui 3 | import { useTheme } from '@mui/material/styles'; 4 | import { Box } from '@mui/material'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | function PlanFreeIcon({ ...other }) { 9 | const theme = useTheme(); 10 | 11 | const PRIMARY_MAIN = theme.palette.primary.main; 12 | 13 | const PRIMARY_DARK = theme.palette.primary.dark; 14 | 15 | const PRIMARY_DARKER = theme.palette.primary.darker; 16 | 17 | return ( 18 | 19 | 26 | 27 | 28 | 29 | 33 | 34 | 38 | 39 | 44 | 45 | 46 | 47 | ); 48 | } 49 | 50 | export default memo(PlanFreeIcon); 51 | -------------------------------------------------------------------------------- /src/assets/illustration_background.js: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | // @mui 3 | import { useTheme } from '@mui/material/styles'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | function BackgroundIllustration() { 8 | const theme = useTheme(); 9 | 10 | const PRIMARY_MAIN = theme.palette.primary.main; 11 | 12 | return ( 13 | <> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | ); 29 | } 30 | 31 | export default memo(BackgroundIllustration); 32 | -------------------------------------------------------------------------------- /src/assets/index.js: -------------------------------------------------------------------------------- 1 | export { default as DocIllustration } from './illustration_doc'; 2 | export { default as SeoIllustration } from './illustration_seo'; 3 | export { default as UploadIllustration } from './illustration_upload'; 4 | export { default as ForbiddenIllustration } from './illustration_403'; 5 | export { default as SeverErrorIllustration } from './illustration_500'; 6 | export { default as BookingIllustration } from './illustration_booking'; 7 | export { default as CheckInIllustration } from './illustration_checkin'; 8 | export { default as PageNotFoundIllustration } from './illustration_404'; 9 | export { default as CheckOutIllustration } from './illustration_checkout'; 10 | export { default as MotivationIllustration } from './illustration_motivation'; 11 | export { default as ComingSoonIllustration } from './illustration_coming_soon'; 12 | export { default as MaintenanceIllustration } from './illustration_maintenance'; 13 | export { default as OrderCompleteIllustration } from './illustration_order_complete'; 14 | 15 | export { default as SentIcon } from './icon_sent'; 16 | export { default as PlanFreeIcon } from './icon_plan_free'; 17 | export { default as PlanStarterIcon } from './icon_plan_starter'; 18 | export { default as PlanPremiumIcon } from './icon_plan_premium'; 19 | -------------------------------------------------------------------------------- /src/components/Avatar.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { forwardRef } from 'react'; 3 | import { useTheme } from '@mui/material/styles'; 4 | import { Avatar as MUIAvatar } from '@mui/material'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | const Avatar = forwardRef(({ color = 'default', children, sx, ...other }, ref) => { 9 | const theme = useTheme(); 10 | 11 | if (color === 'default') { 12 | return ( 13 | 14 | {children} 15 | 16 | ); 17 | } 18 | 19 | return ( 20 | 30 | {children} 31 | 32 | ); 33 | }); 34 | 35 | Avatar.propTypes = { 36 | children: PropTypes.node, 37 | sx: PropTypes.object, 38 | color: PropTypes.oneOf(['default', 'primary', 'secondary', 'info', 'success', 'warning', 'error']), 39 | }; 40 | 41 | export default Avatar; 42 | -------------------------------------------------------------------------------- /src/components/CopyClipboard.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { useSnackbar } from 'notistack'; 4 | import { CopyToClipboard } from 'react-copy-to-clipboard'; 5 | // @mui 6 | import { Tooltip, TextField, IconButton, InputAdornment } from '@mui/material'; 7 | // 8 | import Iconify from './Iconify'; 9 | 10 | // ---------------------------------------------------------------------- 11 | 12 | CopyClipboard.propTypes = { 13 | value: PropTypes.string, 14 | }; 15 | 16 | export default function CopyClipboard({ value, ...other }) { 17 | const { enqueueSnackbar } = useSnackbar(); 18 | const [state, setState] = useState({ 19 | value, 20 | copied: false, 21 | }); 22 | 23 | const handleChange = (event) => { 24 | setState({ value: event.target.value, copied: false }); 25 | }; 26 | 27 | const onCopy = () => { 28 | setState({ ...state, copied: true }); 29 | if (state.value) { 30 | enqueueSnackbar('Copied!'); 31 | } 32 | }; 33 | 34 | return ( 35 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ), 51 | }} 52 | {...other} 53 | /> 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /src/components/EmptyContent.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { styled } from '@mui/material/styles'; 4 | import { Typography } from '@mui/material'; 5 | // 6 | import Image from './Image'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | const RootStyle = styled('div')(({ theme }) => ({ 11 | height: '100%', 12 | display: 'flex', 13 | textAlign: 'center', 14 | alignItems: 'center', 15 | flexDirection: 'column', 16 | justifyContent: 'center', 17 | padding: theme.spacing(8, 2), 18 | })); 19 | 20 | // ---------------------------------------------------------------------- 21 | 22 | EmptyContent.propTypes = { 23 | title: PropTypes.string.isRequired, 24 | img: PropTypes.string, 25 | description: PropTypes.string, 26 | }; 27 | 28 | export default function EmptyContent({ title, description, img, ...other }) { 29 | return ( 30 | 31 | empty content 38 | 39 | 40 | {title} 41 | 42 | 43 | {description && ( 44 | 45 | {description} 46 | 47 | )} 48 | 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /src/components/HeaderBreadcrumbs.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { Box, Typography, Link } from '@mui/material'; 4 | // 5 | import Breadcrumbs from './Breadcrumbs'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | HeaderBreadcrumbs.propTypes = { 10 | links: PropTypes.array, 11 | action: PropTypes.node, 12 | heading: PropTypes.string.isRequired, 13 | moreLink: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), 14 | sx: PropTypes.object, 15 | }; 16 | 17 | export default function HeaderBreadcrumbs({ links, action, heading, moreLink = '' || [], sx, ...other }) { 18 | return ( 19 | 20 | 21 | 22 | 23 | {heading} 24 | 25 | 26 | 27 | 28 | {action && {action}} 29 | 30 | 31 | 32 | {typeof moreLink === 'string' ? ( 33 | 34 | {moreLink} 35 | 36 | ) : ( 37 | moreLink.map((href) => ( 38 | 47 | {href} 48 | 49 | )) 50 | )} 51 | 52 | 53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /src/components/Iconify.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // icons 3 | import { Icon } from '@iconify/react'; 4 | // @mui 5 | import { Box } from '@mui/material'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | Iconify.propTypes = { 10 | icon: PropTypes.oneOfType([PropTypes.element, PropTypes.string]), 11 | sx: PropTypes.object, 12 | }; 13 | 14 | export default function Iconify({ icon, sx, ...other }) { 15 | return ; 16 | } 17 | -------------------------------------------------------------------------------- /src/components/InputStyle.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { styled } from '@mui/material/styles'; 3 | import { TextField } from '@mui/material'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | const InputStyle = styled(TextField, { 8 | shouldForwardProp: (prop) => prop !== 'stretchStart', 9 | })(({ stretchStart, theme }) => ({ 10 | '& .MuiOutlinedInput-root': { 11 | transition: theme.transitions.create(['box-shadow', 'width'], { 12 | easing: theme.transitions.easing.easeInOut, 13 | duration: theme.transitions.duration.shorter, 14 | }), 15 | '&.Mui-focused': { 16 | boxShadow: theme.customShadows.z12, 17 | }, 18 | ...(stretchStart && { 19 | width: stretchStart, 20 | '&.Mui-focused': { 21 | boxShadow: theme.customShadows.z12, 22 | [theme.breakpoints.up('sm')]: { 23 | width: stretchStart + 60, 24 | }, 25 | }, 26 | }), 27 | }, 28 | '& fieldset': { 29 | borderWidth: `1px !important`, 30 | borderColor: `${theme.palette.grey[500_32]} !important`, 31 | }, 32 | })); 33 | 34 | export default InputStyle; 35 | -------------------------------------------------------------------------------- /src/components/Logo.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Link as RouterLink } from 'react-router-dom'; 3 | // @mui 4 | import { Box } from '@mui/material'; 5 | 6 | import Image from './Image'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | Logo.propTypes = { 11 | disabledLink: PropTypes.bool, 12 | sx: PropTypes.object, 13 | isloading: PropTypes.bool, 14 | iscollapse: PropTypes.bool, 15 | }; 16 | 17 | export default function Logo({ disabledLink = false, sx, isloading, iscollapse }) { 18 | // OR 19 | // const logo = '/logo/logo_single.svg'; 20 | 21 | const logo = 22 | isloading || iscollapse ? ( 23 | 24 | 25 | 26 | ) : ( 27 | 28 | 29 | 30 | ); 31 | 32 | if (disabledLink) { 33 | return <>{logo}; 34 | } 35 | 36 | return {logo}; 37 | } 38 | -------------------------------------------------------------------------------- /src/components/MyAvatar.js: -------------------------------------------------------------------------------- 1 | // hooks 2 | import useAuth from '../hooks/useAuth'; 3 | // utils 4 | import createAvatar from '../utils/createAvatar'; 5 | // 6 | import Avatar from './Avatar'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | export default function MyAvatar({ ...other }) { 11 | const { user } = useAuth(); 12 | 13 | return ( 14 | 20 | {createAvatar(user?.name).name} 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /src/components/Page.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Helmet } from 'react-helmet-async'; 3 | import { forwardRef } from 'react'; 4 | // @mui 5 | import { Box } from '@mui/material'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | const Page = forwardRef(({ children, title = '', meta, ...other }, ref) => ( 10 | <> 11 | 12 | {`${title}`} 13 | {meta} 14 | 15 | 16 | 17 | {children} 18 | 19 | 20 | )); 21 | 22 | Page.propTypes = { 23 | children: PropTypes.node.isRequired, 24 | title: PropTypes.string, 25 | meta: PropTypes.node, 26 | }; 27 | 28 | export default Page; 29 | -------------------------------------------------------------------------------- /src/components/ProgressBar.js: -------------------------------------------------------------------------------- 1 | import NProgress from 'nprogress'; 2 | import { useEffect, useMemo } from 'react'; 3 | // @mui 4 | import { useTheme } from '@mui/material/styles'; 5 | import { GlobalStyles } from '@mui/material'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | export function ProgressBarStyle() { 10 | const theme = useTheme(); 11 | 12 | return ( 13 | 40 | ); 41 | } 42 | 43 | export default function ProgressBar() { 44 | NProgress.configure({ 45 | showSpinner: false, 46 | }); 47 | 48 | useMemo(() => { 49 | NProgress.start(); 50 | }, []); 51 | 52 | useEffect(() => { 53 | NProgress.done(); 54 | }, []); 55 | 56 | return null; 57 | } 58 | -------------------------------------------------------------------------------- /src/components/ScrollToTop.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import { useLocation } from 'react-router-dom'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function ScrollToTop() { 7 | const { pathname } = useLocation(); 8 | 9 | useEffect(() => { 10 | window.scrollTo(0, 0); 11 | }, [pathname]); 12 | 13 | return null; 14 | } 15 | -------------------------------------------------------------------------------- /src/components/SearchNotFound.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Paper, Typography } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | SearchNotFound.propTypes = { 7 | searchQuery: PropTypes.string, 8 | }; 9 | 10 | export default function SearchNotFound({ searchQuery = '', ...other }) { 11 | return searchQuery ? ( 12 | 13 | 14 | Not found 15 | 16 | 17 | No results found for   18 | "{searchQuery}". Try checking for typos or using complete words. 19 | 20 | 21 | ) : ( 22 | Please enter keywords 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/components/SvgIconStyle.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Box } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | SvgIconStyle.propTypes = { 7 | src: PropTypes.string.isRequired, 8 | sx: PropTypes.object, 9 | }; 10 | 11 | export default function SvgIconStyle({ src, sx }) { 12 | return ( 13 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /src/components/TextIconLabel.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { Stack } from '@mui/material'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | TextIconLabel.propTypes = { 8 | endIcon: PropTypes.bool, 9 | icon: PropTypes.any, 10 | sx: PropTypes.object, 11 | value: PropTypes.any, 12 | }; 13 | 14 | export default function TextIconLabel({ icon, value, endIcon = false, sx, ...other }) { 15 | return ( 16 | 25 | {!endIcon && icon} 26 | {value} 27 | {endIcon && icon} 28 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /src/components/TextMaxLine.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { forwardRef } from 'react'; 3 | // @mui 4 | import { Typography, Link } from '@mui/material'; 5 | // utils 6 | import GetFontValue from '../utils/getFontValue'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | const TextMaxLine = forwardRef( 11 | ({ asLink, variant = 'body1', line = 2, persistent = false, children, sx, ...other }, ref) => { 12 | const { lineHeight } = GetFontValue(variant); 13 | 14 | const style = { 15 | overflow: 'hidden', 16 | textOverflow: 'ellipsis', 17 | display: '-webkit-box', 18 | WebkitLineClamp: line, 19 | WebkitBoxOrient: 'vertical', 20 | ...(persistent && { 21 | height: lineHeight * line, 22 | }), 23 | ...sx, 24 | }; 25 | 26 | if (asLink) { 27 | return ( 28 | 29 | {children} 30 | 31 | ); 32 | } 33 | 34 | return ( 35 | 36 | {children} 37 | 38 | ); 39 | } 40 | ); 41 | 42 | TextMaxLine.propTypes = { 43 | asLink: PropTypes.bool, 44 | children: PropTypes.node.isRequired, 45 | line: PropTypes.number, 46 | persistent: PropTypes.bool, 47 | sx: PropTypes.object, 48 | variant: PropTypes.oneOf([ 49 | 'body1', 50 | 'body2', 51 | 'button', 52 | 'caption', 53 | 'h1', 54 | 'h2', 55 | 'h3', 56 | 'h4', 57 | 'h5', 58 | 'h6', 59 | 'inherit', 60 | 'overline', 61 | 'subtitle1', 62 | 'subtitle2', 63 | ]), 64 | }; 65 | 66 | export default TextMaxLine; 67 | -------------------------------------------------------------------------------- /src/components/animate/DialogAnimate.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { m, AnimatePresence } from 'framer-motion'; 3 | // @mui 4 | import { Dialog, Box, Paper } from '@mui/material'; 5 | // 6 | import { varFade } from './variants'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | DialogAnimate.propTypes = { 11 | children: PropTypes.node.isRequired, 12 | onClose: PropTypes.func, 13 | open: PropTypes.bool.isRequired, 14 | sx: PropTypes.object, 15 | variants: PropTypes.object 16 | }; 17 | 18 | export default function DialogAnimate({ open = false, variants, onClose, children, sx, ...other }) { 19 | return ( 20 | 21 | {open && ( 22 | ( 28 | 45 | 46 | 47 | {props.children} 48 | 49 | 50 | )} 51 | {...other} 52 | > 53 | {children} 54 | 55 | )} 56 | 57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /src/components/animate/IconButtonAnimate.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { m } from 'framer-motion'; 3 | import { forwardRef } from 'react'; 4 | // @mui 5 | import { Box, IconButton } from '@mui/material'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | const IconButtonAnimate = forwardRef(({ children, size = 'medium', ...other }, ref) => ( 10 | 11 | 12 | {children} 13 | 14 | 15 | )); 16 | 17 | IconButtonAnimate.propTypes = { 18 | children: PropTypes.node.isRequired, 19 | color: PropTypes.oneOf(['inherit', 'default', 'primary', 'secondary', 'info', 'success', 'warning', 'error']), 20 | size: PropTypes.oneOf(['small', 'medium', 'large']) 21 | }; 22 | 23 | export default IconButtonAnimate; 24 | 25 | // ---------------------------------------------------------------------- 26 | 27 | const varSmall = { 28 | hover: { scale: 1.1 }, 29 | tap: { scale: 0.95 } 30 | }; 31 | 32 | const varMedium = { 33 | hover: { scale: 1.09 }, 34 | tap: { scale: 0.97 } 35 | }; 36 | 37 | const varLarge = { 38 | hover: { scale: 1.08 }, 39 | tap: { scale: 0.99 } 40 | }; 41 | 42 | AnimateWrap.propTypes = { 43 | children: PropTypes.node.isRequired, 44 | size: PropTypes.oneOf(['small', 'medium', 'large']) 45 | }; 46 | 47 | function AnimateWrap({ size, children }) { 48 | const isSmall = size === 'small'; 49 | const isLarge = size === 'large'; 50 | 51 | return ( 52 | 61 | {children} 62 | 63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /src/components/animate/MotionContainer.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { m } from 'framer-motion'; 3 | // @mui 4 | import { Box } from '@mui/material'; 5 | // 6 | import { varContainer } from './variants'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | MotionContainer.propTypes = { 11 | action: PropTypes.bool, 12 | animate: PropTypes.bool, 13 | children: PropTypes.node.isRequired 14 | }; 15 | 16 | export default function MotionContainer({ animate, action = false, children, ...other }) { 17 | if (action) { 18 | return ( 19 | 26 | {children} 27 | 28 | ); 29 | } 30 | 31 | return ( 32 | 33 | {children} 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /src/components/animate/MotionLazyContainer.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { LazyMotion } from 'framer-motion'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | // eslint-disable-next-line import/extensions 7 | const loadFeatures = () => import('./features.js').then((res) => res.default); 8 | 9 | MotionLazyContainer.propTypes = { 10 | children: PropTypes.node 11 | }; 12 | 13 | export default function MotionLazyContainer({ children }) { 14 | return ( 15 | 16 | {children} 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /src/components/animate/MotionViewport.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { m } from 'framer-motion'; 3 | // @mui 4 | import { Box } from '@mui/material'; 5 | // hooks 6 | import useResponsive from '../../hooks/useResponsive'; 7 | // 8 | import { varContainer } from '.'; 9 | 10 | // ---------------------------------------------------------------------- 11 | 12 | MotionViewport.propTypes = { 13 | children: PropTypes.node.isRequired, 14 | disableAnimatedMobile: PropTypes.bool, 15 | }; 16 | 17 | export default function MotionViewport({ children, disableAnimatedMobile = true, ...other }) { 18 | const isDesktop = useResponsive('up', 'sm'); 19 | 20 | if (!isDesktop && disableAnimatedMobile) { 21 | return {children}; 22 | } 23 | 24 | return ( 25 | 33 | {children} 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /src/components/animate/TextAnimate.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { m } from 'framer-motion'; 3 | // @mui 4 | import { Box } from '@mui/material'; 5 | // 6 | import { varFade } from './variants'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | TextAnimate.propTypes = { 11 | text: PropTypes.string.isRequired, 12 | variants: PropTypes.object, 13 | sx: PropTypes.object 14 | }; 15 | 16 | export default function TextAnimate({ text, variants, sx, ...other }) { 17 | return ( 18 | 28 | {text.split('').map((letter, index) => ( 29 | 30 | {letter} 31 | 32 | ))} 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /src/components/animate/features.js: -------------------------------------------------------------------------------- 1 | import { domMax } from 'framer-motion'; 2 | 3 | export default domMax; 4 | -------------------------------------------------------------------------------- /src/components/animate/index.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export * from './variants'; 4 | 5 | export { default as DialogAnimate } from './DialogAnimate'; 6 | export { default as TextAnimate } from './TextAnimate'; 7 | 8 | export { default as FabButtonAnimate } from './FabButtonAnimate'; 9 | export { default as IconButtonAnimate } from './IconButtonAnimate'; 10 | 11 | export { default as MotionViewport } from './MotionViewport'; 12 | export { default as MotionContainer } from './MotionContainer'; 13 | export { default as MotionLazyContainer } from './MotionLazyContainer'; 14 | -------------------------------------------------------------------------------- /src/components/animate/variants/actions.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export const varHover = (scale) => ({ 4 | hover: { 5 | scale: scale || 1.1 6 | } 7 | }); 8 | -------------------------------------------------------------------------------- /src/components/animate/variants/container.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export const varContainer = (props) => { 4 | const staggerIn = props?.staggerIn || 0.05; 5 | const delayIn = props?.staggerIn || 0.05; 6 | const staggerOut = props?.staggerIn || 0.05; 7 | 8 | return { 9 | animate: { 10 | transition: { 11 | staggerChildren: staggerIn, 12 | delayChildren: delayIn 13 | } 14 | }, 15 | exit: { 16 | transition: { 17 | staggerChildren: staggerOut, 18 | staggerDirection: -1 19 | } 20 | } 21 | }; 22 | }; 23 | -------------------------------------------------------------------------------- /src/components/animate/variants/flip.js: -------------------------------------------------------------------------------- 1 | import { varTranEnter, varTranExit } from './transition'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export const varFlip = (props) => { 6 | const durationIn = props?.durationIn; 7 | const durationOut = props?.durationOut; 8 | const easeIn = props?.easeIn; 9 | const easeOut = props?.easeOut; 10 | 11 | return { 12 | // IN 13 | inX: { 14 | initial: { rotateX: -180, opacity: 0 }, 15 | animate: { rotateX: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) }, 16 | exit: { rotateX: -180, opacity: 0, transition: varTranExit({ durationOut, easeOut }) } 17 | }, 18 | inY: { 19 | initial: { rotateY: -180, opacity: 0 }, 20 | animate: { rotateY: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) }, 21 | exit: { rotateY: -180, opacity: 0, transition: varTranExit({ durationOut, easeOut }) } 22 | }, 23 | 24 | // OUT 25 | outX: { 26 | initial: { rotateX: 0, opacity: 1 }, 27 | animate: { rotateX: 70, opacity: 0, transition: varTranExit({ durationOut, easeOut }) } 28 | }, 29 | outY: { 30 | initial: { rotateY: 0, opacity: 1 }, 31 | animate: { rotateY: 70, opacity: 0, transition: varTranExit({ durationOut, easeOut }) } 32 | } 33 | }; 34 | }; 35 | -------------------------------------------------------------------------------- /src/components/animate/variants/index.js: -------------------------------------------------------------------------------- 1 | export * from './path'; 2 | export * from './fade'; 3 | export * from './zoom'; 4 | export * from './flip'; 5 | export * from './slide'; 6 | export * from './scale'; 7 | export * from './bounce'; 8 | export * from './rotate'; 9 | export * from './actions'; 10 | export * from './container'; 11 | export * from './transition'; 12 | export * from './background'; 13 | -------------------------------------------------------------------------------- /src/components/animate/variants/path.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export const TRANSITION = { 4 | duration: 2, 5 | ease: [0.43, 0.13, 0.23, 0.96] 6 | }; 7 | 8 | export const varPath = { 9 | animate: { 10 | fillOpacity: [0, 0, 1], 11 | pathLength: [1, 0.4, 0], 12 | transition: TRANSITION 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /src/components/animate/variants/rotate.js: -------------------------------------------------------------------------------- 1 | // 2 | import { varTranEnter, varTranExit } from './transition'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export const varRotate = (props) => { 7 | const durationIn = props?.durationIn; 8 | const durationOut = props?.durationOut; 9 | const easeIn = props?.easeIn; 10 | const easeOut = props?.easeOut; 11 | 12 | return { 13 | // IN 14 | in: { 15 | initial: { opacity: 0, rotate: -360 }, 16 | animate: { opacity: 1, rotate: 0, transition: varTranEnter({ durationIn, easeIn }) }, 17 | exit: { opacity: 0, rotate: -360, transition: varTranExit({ durationOut, easeOut }) } 18 | }, 19 | 20 | // OUT 21 | out: { 22 | initial: { opacity: 1, rotate: 0 }, 23 | animate: { opacity: 0, rotate: -360, transition: varTranExit({ durationOut, easeOut }) } 24 | } 25 | }; 26 | }; 27 | -------------------------------------------------------------------------------- /src/components/animate/variants/scale.js: -------------------------------------------------------------------------------- 1 | // 2 | import { varTranEnter, varTranExit } from './transition'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export const varScale = (props) => { 7 | const durationIn = props?.durationIn; 8 | const durationOut = props?.durationOut; 9 | const easeIn = props?.easeIn; 10 | const easeOut = props?.easeOut; 11 | 12 | return { 13 | // IN 14 | inX: { 15 | initial: { scaleX: 0, opacity: 0 }, 16 | animate: { scaleX: 1, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) }, 17 | exit: { scaleX: 0, opacity: 0, transition: varTranExit({ durationOut, easeOut }) } 18 | }, 19 | inY: { 20 | initial: { scaleY: 0, opacity: 0 }, 21 | animate: { scaleY: 1, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) }, 22 | exit: { scaleY: 0, opacity: 0, transition: varTranExit({ durationOut, easeOut }) } 23 | }, 24 | 25 | // OUT 26 | outX: { 27 | initial: { scaleX: 1, opacity: 1 }, 28 | animate: { scaleX: 0, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) } 29 | }, 30 | outY: { 31 | initial: { scaleY: 1, opacity: 1 }, 32 | animate: { scaleY: 0, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) } 33 | } 34 | }; 35 | }; 36 | -------------------------------------------------------------------------------- /src/components/animate/variants/transition.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export const varTranHover = (props) => { 4 | const duration = props?.duration || 0.32; 5 | const ease = props?.ease || [0.43, 0.13, 0.23, 0.96]; 6 | 7 | return { duration, ease }; 8 | }; 9 | 10 | export const varTranEnter = (props) => { 11 | const duration = props?.durationIn || 0.64; 12 | const ease = props?.easeIn || [0.43, 0.13, 0.23, 0.96]; 13 | 14 | return { duration, ease }; 15 | }; 16 | 17 | export const varTranExit = (props) => { 18 | const duration = props?.durationOut || 0.48; 19 | const ease = props?.easeOut || [0.43, 0.13, 0.23, 0.96]; 20 | 21 | return { duration, ease }; 22 | }; 23 | -------------------------------------------------------------------------------- /src/components/carousel/index.js: -------------------------------------------------------------------------------- 1 | export { default as CarouselDots } from './CarouselDots'; 2 | export { default as CarouselArrows } from './CarouselArrows'; 3 | export { default as CarouselArrowIndex } from './CarouselArrowIndex'; 4 | -------------------------------------------------------------------------------- /src/components/chart/index.js: -------------------------------------------------------------------------------- 1 | export { default as ChartStyle } from './ChartStyle'; 2 | export { default as BaseOptionChart } from './BaseOptionChart'; 3 | -------------------------------------------------------------------------------- /src/components/color-utils/ColorPreview.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { alpha, styled } from '@mui/material/styles'; 4 | import { Box, Typography } from '@mui/material'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | const RootStyle = styled(Box)(() => ({ 9 | display: 'flex', 10 | alignItems: 'center', 11 | justifyContent: 'flex-end', 12 | })); 13 | 14 | const IconStyle = styled('div')(({ theme }) => ({ 15 | marginLeft: -4, 16 | borderRadius: '50%', 17 | width: theme.spacing(2), 18 | height: theme.spacing(2), 19 | border: `solid 2px ${theme.palette.background.paper}`, 20 | boxShadow: `inset -1px 1px 2px ${alpha(theme.palette.common.black, 0.24)}`, 21 | })); 22 | 23 | // ---------------------------------------------------------------------- 24 | 25 | ColorPreview.propTypes = { 26 | colors: PropTypes.arrayOf(PropTypes.string), 27 | limit: PropTypes.number, 28 | sx: PropTypes.object, 29 | }; 30 | 31 | export default function ColorPreview({ colors, limit = 3, sx }) { 32 | const showColor = colors.slice(0, limit); 33 | const moreColor = colors.length - limit; 34 | 35 | return ( 36 | 37 | {showColor.map((color, index) => ( 38 | 39 | ))} 40 | 41 | {colors.length > limit && {`+${moreColor}`}} 42 | 43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /src/components/color-utils/index.js: -------------------------------------------------------------------------------- 1 | export { default as ColorPreview } from './ColorPreview'; 2 | export { default as ColorManyPicker } from './ColorManyPicker'; 3 | export { default as ColorSinglePicker } from './ColorSinglePicker'; 4 | -------------------------------------------------------------------------------- /src/components/hook-form/FormProvider.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // form 3 | import { FormProvider as Form } from 'react-hook-form'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | FormProvider.propTypes = { 8 | children: PropTypes.node.isRequired, 9 | methods: PropTypes.object.isRequired, 10 | onSubmit: PropTypes.func, 11 | }; 12 | 13 | export default function FormProvider({ children, onSubmit, methods }) { 14 | return ( 15 |
16 | {children}
17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /src/components/hook-form/RHFEditor.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // form 3 | import { useFormContext, Controller } from 'react-hook-form'; 4 | // @mui 5 | import { FormHelperText } from '@mui/material'; 6 | // 7 | import Editor from '../editor'; 8 | 9 | // ---------------------------------------------------------------------- 10 | 11 | RHFEditor.propTypes = { 12 | name: PropTypes.string, 13 | }; 14 | 15 | export default function RHFEditor({ name, ...other }) { 16 | const { control } = useFormContext(); 17 | 18 | return ( 19 | ( 23 | 30 | {error?.message} 31 | 32 | } 33 | {...other} 34 | /> 35 | )} 36 | /> 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /src/components/hook-form/RHFRadioGroup.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // form 3 | import { useFormContext, Controller } from 'react-hook-form'; 4 | // @mui 5 | import { Radio, RadioGroup, FormHelperText, FormControlLabel } from '@mui/material'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | RHFRadioGroup.propTypes = { 10 | name: PropTypes.string, 11 | options: PropTypes.array, 12 | }; 13 | 14 | export default function RHFRadioGroup({ name, options, ...other }) { 15 | const { control } = useFormContext(); 16 | 17 | return ( 18 | ( 22 |
23 | 24 | {options.map((option) => ( 25 | } label={option.label} /> 26 | ))} 27 | 28 | 29 | {!!error && ( 30 | 31 | {error.message} 32 | 33 | )} 34 |
35 | )} 36 | /> 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /src/components/hook-form/RHFSelect.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // form 3 | import { useFormContext, Controller } from 'react-hook-form'; 4 | // @mui 5 | import { TextField } from '@mui/material'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | RHFSelect.propTypes = { 10 | children: PropTypes.node, 11 | name: PropTypes.string, 12 | }; 13 | 14 | export default function RHFSelect({ name, children, ...other }) { 15 | const { control } = useFormContext(); 16 | 17 | return ( 18 | ( 22 | 31 | {children} 32 | 33 | )} 34 | /> 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /src/components/hook-form/RHFSwitch.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // form 3 | import { useFormContext, Controller } from 'react-hook-form'; 4 | // @mui 5 | import { Switch, FormControlLabel } from '@mui/material'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | RHFSwitch.propTypes = { 10 | name: PropTypes.string, 11 | }; 12 | 13 | export default function RHFSwitch({ name, ...other }) { 14 | const { control } = useFormContext(); 15 | 16 | return ( 17 | } /> 20 | } 21 | {...other} 22 | /> 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/components/hook-form/RHFTextField.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // form 3 | import { useFormContext, Controller } from 'react-hook-form'; 4 | // @mui 5 | import { TextField } from '@mui/material'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | RHFTextField.propTypes = { 10 | name: PropTypes.string, 11 | }; 12 | 13 | export default function RHFTextField({ name, ...other }) { 14 | const { control } = useFormContext(); 15 | 16 | return ( 17 | ( 21 | 22 | )} 23 | /> 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /src/components/hook-form/index.js: -------------------------------------------------------------------------------- 1 | export * from './RHFCheckbox'; 2 | export * from './RHFUpload'; 3 | 4 | export { default as FormProvider } from './FormProvider'; 5 | 6 | export { default as RHFSwitch } from './RHFSwitch'; 7 | export { default as RHFSelect } from './RHFSelect'; 8 | export { default as RHFEditor } from './RHFEditor'; 9 | export { default as RHFTextField } from './RHFTextField'; 10 | export { default as RHFRadioGroup } from './RHFRadioGroup'; 11 | -------------------------------------------------------------------------------- /src/components/map/MapControlFullscreen.js: -------------------------------------------------------------------------------- 1 | import { FullscreenControl } from 'react-map-gl'; 2 | // @mui 3 | import { styled } from '@mui/material/styles'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | const FullscreenControlStyle = styled(FullscreenControl)(({ theme }) => ({ 8 | zIndex: 99, 9 | borderRadius: 8, 10 | overflow: 'hidden', 11 | top: theme.spacing(1.5), 12 | left: theme.spacing(1.5), 13 | boxShadow: theme.customShadows.z8, 14 | '& span.mapboxgl-ctrl-icon': { 15 | transform: ' scale(0.75)', 16 | }, 17 | })); 18 | 19 | // ---------------------------------------------------------------------- 20 | 21 | export default function MapControlFullscreen({ ...other }) { 22 | return ; 23 | } 24 | -------------------------------------------------------------------------------- /src/components/map/MapControlGeolocate.js: -------------------------------------------------------------------------------- 1 | import { GeolocateControl } from 'react-map-gl'; 2 | // @mui 3 | import { styled } from '@mui/material/styles'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | const GeolocateControlStyle = styled(GeolocateControl)(({ theme }) => ({ 8 | zIndex: 99, 9 | borderRadius: 8, 10 | overflow: 'hidden', 11 | top: theme.spacing(6), 12 | left: theme.spacing(1.5), 13 | boxShadow: theme.customShadows.z8, 14 | })); 15 | 16 | // ---------------------------------------------------------------------- 17 | 18 | export default function MapControlGeolocate({ ...other }) { 19 | return ; 20 | } 21 | -------------------------------------------------------------------------------- /src/components/map/MapControlMarker.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Marker } from 'react-map-gl'; 3 | // @mui 4 | import { styled } from '@mui/material/styles'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3 9 | c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9 10 | C20.1,15.8,20.2,15.8,20.2,15.7z`; 11 | const SIZE = 20; 12 | 13 | const IconStyle = styled('svg')(({ theme }) => ({ 14 | height: SIZE, 15 | stroke: 'none', 16 | cursor: 'pointer', 17 | fill: theme.palette.error.main, 18 | transform: `translate(${-SIZE / 2}px,${-SIZE}px)`, 19 | })); 20 | 21 | // ---------------------------------------------------------------------- 22 | 23 | MapControlMarker.propTypes = { 24 | onClick: PropTypes.func, 25 | }; 26 | 27 | export default function MapControlMarker({ onClick, ...other }) { 28 | return ( 29 | 30 | 31 | 32 | 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /src/components/map/MapControlNavigation.js: -------------------------------------------------------------------------------- 1 | import { NavigationControl } from 'react-map-gl'; 2 | // @mui 3 | import { styled } from '@mui/material/styles'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | const NavigationControlStyle = styled(NavigationControl)(({ theme }) => ({ 8 | zIndex: 99, 9 | borderRadius: 8, 10 | overflow: 'hidden', 11 | bottom: theme.spacing(6), 12 | left: theme.spacing(1.5), 13 | boxShadow: theme.customShadows.z8, 14 | '& button+button': { 15 | borderTop: `1px solid ${theme.palette.divider}`, 16 | }, 17 | })); 18 | 19 | // ---------------------------------------------------------------------- 20 | 21 | export default function MapControlNavigation({ ...other }) { 22 | return ; 23 | } 24 | -------------------------------------------------------------------------------- /src/components/map/MapControlScale.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { ScaleControl } from 'react-map-gl'; 3 | // @mui 4 | import { styled } from '@mui/material/styles'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | const RootStyle = styled('div')(({ theme }) => ({ 9 | zIndex: 99, 10 | position: 'absolute', 11 | left: theme.spacing(1.5), 12 | bottom: theme.spacing(3.5), 13 | boxShadow: theme.customShadows.z8, 14 | '& .mapboxgl-ctrl': { 15 | border: 'none', 16 | borderRadius: 4, 17 | lineHeight: '14px', 18 | color: theme.palette.common.white, 19 | backgroundImage: `linear-gradient(to right, #8a2387, #e94057, #f27121)`, 20 | }, 21 | })); 22 | 23 | // ---------------------------------------------------------------------- 24 | 25 | MapControlScale.propTypes = { 26 | sx: PropTypes.object, 27 | }; 28 | 29 | export default function MapControlScale({ sx, ...other }) { 30 | return ( 31 | 32 | 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /src/components/map/index.js: -------------------------------------------------------------------------------- 1 | export { default as MapControlPopup } from './MapControlPopup'; 2 | export { default as MapControlScale } from './MapControlScale'; 3 | export { default as MapControlMarker } from './MapControlMarker'; 4 | export { default as MapControlGeolocate } from './MapControlGeolocate'; 5 | export { default as MapControlFullscreen } from './MapControlFullscreen'; 6 | export { default as MapControlNavigation } from './MapControlNavigation'; 7 | -------------------------------------------------------------------------------- /src/components/mega-menu/MenuHotProducts.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Link as RouterLink } from 'react-router-dom'; 3 | // @mui 4 | import { Link, Typography, Box } from '@mui/material'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | MenuHotProducts.propTypes = { 9 | tags: PropTypes.array.isRequired, 10 | }; 11 | 12 | export default function MenuHotProducts({ tags, ...other }) { 13 | return ( 14 | 15 | 16 | Hot Products: 17 | 18 |   19 | {tags.map((tag, index) => ( 20 | theme.transitions.create('all'), 29 | '&:hover': { color: 'primary.main' }, 30 | }} 31 | > 32 | {index === 0 ? tag.name : `, ${tag.name} `} 33 | 34 | ))} 35 | 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /src/components/mega-menu/index.js: -------------------------------------------------------------------------------- 1 | export { default as MegaMenuDesktopVertical } from './MegaMenuDesktopVertical'; 2 | export { default as MegaMenuDesktopHorizon } from './MegaMenuDesktopHorizon'; 3 | export { default as MegaMenuMobile } from './MegaMenuMobile'; 4 | export { default as MenuConfig } from './MenuConfig'; 5 | -------------------------------------------------------------------------------- /src/components/nav-section/horizontal/index.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { memo } from 'react'; 3 | // @mui 4 | import { Stack } from '@mui/material'; 5 | // 6 | import { NavListRoot } from './NavList'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | const hideScrollbar = { 11 | msOverflowStyle: 'none', 12 | scrollbarWidth: 'none', 13 | overflowY: 'scroll', 14 | '&::-webkit-scrollbar': { 15 | display: 'none', 16 | }, 17 | }; 18 | 19 | NavSectionHorizontal.propTypes = { 20 | navConfig: PropTypes.array, 21 | }; 22 | 23 | function NavSectionHorizontal({ navConfig }) { 24 | return ( 25 | 26 | 27 | {navConfig.map((group) => ( 28 | 29 | {group.items.map((list) => ( 30 | 31 | ))} 32 | 33 | ))} 34 | 35 | 36 | ); 37 | } 38 | 39 | export default memo(NavSectionHorizontal); 40 | -------------------------------------------------------------------------------- /src/components/nav-section/index.js: -------------------------------------------------------------------------------- 1 | import { matchPath } from 'react-router-dom'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export { default as NavSectionVertical } from './vertical'; 6 | export { default as NavSectionHorizontal } from './horizontal'; 7 | 8 | export function isExternalLink(path) { 9 | return path.includes('http'); 10 | } 11 | 12 | export function getActive(path, pathname) { 13 | return path ? !!matchPath({ path, end: false }, pathname) : false; 14 | } 15 | -------------------------------------------------------------------------------- /src/components/nav-section/vertical/index.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { styled } from '@mui/material/styles'; 4 | import { List, Box, ListSubheader } from '@mui/material'; 5 | // hooks 6 | import useLocales from '../../../hooks/useLocales'; 7 | // 8 | import { NavListRoot } from './NavList'; 9 | 10 | // ---------------------------------------------------------------------- 11 | 12 | export const ListSubheaderStyle = styled((props) => )( 13 | ({ theme }) => ({ 14 | ...theme.typography.overline, 15 | paddingTop: theme.spacing(3), 16 | paddingLeft: theme.spacing(2), 17 | paddingBottom: theme.spacing(1), 18 | color: theme.palette.text.primary, 19 | transition: theme.transitions.create('opacity', { 20 | duration: theme.transitions.duration.shorter, 21 | }), 22 | }) 23 | ); 24 | 25 | // ---------------------------------------------------------------------- 26 | 27 | NavSectionVertical.propTypes = { 28 | isCollapse: PropTypes.bool, 29 | navConfig: PropTypes.array, 30 | }; 31 | 32 | export default function NavSectionVertical({ navConfig, isCollapse = false, ...other }) { 33 | const { translate } = useLocales(); 34 | 35 | return ( 36 | 37 | {navConfig.map((group) => ( 38 | 39 | 46 | {translate(group.subheader)} 47 | 48 | 49 | {group.items.map((list) => ( 50 | 51 | ))} 52 | 53 | ))} 54 | 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /src/components/settings/ThemeColorPresets.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { useMemo } from 'react'; 3 | // @mui 4 | import { alpha, ThemeProvider, createTheme, useTheme } from '@mui/material/styles'; 5 | // hooks 6 | import useSettings from '../../hooks/useSettings'; 7 | // 8 | import componentsOverride from '../../theme/overrides'; 9 | 10 | // ---------------------------------------------------------------------- 11 | 12 | ThemeColorPresets.propTypes = { 13 | children: PropTypes.node, 14 | }; 15 | 16 | export default function ThemeColorPresets({ children }) { 17 | const defaultTheme = useTheme(); 18 | 19 | const { setColor } = useSettings(); 20 | 21 | const themeOptions = useMemo( 22 | () => ({ 23 | ...defaultTheme, 24 | palette: { 25 | ...defaultTheme.palette, 26 | primary: setColor, 27 | }, 28 | customShadows: { 29 | ...defaultTheme.customShadows, 30 | primary: `0 8px 16px 0 ${alpha(setColor.main, 0.24)}`, 31 | }, 32 | }), 33 | [setColor, defaultTheme] 34 | ); 35 | 36 | const theme = createTheme(themeOptions); 37 | 38 | theme.components = componentsOverride(theme); 39 | 40 | return {children}; 41 | } 42 | -------------------------------------------------------------------------------- /src/components/settings/ThemeLocalization.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { ThemeProvider, createTheme, useTheme } from '@mui/material/styles'; 4 | // hooks 5 | import useLocales from '../../hooks/useLocales'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | ThemeLocalization.propTypes = { 10 | children: PropTypes.node.isRequired, 11 | }; 12 | 13 | export default function ThemeLocalization({ children }) { 14 | const defaultTheme = useTheme(); 15 | 16 | const { currentLang } = useLocales(); 17 | 18 | const theme = createTheme(defaultTheme, currentLang.systemValue); 19 | 20 | return {children}; 21 | } 22 | -------------------------------------------------------------------------------- /src/components/settings/ThemeRtlLayout.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { useEffect } from 'react'; 3 | // rtl 4 | import rtlPlugin from 'stylis-plugin-rtl'; 5 | // emotion 6 | import createCache from '@emotion/cache'; 7 | import { CacheProvider } from '@emotion/react'; 8 | // @mui 9 | import { useTheme } from '@mui/material/styles'; 10 | 11 | // ---------------------------------------------------------------------- 12 | 13 | ThemeRtlLayout.propTypes = { 14 | children: PropTypes.node, 15 | }; 16 | 17 | export default function ThemeRtlLayout({ children }) { 18 | const theme = useTheme(); 19 | 20 | useEffect(() => { 21 | document.dir = theme.direction; 22 | }, [theme.direction]); 23 | 24 | const cacheRtl = createCache({ 25 | key: theme.direction === 'rtl' ? 'rtl' : 'css', 26 | stylisPlugins: theme.direction === 'rtl' ? [rtlPlugin] : [], 27 | }); 28 | 29 | return {children}; 30 | } 31 | -------------------------------------------------------------------------------- /src/components/settings/drawer/BoxMask.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { Radio, FormControlLabel } from '@mui/material'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | BoxMask.propTypes = { 8 | value: PropTypes.string, 9 | }; 10 | 11 | export default function BoxMask({ value }) { 12 | return ( 13 | } 17 | sx={{ 18 | m: 0, 19 | top: 0, 20 | right: 0, 21 | bottom: 0, 22 | left: 0, 23 | position: 'absolute', 24 | }} 25 | /> 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/components/settings/drawer/SettingContrast.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { styled } from '@mui/material/styles'; 3 | import { Grid, RadioGroup, CardActionArea } from '@mui/material'; 4 | // hooks 5 | import useSettings from '../../../hooks/useSettings'; 6 | // 7 | import Iconify from '../../Iconify'; 8 | import BoxMask from './BoxMask'; 9 | 10 | // ---------------------------------------------------------------------- 11 | 12 | const BoxStyle = styled(CardActionArea)(({ theme }) => ({ 13 | height: 72, 14 | display: 'flex', 15 | alignItems: 'center', 16 | justifyContent: 'center', 17 | color: theme.palette.text.disabled, 18 | border: `solid 1px ${theme.palette.grey[500_12]}`, 19 | borderRadius: Number(theme.shape.borderRadius) * 1.25, 20 | })); 21 | 22 | // ---------------------------------------------------------------------- 23 | 24 | export default function SettingContrast() { 25 | const { themeContrast, onChangeContrast } = useSettings(); 26 | 27 | return ( 28 | 29 | 30 | {['default', 'bold'].map((contrast, index) => { 31 | const isSelected = themeContrast === contrast; 32 | 33 | return ( 34 | 35 | theme.customShadows.z20, 40 | }), 41 | }} 42 | > 43 | 44 | 45 | 46 | 47 | ); 48 | })} 49 | 50 | 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /src/components/settings/drawer/SettingFullscreen.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | // @mui 3 | import { alpha } from '@mui/material/styles'; 4 | import { Button } from '@mui/material'; 5 | // 6 | import Iconify from '../../Iconify'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | export default function SettingFullscreen() { 11 | const [fullscreen, setFullscreen] = useState(false); 12 | 13 | const toggleFullScreen = () => { 14 | if (!document.fullscreenElement) { 15 | document.documentElement.requestFullscreen(); 16 | setFullscreen(true); 17 | } else if (document.exitFullscreen) { 18 | document.exitFullscreen(); 19 | setFullscreen(false); 20 | } 21 | }; 22 | 23 | return ( 24 | 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /src/components/settings/drawer/SettingMode.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { styled } from '@mui/material/styles'; 3 | import { Grid, RadioGroup, CardActionArea } from '@mui/material'; 4 | // hooks 5 | import useSettings from '../../../hooks/useSettings'; 6 | // 7 | import Iconify from '../../Iconify'; 8 | import BoxMask from './BoxMask'; 9 | 10 | // ---------------------------------------------------------------------- 11 | 12 | const BoxStyle = styled(CardActionArea)(({ theme }) => ({ 13 | height: 72, 14 | display: 'flex', 15 | alignItems: 'center', 16 | justifyContent: 'center', 17 | color: theme.palette.text.disabled, 18 | border: `solid 1px ${theme.palette.grey[500_12]}`, 19 | borderRadius: Number(theme.shape.borderRadius) * 1.25, 20 | })); 21 | 22 | // ---------------------------------------------------------------------- 23 | 24 | export default function SettingMode() { 25 | const { themeMode, onChangeMode } = useSettings(); 26 | 27 | return ( 28 | 29 | 30 | {['light', 'dark'].map((mode, index) => { 31 | const isSelected = themeMode === mode; 32 | 33 | return ( 34 | 35 | theme.customShadows.z20, 41 | }), 42 | }} 43 | > 44 | 45 | 46 | 47 | 48 | ); 49 | })} 50 | 51 | 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /src/components/settings/index.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // 3 | import SettingsDrawer from './drawer'; 4 | // 5 | import ThemeContrast from './ThemeContrast'; 6 | import ThemeRtlLayout from './ThemeRtlLayout'; 7 | import ThemeColorPresets from './ThemeColorPresets'; 8 | import ThemeLocalization from './ThemeLocalization'; 9 | 10 | // ---------------------------------------------------------------------- 11 | 12 | ThemeSettings.propTypes = { 13 | children: PropTypes.node.isRequired, 14 | }; 15 | 16 | export default function ThemeSettings({ children }) { 17 | return ( 18 | 19 | 20 | 21 | 22 | {children} 23 | 24 | 25 | 26 | 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /src/components/skeleton/SkeletonConversationItem.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Stack, Skeleton } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function SkeletonConversationItem() { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /src/components/skeleton/SkeletonKanbanColumn.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Stack, Skeleton, Box, Paper } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function SkeletonKanbanColumn() { 7 | return ( 8 | 15 | {[...Array(3)].map((_, index) => ( 16 | 17 | 18 | 19 | {index === 0 && ( 20 | 21 | )} 22 | {index !== 2 && ( 23 | 24 | )} 25 | 26 | 27 | ))} 28 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /src/components/skeleton/SkeletonMailSidebarItem.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Stack, Skeleton } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function SkeletonMailSidebarItem() { 7 | return ( 8 | 9 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/components/skeleton/SkeletonMap.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Stack, Skeleton } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function SkeletonMap() { 7 | return ( 8 | 9 | {[...Array(5)].map((_, index) => ( 10 | 15 | ))} 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/components/skeleton/SkeletonPost.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Box, Skeleton } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function SkeletonPost() { 7 | return ( 8 | <> 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /src/components/skeleton/SkeletonPostItem.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Box, Skeleton, Grid } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function SkeletonPostItem() { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/components/skeleton/SkeletonProduct.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Grid, Skeleton } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function SkeletonProduct() { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/components/skeleton/SkeletonProductItem.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Card, Skeleton, Stack } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function SkeletonProductItem() { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /src/components/skeleton/index.js: -------------------------------------------------------------------------------- 1 | export { default as SkeletonMap } from './SkeletonMap'; 2 | export { default as SkeletonPost } from './SkeletonPost'; 3 | export { default as SkeletonProduct } from './SkeletonProduct'; 4 | export { default as SkeletonPostItem } from './SkeletonPostItem'; 5 | export { default as SkeletonProductItem } from './SkeletonProductItem'; 6 | export { default as SkeletonKanbanColumn } from './SkeletonKanbanColumn'; 7 | export { default as SkeletonMailSidebarItem } from './SkeletonMailSidebarItem'; 8 | export { default as SkeletonConversationItem } from './SkeletonConversationItem'; 9 | -------------------------------------------------------------------------------- /src/components/table/TableEmptyRows.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { TableRow, TableCell } from '@mui/material'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | TableEmptyRows.propTypes = { 8 | emptyRows: PropTypes.number, 9 | height: PropTypes.number, 10 | }; 11 | 12 | export default function TableEmptyRows({ emptyRows, height }) { 13 | if (!emptyRows) { 14 | return null; 15 | } 16 | 17 | return ( 18 | 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /src/components/table/TableMoreMenu.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { IconButton } from '@mui/material'; 4 | // 5 | import Iconify from '../Iconify'; 6 | import MenuPopover from '../MenuPopover'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | TableMoreMenu.propTypes = { 11 | actions: PropTypes.node, 12 | open: PropTypes.object, 13 | onClose: PropTypes.func, 14 | onOpen: PropTypes.func, 15 | }; 16 | 17 | export default function TableMoreMenu({ actions, open, onClose, onOpen }) { 18 | return ( 19 | <> 20 | 21 | 22 | 23 | 24 | 42 | {actions} 43 | 44 | 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /src/components/table/TableNoData.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { TableRow, TableCell } from '@mui/material'; 4 | // 5 | import EmptyContent from '../EmptyContent'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | TableNoData.propTypes = { 10 | isNotFound: PropTypes.bool, 11 | }; 12 | 13 | export default function TableNoData({ isNotFound }) { 14 | return ( 15 | 16 | {isNotFound ? ( 17 | 18 | 24 | 25 | ) : ( 26 | 27 | )} 28 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /src/components/table/TableSelectedActions.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { Checkbox, Typography, Stack } from '@mui/material'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | TableSelectedActions.propTypes = { 8 | dense: PropTypes.bool, 9 | actions: PropTypes.node, 10 | rowCount: PropTypes.number, 11 | numSelected: PropTypes.number, 12 | onSelectAllRows: PropTypes.func, 13 | sx: PropTypes.object, 14 | }; 15 | 16 | export default function TableSelectedActions({ dense, actions, rowCount, numSelected, onSelectAllRows, sx, ...other }) { 17 | return ( 18 | 39 | 0 && numSelected < rowCount} 41 | checked={rowCount > 0 && numSelected === rowCount} 42 | onChange={(event) => onSelectAllRows(event.target.checked)} 43 | /> 44 | 45 | 56 | {numSelected} selected 57 | 58 | 59 | {actions && actions} 60 | 61 | ); 62 | } 63 | -------------------------------------------------------------------------------- /src/components/table/TableSkeleton.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { TableRow, TableCell, Skeleton, Stack } from '@mui/material'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function TableSkeleton({ ...other }) { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/components/table/index.js: -------------------------------------------------------------------------------- 1 | export { default as TableNoData } from './TableNoData'; 2 | export { default as TableMoreMenu } from './TableMoreMenu'; 3 | export { default as TableSkeleton } from './TableSkeleton'; 4 | export { default as TableEmptyRows } from './TableEmptyRows'; 5 | export { default as TableHeadCustom } from './TableHeadCustom'; 6 | export { default as TableSelectedActions } from './TableSelectedActions'; 7 | -------------------------------------------------------------------------------- /src/components/upload/BlockContent.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Box, Typography, Stack } from '@mui/material'; 3 | // assets 4 | import { UploadIllustration } from '../../assets'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | export default function BlockContent() { 9 | return ( 10 | 17 | 18 | 19 | 20 | 21 | Drop or Select file 22 | 23 | 24 | 25 | Drop files here or click  26 | 31 | browse 32 | 33 |  thorough your machine 34 | 35 | 36 | 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /src/components/upload/RejectionFiles.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | // @mui 3 | import { alpha } from '@mui/material/styles'; 4 | import { Box, Paper, Typography } from '@mui/material'; 5 | // utils 6 | import { fData } from '../../utils/formatNumber'; 7 | import getFileData from '../../utils/getFileData'; 8 | 9 | // ---------------------------------------------------------------------- 10 | 11 | RejectionFiles.propTypes = { 12 | fileRejections: PropTypes.array.isRequired, 13 | }; 14 | 15 | export default function RejectionFiles({ fileRejections }) { 16 | return ( 17 | alpha(theme.palette.error.main, 0.08), 25 | }} 26 | > 27 | {fileRejections.map(({ file, errors }) => { 28 | const { path, size } = getFileData(file); 29 | 30 | return ( 31 | 32 | 33 | {path} - {size ? fData(size) : ''} 34 | 35 | 36 | {errors.map((error) => ( 37 | 38 | {error.message} 39 | 40 | ))} 41 | 42 | ); 43 | })} 44 | 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /src/components/upload/index.js: -------------------------------------------------------------------------------- 1 | export { default as BlockContent } from './BlockContent'; 2 | export { default as RejectionFiles } from './RejectionFiles'; 3 | export { default as MultiFilePreview } from './MultiFilePreview'; 4 | 5 | export { default as UploadAvatar } from './UploadAvatar'; 6 | export { default as UploadMultiFile } from './UploadMultiFile'; 7 | export { default as UploadSingleFile } from './UploadSingleFile'; 8 | -------------------------------------------------------------------------------- /src/guards/AuthGuard.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { useState } from 'react'; 3 | import { Navigate, useLocation } from 'react-router-dom'; 4 | // hooks 5 | import useAuth from '../hooks/useAuth'; 6 | // pages 7 | import Login from '../pages/auth/Login'; 8 | // components 9 | import LoadingScreen from '../components/LoadingScreen'; 10 | 11 | // ---------------------------------------------------------------------- 12 | 13 | AuthGuard.propTypes = { 14 | children: PropTypes.node, 15 | }; 16 | 17 | export default function AuthGuard({ children }) { 18 | const { isAuthenticated, isInitialized } = useAuth(); 19 | 20 | const { pathname } = useLocation(); 21 | 22 | const [requestedLocation, setRequestedLocation] = useState(null); 23 | 24 | if (!isInitialized) { 25 | return ; 26 | } 27 | 28 | if (!isAuthenticated) { 29 | if (pathname !== requestedLocation) { 30 | setRequestedLocation(pathname); 31 | } 32 | return ; 33 | } 34 | 35 | if (requestedLocation && pathname !== requestedLocation) { 36 | setRequestedLocation(null); 37 | return ; 38 | } 39 | 40 | return <>{children}; 41 | } 42 | -------------------------------------------------------------------------------- /src/guards/GuestGuard.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Navigate } from 'react-router-dom'; 3 | // hooks 4 | import useAuth from '../hooks/useAuth'; 5 | // routes 6 | import { PATH_DASHBOARD } from '../routes/paths'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | GuestGuard.propTypes = { 11 | children: PropTypes.node, 12 | }; 13 | 14 | export default function GuestGuard({ children }) { 15 | const { isAuthenticated } = useAuth(); 16 | 17 | if (isAuthenticated) { 18 | return ; 19 | } 20 | 21 | return <>{children}; 22 | } 23 | -------------------------------------------------------------------------------- /src/guards/RoleBasedGuard.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { m } from 'framer-motion'; 3 | // @mui 4 | import { Container, Typography } from '@mui/material'; 5 | // hooks 6 | import useAuth from '../hooks/useAuth'; 7 | // components 8 | import { MotionContainer, varBounce } from '../components/animate'; 9 | // assets 10 | import { ForbiddenIllustration } from '../assets'; 11 | 12 | // ---------------------------------------------------------------------- 13 | 14 | RoleBasedGuard.propTypes = { 15 | hasContent: PropTypes.bool, 16 | roles: PropTypes.arrayOf(PropTypes.string), // Example ['admin', 'leader'] 17 | children: PropTypes.node.isRequired, 18 | }; 19 | 20 | export default function RoleBasedGuard({ hasContent, roles, children }) { 21 | // Logic here to get current user role 22 | const { user } = useAuth(); 23 | 24 | // const currentRole = 'user'; 25 | const currentRole = user?.role; // admin; 26 | 27 | if (typeof roles !== 'undefined' && !roles.includes(currentRole)) { 28 | return hasContent ? ( 29 | 30 | 31 | 32 | Permission Denied 33 | 34 | 35 | 36 | 37 | You do not have permission to access this page 38 | 39 | 40 | 41 | 42 | 43 | 44 | ) : null; 45 | } 46 | 47 | return <>{children}; 48 | } 49 | -------------------------------------------------------------------------------- /src/hooks/useAuth.js: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react'; 2 | // 3 | import { AuthContext } from '../contexts/JWTContext'; 4 | // import { AuthContext } from '../contexts/Auth0Context'; 5 | // import { AuthContext } from '../contexts/FirebaseContext'; 6 | // import { AuthContext } from '../contexts/AwsCognitoContext'; 7 | 8 | // ---------------------------------------------------------------------- 9 | 10 | const useAuth = () => { 11 | const context = useContext(AuthContext); 12 | 13 | if (!context) throw new Error('Auth context must be use inside AuthProvider'); 14 | 15 | return context; 16 | }; 17 | 18 | export default useAuth; 19 | -------------------------------------------------------------------------------- /src/hooks/useCollapseDrawer.js: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react'; 2 | import { CollapseDrawerContext } from '../contexts/CollapseDrawerContext'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | const useCollapseDrawer = () => useContext(CollapseDrawerContext); 7 | 8 | export default useCollapseDrawer; 9 | -------------------------------------------------------------------------------- /src/hooks/useCountdown.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function useCountdown(date) { 6 | const [countdown, setCountdown] = useState({ 7 | days: '00', 8 | hours: '00', 9 | minutes: '00', 10 | seconds: '00' 11 | }); 12 | 13 | useEffect(() => { 14 | const interval = setInterval(() => setNewTime(), 1000); 15 | return () => clearInterval(interval); 16 | // eslint-disable-next-line react-hooks/exhaustive-deps 17 | }, []); 18 | 19 | const setNewTime = () => { 20 | const startTime = date; 21 | const endTime = new Date(); 22 | const distanceToNow = startTime - endTime; 23 | 24 | const getDays = Math.floor(distanceToNow / (1000 * 60 * 60 * 24)); 25 | const getHours = `0${Math.floor((distanceToNow % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))}`.slice(-2); 26 | const getMinutes = `0${Math.floor((distanceToNow % (1000 * 60 * 60)) / (1000 * 60))}`.slice(-2); 27 | const getSeconds = `0${Math.floor((distanceToNow % (1000 * 60)) / 1000)}`.slice(-2); 28 | 29 | setCountdown({ 30 | days: getDays || '000', 31 | hours: getHours || '000', 32 | minutes: getMinutes || '000', 33 | seconds: getSeconds || '000' 34 | }); 35 | }; 36 | 37 | return countdown; 38 | } 39 | 40 | // Usage 41 | // const countdown = useCountdown(new Date('07/07/2022 21:30')); 42 | -------------------------------------------------------------------------------- /src/hooks/useCustomer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prettier/prettier */ 2 | import { useDispatch } from 'react-redux'; 3 | 4 | // redux 5 | import { addCustomer, editCustomer, deleteCustomer } from '../redux/slices/user'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | export default function useCustomer() { 10 | const dispatch = useDispatch(); 11 | 12 | return { 13 | // -------------- Editing part --------------------- 14 | editCustomer: ({ data }) => { 15 | dispatch(editCustomer({ data })); 16 | }, 17 | // -------------- Creating part --------------------- 18 | addCustomer: ({ data }) => { 19 | dispatch(addCustomer({ data })); 20 | }, 21 | 22 | // -------------- Delete Employee --------------------- 23 | deleteCustomer: (id) => { 24 | dispatch(deleteCustomer(id)); 25 | }, 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/hooks/useDateRangePicker.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { isSameDay, isSameMonth } from 'date-fns'; 3 | // 4 | import useToggle from './useToggle'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | export default function useDateRangePicker(date) { 9 | const { toggle: openPicker, onOpen: onOpenPicker, onClose: onClosePicker } = useToggle(); 10 | 11 | const [startTime, setStartTime] = useState(date[0]); 12 | 13 | const [endTime, setEndTime] = useState(date[1]); 14 | 15 | const isSameDays = startTime && endTime ? isSameDay(new Date(startTime), new Date(endTime)) : false; 16 | 17 | const isSameMonths = startTime && endTime ? isSameMonth(new Date(startTime), new Date(endTime)) : false; 18 | 19 | const handleChangeStartTime = (newValue) => { 20 | setStartTime(newValue); 21 | }; 22 | 23 | const handleChangeEndTime = (newValue) => { 24 | setEndTime(newValue); 25 | }; 26 | 27 | return { 28 | startTime, 29 | endTime, 30 | onChangeStartTime: handleChangeStartTime, 31 | onChangeEndTime: handleChangeEndTime, 32 | // 33 | openPicker, 34 | onOpenPicker, 35 | onClosePicker, 36 | // 37 | isSameDays, 38 | isSameMonths, 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /src/hooks/useEmployee.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable prettier/prettier */ 2 | import { useDispatch } from 'react-redux'; 3 | 4 | // redux 5 | import { addEmployee, editEmployee, deleteEmployee } from '../redux/slices/user'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | export default function useEmployee() { 10 | const dispatch = useDispatch(); 11 | 12 | return { 13 | // -------------- Editing part --------------------- 14 | editEmployee: ({ data }) => { 15 | dispatch(editEmployee({ data })); 16 | }, 17 | // -------------- Creating part --------------------- 18 | addEmployee: ({ data }) => { 19 | dispatch(addEmployee({ data })); 20 | }, 21 | 22 | // -------------- Delete Employee --------------------- 23 | deleteEmployee: (id) => { 24 | dispatch(deleteEmployee(id)); 25 | }, 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/hooks/useIsMountedRef.js: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect } from 'react'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function useIsMountedRef() { 6 | const isMounted = useRef(true); 7 | 8 | useEffect( 9 | () => () => { 10 | isMounted.current = false; 11 | }, 12 | [] 13 | ); 14 | 15 | return isMounted; 16 | } 17 | -------------------------------------------------------------------------------- /src/hooks/useLocalStorage.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function useLocalStorage(key, defaultValue) { 6 | const [value, setValue] = useState(() => { 7 | const storedValue = localStorage.getItem(key); 8 | 9 | return storedValue === null ? defaultValue : JSON.parse(storedValue); 10 | }); 11 | 12 | useEffect(() => { 13 | const listener = (e) => { 14 | if (e.storageArea === localStorage && e.key === key) { 15 | setValue(JSON.parse(e.newValue)); 16 | } 17 | }; 18 | window.addEventListener('storage', listener); 19 | 20 | return () => { 21 | window.removeEventListener('storage', listener); 22 | }; 23 | }, [key, defaultValue]); 24 | 25 | const setValueInLocalStorage = (newValue) => { 26 | setValue((currentValue) => { 27 | const result = typeof newValue === 'function' ? newValue(currentValue) : newValue; 28 | 29 | localStorage.setItem(key, JSON.stringify(result)); 30 | 31 | return result; 32 | }); 33 | }; 34 | 35 | return [value, setValueInLocalStorage]; 36 | } 37 | -------------------------------------------------------------------------------- /src/hooks/useLocales.js: -------------------------------------------------------------------------------- 1 | import { useTranslation } from 'react-i18next'; 2 | import useSettings from './useSettings'; 3 | // config 4 | import { allLangs, defaultLang } from '../config'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | export default function useLocales() { 9 | const { i18n, t: translate } = useTranslation(); 10 | 11 | const { onChangeDirectionByLang } = useSettings(); 12 | 13 | const langStorage = localStorage.getItem('i18nextLng'); 14 | 15 | const currentLang = allLangs.find((_lang) => _lang.value === langStorage) || defaultLang; 16 | 17 | const handleChangeLanguage = (newlang) => { 18 | i18n.changeLanguage(newlang); 19 | onChangeDirectionByLang(newlang); 20 | }; 21 | 22 | return { 23 | onChangeLang: handleChangeLanguage, 24 | translate: (text, options) => translate(text, options), 25 | currentLang, 26 | allLangs, 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /src/hooks/useOffSetTop.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function useOffSetTop(top) { 6 | const [offsetTop, setOffSetTop] = useState(false); 7 | const isTop = top || 100; 8 | 9 | useEffect(() => { 10 | window.onscroll = () => { 11 | if (window.pageYOffset > isTop) { 12 | setOffSetTop(true); 13 | } else { 14 | setOffSetTop(false); 15 | } 16 | }; 17 | return () => { 18 | window.onscroll = null; 19 | }; 20 | }, [isTop]); 21 | 22 | return offsetTop; 23 | } 24 | 25 | // Usage 26 | // const offset = useOffSetTop(100); 27 | -------------------------------------------------------------------------------- /src/hooks/useResponsive.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { useTheme } from '@mui/material/styles'; 3 | import useMediaQuery from '@mui/material/useMediaQuery'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | export default function useResponsive(query, key, start, end) { 8 | const theme = useTheme(); 9 | 10 | const mediaUp = useMediaQuery(theme.breakpoints.up(key)); 11 | 12 | const mediaDown = useMediaQuery(theme.breakpoints.down(key)); 13 | 14 | const mediaBetween = useMediaQuery(theme.breakpoints.between(start, end)); 15 | 16 | const mediaOnly = useMediaQuery(theme.breakpoints.only(key)); 17 | 18 | if (query === 'up') { 19 | return mediaUp; 20 | } 21 | 22 | if (query === 'down') { 23 | return mediaDown; 24 | } 25 | 26 | if (query === 'between') { 27 | return mediaBetween; 28 | } 29 | 30 | if (query === 'only') { 31 | return mediaOnly; 32 | } 33 | return null; 34 | } 35 | -------------------------------------------------------------------------------- /src/hooks/useSettings.js: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react'; 2 | import { SettingsContext } from '../contexts/SettingsContext'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | const useSettings = () => useContext(SettingsContext); 7 | 8 | export default useSettings; 9 | -------------------------------------------------------------------------------- /src/hooks/useTabs.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function useTabs(defaultValues) { 6 | const [currentTab, setCurrentTab] = useState(defaultValues || ''); 7 | 8 | return { 9 | currentTab, 10 | onChangeTab: (event, newValue) => { 11 | setCurrentTab(newValue); 12 | }, 13 | setCurrentTab, 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/hooks/useToggle.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function useToggle(defaultChecked) { 6 | const [toggle, setToggle] = useState(defaultChecked || false); 7 | 8 | return { 9 | toggle, 10 | onToggle: () => setToggle(!toggle), 11 | onOpen: () => setToggle(true), 12 | onClose: () => setToggle(false), 13 | setToggle, 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/layouts/LogoOnlyLayout.js: -------------------------------------------------------------------------------- 1 | import { Outlet } from 'react-router-dom'; 2 | // @mui 3 | import { styled } from '@mui/material/styles'; 4 | // components 5 | import Logo from '../components/Logo'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | const HeaderStyle = styled('header')(({ theme }) => ({ 10 | top: 0, 11 | left: 0, 12 | lineHeight: 0, 13 | width: '100%', 14 | position: 'absolute', 15 | padding: theme.spacing(3, 3, 0), 16 | [theme.breakpoints.up('sm')]: { 17 | padding: theme.spacing(5, 5, 0) 18 | } 19 | })); 20 | 21 | // ---------------------------------------------------------------------- 22 | 23 | export default function LogoOnlyLayout() { 24 | return ( 25 | <> 26 | 27 | 28 | 29 | 30 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /src/layouts/dashboard/navbar/NavConfig.js: -------------------------------------------------------------------------------- 1 | // routes 2 | import { PATH_DASHBOARD } from '../../../routes/paths'; 3 | // components 4 | import SvgIconStyle from '../../../components/SvgIconStyle'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | const getIcon = (name) => ; 9 | 10 | const ICONS = { 11 | user: getIcon('ic_user'), 12 | dashboard: getIcon('ic_dashboard'), 13 | }; 14 | 15 | const navConfig = [ 16 | // GENERAL 17 | // ---------------------------------------------------------------------- 18 | { 19 | subheader: 'Dashboard', 20 | items: [ 21 | { title: 'Manage Bus List', path: PATH_DASHBOARD.bus.buslist, icon: ICONS.dashboard }, 22 | { title: 'Tasks', path: PATH_DASHBOARD.task.tasklist, icon: ICONS.dashboard }, 23 | { title: 'Employees', path: PATH_DASHBOARD.employee.employeelist, icon: ICONS.user }, 24 | { title: 'Customers', path: PATH_DASHBOARD.customer.customerlist, icon: ICONS.user }, 25 | ], 26 | }, 27 | ]; 28 | 29 | export default navConfig; 30 | -------------------------------------------------------------------------------- /src/layouts/dashboard/navbar/NavbarHorizontal.js: -------------------------------------------------------------------------------- 1 | import { memo } from 'react'; 2 | // @mui 3 | import { styled } from '@mui/material/styles'; 4 | import { Container, AppBar } from '@mui/material'; 5 | // config 6 | import { HEADER } from '../../../config'; 7 | // components 8 | import { NavSectionHorizontal } from '../../../components/nav-section'; 9 | // 10 | import navConfig from './NavConfig'; 11 | 12 | // ---------------------------------------------------------------------- 13 | 14 | const RootStyle = styled(AppBar)(({ theme }) => ({ 15 | transition: theme.transitions.create('top', { 16 | easing: theme.transitions.easing.easeInOut, 17 | duration: theme.transitions.duration.shorter, 18 | }), 19 | width: '100%', 20 | position: 'fixed', 21 | zIndex: theme.zIndex.appBar, 22 | padding: theme.spacing(1, 0), 23 | boxShadow: theme.customShadows.z8, 24 | top: HEADER.DASHBOARD_DESKTOP_OFFSET_HEIGHT, 25 | backgroundColor: theme.palette.background.default, 26 | })); 27 | 28 | // ---------------------------------------------------------------------- 29 | 30 | function NavbarHorizontal() { 31 | return ( 32 | 33 | 34 | 35 | 36 | 37 | ); 38 | } 39 | 40 | export default memo(NavbarHorizontal); 41 | -------------------------------------------------------------------------------- /src/layouts/main/MenuConfig.js: -------------------------------------------------------------------------------- 1 | // Path 2 | import { PATH_AUTH } from '../../routes/paths'; 3 | // components 4 | import Iconify from '../../components/Iconify'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | const ICON_SIZE = { 9 | width: 22, 10 | height: 22, 11 | }; 12 | 13 | const menuConfig = [ 14 | { 15 | title: 'LogIn', 16 | icon: , 17 | path: PATH_AUTH.login, 18 | }, 19 | ]; 20 | 21 | export default menuConfig; 22 | -------------------------------------------------------------------------------- /src/layouts/main/index.js: -------------------------------------------------------------------------------- 1 | import { useLocation, Outlet } from 'react-router-dom'; 2 | // @mui 3 | import { Box, Link, Container, Typography, Stack } from '@mui/material'; 4 | // components 5 | import Logo from '../../components/Logo'; 6 | // 7 | import MainHeader from './MainHeader'; 8 | 9 | // ---------------------------------------------------------------------- 10 | 11 | export default function MainLayout() { 12 | const { pathname } = useLocation(); 13 | 14 | // const isHome = pathname === '/'; 15 | 16 | return ( 17 | 18 | 19 | 20 | 21 | 22 | 23 | 31 | 32 | 33 | 34 | admin@admin.com 35 | 36 | 37 | 38 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /src/locales/cn.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | // IF THIS TRANSLATION IS INCORRECT PLEASE IGNORE THIS AS THIS TRANSLATION IS FOR DEMO PURPOSES ONLY 4 | // We are happy if you can help improve the translation by sending an email to support@minimals.cc. 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | const cn = { 9 | demo: { 10 | title: `Chinese`, 11 | introduction: `Lorem Ipsum 只是印刷和排版行业的虚拟文本。 自 1500 年代以来,Lorem Ipsum 一直是行业的标准虚拟文本,当时一位不知名的印刷商采用了一种类型的厨房并将其加扰以制作类型样本书。 它不仅经历了五个世纪,而且经历了电子排版的飞跃,基本保持不变。 它在 1960 年代随着包含 Lorem Ipsum 段落的 Letraset 表的发布而流行起来,最近还随着 Aldus PageMaker 等桌面出版软件(包括 Lorem Ipsum 的版本)而普及.`, 12 | }, 13 | docs: { 14 | hi: `你好`, 15 | description: `需要帮忙?\n 请查看我们的文档.`, 16 | documentation: `文件`, 17 | }, 18 | app: `应用程序`, 19 | user: `用户`, 20 | list: `列表`, 21 | edit: `编辑`, 22 | shop: `商店`, 23 | blog: `博客`, 24 | post: `邮政`, 25 | mail: `电子邮件`, 26 | chat: `聊天`, 27 | cards: `牌`, 28 | posts: `帖子`, 29 | create: `创建`, 30 | kanban: `登机`, 31 | general: `一般的`, 32 | banking: `银行业`, 33 | booking: `预订`, 34 | profile: `轮廓`, 35 | account: `帐户`, 36 | product: `产品`, 37 | invoice: `发票`, 38 | details: `细节`, 39 | checkout: `退房`, 40 | calendar: `日历`, 41 | analytics: `分析`, 42 | ecommerce: `电子商务`, 43 | management: `管理`, 44 | menu_level_1: `菜单级别 1`, 45 | menu_level_2: `菜单级别 2`, 46 | menu_level_3: `菜单级别 3`, 47 | item_disabled: `项目已禁用`, 48 | item_label: `项目标签`, 49 | item_caption: `项目标题`, 50 | description: `描述`, 51 | other_cases: `其他情况`, 52 | item_by_roles: `按角色逐项`, 53 | only_admin_can_see_this_item: `只有管理员可以看到这个项目`, 54 | }; 55 | 56 | export default cn; 57 | -------------------------------------------------------------------------------- /src/locales/i18n.js: -------------------------------------------------------------------------------- 1 | import i18n from 'i18next'; 2 | import LanguageDetector from 'i18next-browser-languagedetector'; 3 | import { initReactI18next } from 'react-i18next'; 4 | // config 5 | import { defaultLang } from '../config'; 6 | // 7 | import enLocales from './en'; 8 | import frLocales from './fr'; 9 | import vnLocales from './vn'; 10 | import cnLocales from './cn'; 11 | import arLocales from './ar'; 12 | 13 | // ---------------------------------------------------------------------- 14 | 15 | i18n 16 | .use(LanguageDetector) 17 | .use(initReactI18next) 18 | .init({ 19 | resources: { 20 | en: { translations: enLocales }, 21 | fr: { translations: frLocales }, 22 | vn: { translations: vnLocales }, 23 | cn: { translations: cnLocales }, 24 | ar: { translations: arLocales }, 25 | }, 26 | lng: localStorage.getItem('i18nextLng') || defaultLang.value, 27 | fallbackLng: defaultLang.value, 28 | debug: false, 29 | ns: ['translations'], 30 | defaultNS: 'translations', 31 | interpolation: { 32 | escapeValue: false, 33 | }, 34 | }); 35 | 36 | export default i18n; 37 | -------------------------------------------------------------------------------- /src/pages/Home.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { styled } from '@mui/material/styles'; 3 | // components 4 | import Page from '../components/Page'; 5 | // sections 6 | import { 7 | HomeHero, 8 | HomeMinimal, 9 | HomeDarkMode, 10 | HomeLookingFor, 11 | HomeColorPresets, 12 | HomePricingPlans, 13 | HomeAdvertisement, 14 | HomeCleanInterfaces, 15 | HomeHugePackElements, 16 | } from '../sections/home'; 17 | 18 | // ---------------------------------------------------------------------- 19 | 20 | const ContentStyle = styled('div')(({ theme }) => ({ 21 | overflow: 'hidden', 22 | position: 'relative', 23 | backgroundColor: theme.palette.background.default, 24 | })); 25 | 26 | // ---------------------------------------------------------------------- 27 | 28 | export default function HomePage() { 29 | return ( 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /src/pages/Page500.js: -------------------------------------------------------------------------------- 1 | import { m } from 'framer-motion'; 2 | import { Link as RouterLink } from 'react-router-dom'; 3 | import { styled } from '@mui/material/styles'; 4 | // @mui 5 | import { Button, Typography, Container } from '@mui/material'; 6 | // components 7 | import Page from '../components/Page'; 8 | import { MotionContainer, varBounce } from '../components/animate'; 9 | // assets 10 | import { SeverErrorIllustration } from '../assets'; 11 | 12 | // ---------------------------------------------------------------------- 13 | 14 | const ContentStyle = styled('div')(({ theme }) => ({ 15 | maxWidth: 480, 16 | margin: 'auto', 17 | minHeight: '100vh', 18 | display: 'flex', 19 | justifyContent: 'center', 20 | flexDirection: 'column', 21 | padding: theme.spacing(12, 0), 22 | })); 23 | 24 | // ---------------------------------------------------------------------- 25 | 26 | export default function Page500() { 27 | return ( 28 | 29 | 30 | 31 | 32 | 33 | 500 Internal Server Error 34 | 35 | 36 | 37 | 38 | There was an error, please try again later. 39 | 40 | 41 | 42 | 43 | 44 | 45 | 48 | 49 | 50 | 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /src/pages/dashboard/bus/BusCreate.js: -------------------------------------------------------------------------------- 1 | import { paramCase, capitalCase } from 'change-case'; 2 | import { useParams, useLocation } from 'react-router-dom'; 3 | // @mui 4 | import { Container } from '@mui/material'; 5 | // routes 6 | import { PATH_DASHBOARD } from '../../../routes/paths'; 7 | // hooks 8 | import useSettings from '../../../hooks/useSettings'; 9 | // _mock_ 10 | import { _userList } from '../../../_mock'; 11 | // components 12 | import Page from '../../../components/Page'; 13 | import HeaderBreadcrumbs from '../../../components/HeaderBreadcrumbs'; 14 | // sections 15 | import BusNewEditForm from '../../../sections/@dashboard/bus/BusNewEditForm'; 16 | 17 | // ---------------------------------------------------------------------- 18 | 19 | export default function BusCreate() { 20 | const { themeStretch } = useSettings(); 21 | 22 | const { pathname } = useLocation(); 23 | 24 | const { name = '' } = useParams(); 25 | 26 | const isEdit = pathname.includes('edit'); 27 | 28 | const currentUser = _userList.find((user) => paramCase(user.name) === name); 29 | 30 | return ( 31 | 32 | 33 | 41 | 42 | 43 | 44 | 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /src/pages/dashboard/bus/Buses.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Container } from '@mui/material'; 3 | // hooks 4 | import useSettings from '../../../hooks/useSettings'; 5 | // components 6 | import Page from '../../../components/Page'; 7 | import BusList from './BusList'; 8 | 9 | // ---------------------------------------------------------------------- 10 | 11 | export default function Buses() { 12 | const { themeStretch } = useSettings(); 13 | 14 | return ( 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/pages/dashboard/order/OrderCreate.js: -------------------------------------------------------------------------------- 1 | import { paramCase, capitalCase } from 'change-case'; 2 | import { useParams, useLocation } from 'react-router-dom'; 3 | // @mui 4 | import { Container } from '@mui/material'; 5 | // routes 6 | import { PATH_DASHBOARD } from '../../../routes/paths'; 7 | // hooks 8 | import useSettings from '../../../hooks/useSettings'; 9 | // _mock_ 10 | import { _userList } from '../../../_mock'; 11 | // components 12 | import Page from '../../../components/Page'; 13 | import HeaderBreadcrumbs from '../../../components/HeaderBreadcrumbs'; 14 | // sections 15 | import OrderNewEditForm from '../../../sections/@dashboard/order/OrderNewEditForm'; 16 | 17 | // ---------------------------------------------------------------------- 18 | 19 | export default function OrderCreate() { 20 | const { themeStretch } = useSettings(); 21 | 22 | const { pathname } = useLocation(); 23 | 24 | const { name = '' } = useParams(); 25 | 26 | const isEdit = pathname.includes('edit'); 27 | 28 | const currentUser = _userList.find((user) => paramCase(user.name) === name); 29 | 30 | return ( 31 | 32 | 33 | 41 | 42 | 43 | 44 | 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /src/pages/dashboard/order/Orders.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Container } from '@mui/material'; 3 | // hooks 4 | import useSettings from '../../../hooks/useSettings'; 5 | // components 6 | import Page from '../../../components/Page'; 7 | import OrderList from './OrderList'; 8 | 9 | // ---------------------------------------------------------------------- 10 | 11 | export default function Orders() { 12 | const { themeStretch } = useSettings(); 13 | 14 | return ( 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/pages/dashboard/user/UserAccount.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Container } from '@mui/material'; 3 | // routes 4 | import { PATH_DASHBOARD } from '../../../routes/paths'; 5 | // hooks 6 | import useSettings from '../../../hooks/useSettings'; 7 | // components 8 | import Page from '../../../components/Page'; 9 | import HeaderBreadcrumbs from '../../../components/HeaderBreadcrumbs'; 10 | // sections 11 | import { AccountGeneral } from '../../../sections/@dashboard/user/account'; 12 | 13 | // ---------------------------------------------------------------------- 14 | 15 | export default function UserAccount() { 16 | const { themeStretch } = useSettings(); 17 | 18 | return ( 19 | 20 | 21 | 25 | 26 | 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /src/pages/dashboard/user/customer/Customers.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Container } from '@mui/material'; 3 | // hooks 4 | import useSettings from '../../../../hooks/useSettings'; 5 | // components 6 | import Page from '../../../../components/Page'; 7 | import CustomerList from './CustomerList'; 8 | 9 | // ---------------------------------------------------------------------- 10 | 11 | export default function Customers() { 12 | const { themeStretch } = useSettings(); 13 | 14 | return ( 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/pages/dashboard/user/employee/Employees.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Container } from '@mui/material'; 3 | // hooks 4 | import useSettings from '../../../../hooks/useSettings'; 5 | // components 6 | import Page from '../../../../components/Page'; 7 | import EmployeesList from './EmployeesList'; 8 | 9 | // ---------------------------------------------------------------------- 10 | 11 | export default function Employees() { 12 | const { themeStretch } = useSettings(); 13 | 14 | return ( 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /src/redux/rootReducer.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import storage from 'redux-persist/lib/storage'; 3 | // slices 4 | // import orderReducer from './slices/order'; 5 | import userReducer from './slices/user'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | const rootPersistConfig = { 10 | key: 'root', 11 | storage, 12 | keyPrefix: 'redux-', 13 | whitelist: [], 14 | }; 15 | 16 | const rootReducer = combineReducers({ 17 | // order: orderReducer, 18 | user: userReducer, 19 | }); 20 | 21 | export { rootPersistConfig, rootReducer }; 22 | -------------------------------------------------------------------------------- /src/redux/slices/order.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clever-web/Buswash-React-Node-MySQL/4afb6bc6c28e67649aaf47f8f699c3842fcd5535/src/redux/slices/order.js -------------------------------------------------------------------------------- /src/redux/store.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit'; 2 | import { useDispatch as useAppDispatch, useSelector as useAppSelector } from 'react-redux'; 3 | import { persistStore, persistReducer } from 'redux-persist'; 4 | import { rootPersistConfig, rootReducer } from './rootReducer'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | const store = configureStore({ 9 | reducer: persistReducer(rootPersistConfig, rootReducer), 10 | middleware: (getDefaultMiddleware) => 11 | getDefaultMiddleware({ 12 | serializableCheck: false, 13 | immutableCheck: false, 14 | }), 15 | }); 16 | 17 | const persistor = persistStore(store); 18 | 19 | const { dispatch } = store; 20 | 21 | const useSelector = useAppSelector; 22 | 23 | const useDispatch = () => useAppDispatch(); 24 | 25 | export { store, persistor, dispatch, useSelector, useDispatch }; 26 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = (onPerfEntry) => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /src/routes/paths.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | function path(root, sublink) { 4 | return `${root}${sublink}`; 5 | } 6 | 7 | const ROOTS_AUTH = '/auth'; 8 | const ROOTS_DASHBOARD = '/dashboard'; 9 | 10 | // ---------------------------------------------------------------------- 11 | 12 | export const PATH_AUTH = { 13 | root: ROOTS_AUTH, 14 | login: path(ROOTS_AUTH, '/login'), 15 | register: path(ROOTS_AUTH, '/register'), 16 | verify: path(ROOTS_AUTH, '/verify'), 17 | resetPassword: path(ROOTS_AUTH, '/reset-password'), 18 | newPassword: path(ROOTS_AUTH, '/new-password'), 19 | }; 20 | 21 | export const PATH_PAGE = { 22 | page403: '/403', 23 | page404: '/404', 24 | page500: '/500', 25 | }; 26 | 27 | export const PATH_DASHBOARD = { 28 | root: ROOTS_DASHBOARD, 29 | task: { 30 | tasklist: path(ROOTS_DASHBOARD, '/task'), 31 | new: path(ROOTS_DASHBOARD, '/task/new'), 32 | edit: (name) => path(ROOTS_DASHBOARD, `/task/${name}/edit`), 33 | }, 34 | bus: { 35 | buslist: path(ROOTS_DASHBOARD, '/bus'), 36 | new: path(ROOTS_DASHBOARD, '/bus/new'), 37 | edit: (name) => path(ROOTS_DASHBOARD, `/bus/${name}/edit`), 38 | }, 39 | employee: { 40 | employeelist: path(ROOTS_DASHBOARD, '/employee'), 41 | new: path(ROOTS_DASHBOARD, '/employee/new'), 42 | edit: (name) => path(ROOTS_DASHBOARD, `/employee/${name}/edit`), 43 | }, 44 | customer: { 45 | customerlist: path(ROOTS_DASHBOARD, '/customer'), 46 | new: path(ROOTS_DASHBOARD, '/customer/new'), 47 | edit: (name) => path(ROOTS_DASHBOARD, `/customer/${name}/edit`), 48 | }, 49 | permissionDenied: path(ROOTS_DASHBOARD, '/permission-denied'), 50 | user: { 51 | profile: path(ROOTS_DASHBOARD, '/profile'), 52 | }, 53 | }; 54 | -------------------------------------------------------------------------------- /src/sections/@dashboard/bus/list/BusTableToolbar.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Stack, InputAdornment, TextField, MenuItem } from '@mui/material'; 3 | // components 4 | import Iconify from '../../../../components/Iconify'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | BusTableToolbar.propTypes = { 9 | filterName: PropTypes.string, 10 | onFilterName: PropTypes.func, 11 | onFilterRole: PropTypes.func, 12 | optionsRole: PropTypes.arrayOf(PropTypes.string), 13 | }; 14 | 15 | export default function BusTableToolbar({ filterName, onFilterName, optionsRole }) { 16 | return ( 17 | 18 | onFilterName(event.target.value)} 22 | placeholder="Search Bus..." 23 | InputProps={{ 24 | startAdornment: ( 25 | 26 | 27 | 28 | ), 29 | }} 30 | /> 31 | 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/sections/@dashboard/bus/list/index.js: -------------------------------------------------------------------------------- 1 | export { default as BusTableRow } from './BusTableRow'; 2 | export { default as BusTableToolbar } from './BusTableToolbar'; 3 | -------------------------------------------------------------------------------- /src/sections/@dashboard/customer/list/CustomerTableToolbar.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Stack, InputAdornment, TextField, MenuItem } from '@mui/material'; 3 | // components 4 | import Iconify from '../../../../components/Iconify'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | CustomerTableToolbar.propTypes = { 9 | filterName: PropTypes.string, 10 | onFilterName: PropTypes.func, 11 | }; 12 | 13 | export default function CustomerTableToolbar({ filterName, onFilterName }) { 14 | return ( 15 | 16 | onFilterName(event.target.value)} 20 | placeholder="Search user..." 21 | InputProps={{ 22 | startAdornment: ( 23 | 24 | 25 | 26 | ), 27 | }} 28 | /> 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /src/sections/@dashboard/customer/list/index.js: -------------------------------------------------------------------------------- 1 | export { default as CustomerTableRow } from './CustomerTableRow'; 2 | export { default as CustomerTableToolbar } from './CustomerTableToolbar'; 3 | -------------------------------------------------------------------------------- /src/sections/@dashboard/employee/list/EmployeeTableToolbar.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Stack, InputAdornment, TextField } from '@mui/material'; 3 | // components 4 | import Iconify from '../../../../components/Iconify'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | EmployeeTableToolbar.propTypes = { 9 | filterName: PropTypes.string, 10 | onFilterName: PropTypes.func, 11 | }; 12 | 13 | export default function EmployeeTableToolbar({ filterName, onFilterName }) { 14 | return ( 15 | 16 | onFilterName(event.target.value)} 20 | placeholder="Search user..." 21 | InputProps={{ 22 | startAdornment: ( 23 | 24 | 25 | 26 | ), 27 | }} 28 | /> 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /src/sections/@dashboard/employee/list/index.js: -------------------------------------------------------------------------------- 1 | export { default as EmployeeTableRow } from './EmployeeTableRow'; 2 | export { default as EmployeeTableToolbar } from './EmployeeTableToolbar'; 3 | -------------------------------------------------------------------------------- /src/sections/@dashboard/order/list/OrderTableToolbar.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { Stack, InputAdornment, TextField, MenuItem } from '@mui/material'; 3 | // components 4 | import Iconify from '../../../../components/Iconify'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | OrderTableToolbar.propTypes = { 9 | filterName: PropTypes.string, 10 | onFilterName: PropTypes.func, 11 | }; 12 | 13 | export default function OrderTableToolbar({ filterName, onFilterName }) { 14 | return ( 15 | 16 | onFilterName(event.target.value)} 20 | placeholder="Search user..." 21 | InputProps={{ 22 | startAdornment: ( 23 | 24 | 25 | 26 | ), 27 | }} 28 | /> 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /src/sections/@dashboard/order/list/index.js: -------------------------------------------------------------------------------- 1 | export { default as OrderTableRow } from './OrderTableRow'; 2 | export { default as OrderTableToolbar } from './OrderTableToolbar'; 3 | -------------------------------------------------------------------------------- /src/sections/@dashboard/user/account/index.js: -------------------------------------------------------------------------------- 1 | export { default as AccountGeneral } from './AccountGeneral'; 2 | -------------------------------------------------------------------------------- /src/sections/auth/AuthFirebaseSocial.js: -------------------------------------------------------------------------------- 1 | // @mui 2 | import { Stack, Button, Divider, Typography } from '@mui/material'; 3 | // components 4 | import Iconify from '../../components/Iconify'; 5 | 6 | // ---------------------------------------------------------------------- 7 | 8 | export default function AuthFirebaseSocial() { 9 | return ( 10 | <> 11 | 12 | 15 | 16 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | OR 28 | 29 | 30 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /src/sections/auth/login/index.js: -------------------------------------------------------------------------------- 1 | export { default as LoginForm } from './LoginForm'; 2 | -------------------------------------------------------------------------------- /src/sections/auth/new-password/index.js: -------------------------------------------------------------------------------- 1 | export { default as NewPasswordForm } from './NewPasswordForm'; 2 | -------------------------------------------------------------------------------- /src/sections/auth/register/index.js: -------------------------------------------------------------------------------- 1 | export { default as RegisterForm } from './RegisterForm'; 2 | -------------------------------------------------------------------------------- /src/sections/auth/reset-password/ResetPasswordForm.js: -------------------------------------------------------------------------------- 1 | import * as Yup from 'yup'; 2 | import { useNavigate } from 'react-router-dom'; 3 | // form 4 | import { yupResolver } from '@hookform/resolvers/yup'; 5 | import { useForm } from 'react-hook-form'; 6 | // @mui 7 | import { Stack } from '@mui/material'; 8 | import { LoadingButton } from '@mui/lab'; 9 | // routes 10 | import { PATH_AUTH } from '../../../routes/paths'; 11 | // components 12 | import { FormProvider, RHFTextField } from '../../../components/hook-form'; 13 | 14 | // ---------------------------------------------------------------------- 15 | 16 | export default function ResetPasswordForm() { 17 | const navigate = useNavigate(); 18 | 19 | const ResetPasswordSchema = Yup.object().shape({ 20 | email: Yup.string().email('Email must be a valid email address').required('Email is required'), 21 | }); 22 | 23 | const methods = useForm({ 24 | resolver: yupResolver(ResetPasswordSchema), 25 | defaultValues: { email: '' }, 26 | }); 27 | 28 | const { 29 | handleSubmit, 30 | formState: { isSubmitting }, 31 | } = methods; 32 | 33 | const onSubmit = async (data) => { 34 | try { 35 | await new Promise((resolve) => setTimeout(resolve, 500)); 36 | 37 | sessionStorage.setItem('email-recovery', data.email); 38 | 39 | navigate(PATH_AUTH.newPassword); 40 | } catch (error) { 41 | console.error(error); 42 | } 43 | }; 44 | 45 | return ( 46 | 47 | 48 | 49 | 50 | 51 | Send Request 52 | 53 | 54 | 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /src/sections/auth/reset-password/index.js: -------------------------------------------------------------------------------- 1 | export { default as ResetPasswordForm } from './ResetPasswordForm'; 2 | -------------------------------------------------------------------------------- /src/sections/auth/verify-code/index.js: -------------------------------------------------------------------------------- 1 | export { default as VerifyCodeForm } from './VerifyCodeForm'; 2 | -------------------------------------------------------------------------------- /src/sections/home/index.js: -------------------------------------------------------------------------------- 1 | export { default as HomeHero } from './HomeHero'; 2 | export { default as HomeMinimal } from './HomeMinimal'; 3 | export { default as HomeDarkMode } from './HomeDarkMode'; 4 | export { default as HomeLookingFor } from './HomeLookingFor'; 5 | export { default as HomeColorPresets } from './HomeColorPresets'; 6 | export { default as HomePricingPlans } from './HomePricingPlans'; 7 | export { default as HomeAdvertisement } from './HomeAdvertisement'; 8 | export { default as HomeCleanInterfaces } from './HomeCleanInterfaces'; 9 | export { default as HomeHugePackElements } from './HomeHugePackElements'; 10 | -------------------------------------------------------------------------------- /src/theme/breakpoints.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | const breakpoints = { 4 | values: { 5 | xs: 0, 6 | sm: 600, 7 | md: 900, 8 | lg: 1200, 9 | xl: 1536 10 | } 11 | }; 12 | 13 | export default breakpoints; 14 | -------------------------------------------------------------------------------- /src/theme/index.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { useMemo } from 'react'; 3 | // @mui 4 | import { CssBaseline } from '@mui/material'; 5 | import { createTheme, ThemeProvider as MUIThemeProvider, StyledEngineProvider } from '@mui/material/styles'; 6 | // hooks 7 | import useSettings from '../hooks/useSettings'; 8 | // 9 | import palette from './palette'; 10 | import typography from './typography'; 11 | import breakpoints from './breakpoints'; 12 | import componentsOverride from './overrides'; 13 | import shadows, { customShadows } from './shadows'; 14 | 15 | // ---------------------------------------------------------------------- 16 | 17 | ThemeProvider.propTypes = { 18 | children: PropTypes.node, 19 | }; 20 | 21 | export default function ThemeProvider({ children }) { 22 | const { themeMode, themeDirection } = useSettings(); 23 | 24 | const isLight = themeMode === 'light'; 25 | 26 | const themeOptions = useMemo( 27 | () => ({ 28 | palette: isLight ? palette.light : palette.dark, 29 | typography, 30 | breakpoints, 31 | shape: { borderRadius: 8 }, 32 | direction: themeDirection, 33 | shadows: isLight ? shadows.light : shadows.dark, 34 | customShadows: isLight ? customShadows.light : customShadows.dark, 35 | }), 36 | [isLight, themeDirection] 37 | ); 38 | 39 | const theme = createTheme(themeOptions); 40 | 41 | theme.components = componentsOverride(theme); 42 | 43 | return ( 44 | 45 | 46 | 47 | {children} 48 | 49 | 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /src/theme/overrides/Accordion.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Accordion(theme) { 4 | return { 5 | MuiAccordion: { 6 | styleOverrides: { 7 | root: { 8 | '&.Mui-expanded': { 9 | boxShadow: theme.customShadows.z8, 10 | borderRadius: theme.shape.borderRadius, 11 | }, 12 | '&.Mui-disabled': { 13 | backgroundColor: 'transparent', 14 | }, 15 | }, 16 | }, 17 | }, 18 | MuiAccordionSummary: { 19 | styleOverrides: { 20 | root: { 21 | paddingLeft: theme.spacing(2), 22 | paddingRight: theme.spacing(1), 23 | '&.Mui-disabled': { 24 | opacity: 1, 25 | color: theme.palette.action.disabled, 26 | '& .MuiTypography-root': { 27 | color: 'inherit', 28 | }, 29 | }, 30 | }, 31 | expandIconWrapper: { 32 | color: 'inherit', 33 | }, 34 | }, 35 | }, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /src/theme/overrides/Autocomplete.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Autocomplete(theme) { 4 | return { 5 | MuiAutocomplete: { 6 | styleOverrides: { 7 | paper: { 8 | boxShadow: theme.customShadows.dropdown, 9 | }, 10 | listbox: { 11 | padding: theme.spacing(0, 1), 12 | '& .MuiAutocomplete-option': { 13 | padding: theme.spacing(1), 14 | margin: theme.spacing(1, 0), 15 | borderRadius: theme.shape.borderRadius, 16 | }, 17 | }, 18 | }, 19 | }, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/theme/overrides/Avatar.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Avatar(theme) { 4 | return { 5 | MuiAvatar: { 6 | styleOverrides: { 7 | colorDefault: { 8 | color: theme.palette.text.secondary, 9 | backgroundColor: theme.palette.grey[400], 10 | }, 11 | }, 12 | }, 13 | MuiAvatarGroup: { 14 | styleOverrides: { 15 | avatar: { 16 | fontSize: 16, 17 | fontWeight: theme.typography.fontWeightMedium, 18 | '&:first-of-type': { 19 | fontSize: 14, 20 | color: theme.palette.primary.main, 21 | backgroundColor: theme.palette.primary.lighter, 22 | }, 23 | }, 24 | }, 25 | }, 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/theme/overrides/Backdrop.js: -------------------------------------------------------------------------------- 1 | import { alpha } from '@mui/material/styles'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function Backdrop(theme) { 6 | const varLow = alpha(theme.palette.grey[900], 0.48); 7 | const varHigh = alpha(theme.palette.grey[900], 1); 8 | 9 | return { 10 | MuiBackdrop: { 11 | styleOverrides: { 12 | root: { 13 | background: [ 14 | `rgb(22,28,36)`, 15 | `-moz-linear-gradient(75deg, ${varLow} 0%, ${varHigh} 100%)`, 16 | `-webkit-linear-gradient(75deg, ${varLow} 0%, ${varHigh} 100%)`, 17 | `linear-gradient(75deg, ${varLow} 0%, ${varHigh} 100%)`, 18 | ], 19 | '&.MuiBackdrop-invisible': { 20 | background: 'transparent', 21 | }, 22 | }, 23 | }, 24 | }, 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /src/theme/overrides/Badge.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Badge() { 4 | return { 5 | MuiBadge: { 6 | styleOverrides: { 7 | dot: { 8 | width: 10, 9 | height: 10, 10 | borderRadius: '50%', 11 | }, 12 | }, 13 | }, 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/theme/overrides/Breadcrumbs.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Breadcrumbs(theme) { 4 | return { 5 | MuiBreadcrumbs: { 6 | styleOverrides: { 7 | separator: { 8 | marginLeft: theme.spacing(2), 9 | marginRight: theme.spacing(2), 10 | }, 11 | }, 12 | }, 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /src/theme/overrides/Button.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Button(theme) { 4 | return { 5 | MuiButton: { 6 | styleOverrides: { 7 | root: { 8 | '&:hover': { 9 | boxShadow: 'none', 10 | }, 11 | }, 12 | sizeLarge: { 13 | height: 48, 14 | }, 15 | // contained 16 | containedInherit: { 17 | color: theme.palette.grey[800], 18 | boxShadow: theme.customShadows.z8, 19 | '&:hover': { 20 | backgroundColor: theme.palette.grey[400], 21 | }, 22 | }, 23 | containedPrimary: { 24 | boxShadow: theme.customShadows.primary, 25 | }, 26 | containedSecondary: { 27 | boxShadow: theme.customShadows.secondary, 28 | }, 29 | containedInfo: { 30 | boxShadow: theme.customShadows.info, 31 | }, 32 | containedSuccess: { 33 | boxShadow: theme.customShadows.success, 34 | }, 35 | containedWarning: { 36 | boxShadow: theme.customShadows.warning, 37 | }, 38 | containedError: { 39 | boxShadow: theme.customShadows.error, 40 | }, 41 | // outlined 42 | outlinedInherit: { 43 | border: `1px solid ${theme.palette.grey[500_32]}`, 44 | '&:hover': { 45 | backgroundColor: theme.palette.action.hover, 46 | }, 47 | }, 48 | textInherit: { 49 | '&:hover': { 50 | backgroundColor: theme.palette.action.hover, 51 | }, 52 | }, 53 | }, 54 | }, 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /src/theme/overrides/ButtonGroup.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function ButtonGroup(theme) { 4 | const styleContained = (color) => ({ 5 | props: { variant: 'contained', color }, 6 | style: { boxShadow: theme.customShadows[color] }, 7 | }); 8 | 9 | return { 10 | MuiButtonGroup: { 11 | variants: [ 12 | { 13 | props: { variant: 'contained', color: 'inherit' }, 14 | style: { boxShadow: theme.customShadows.z8 }, 15 | }, 16 | styleContained('primary'), 17 | styleContained('secondary'), 18 | styleContained('info'), 19 | styleContained('success'), 20 | styleContained('warning'), 21 | styleContained('error'), 22 | 23 | { 24 | props: { disabled: true }, 25 | style: { 26 | boxShadow: 'none', 27 | '& .MuiButtonGroup-grouped.Mui-disabled': { 28 | color: theme.palette.action.disabled, 29 | borderColor: `${theme.palette.action.disabledBackground} !important`, 30 | '&.MuiButton-contained': { 31 | backgroundColor: theme.palette.action.disabledBackground, 32 | }, 33 | }, 34 | }, 35 | }, 36 | ], 37 | 38 | styleOverrides: { 39 | root: { 40 | '&:hover': { 41 | boxShadow: 'none', 42 | }, 43 | }, 44 | }, 45 | }, 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /src/theme/overrides/Card.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Card(theme) { 4 | return { 5 | MuiCard: { 6 | styleOverrides: { 7 | root: { 8 | position: 'relative', 9 | boxShadow: theme.customShadows.card, 10 | borderRadius: Number(theme.shape.borderRadius) * 2, 11 | zIndex: 0, // Fix Safari overflow: hidden with border radius 12 | }, 13 | }, 14 | }, 15 | MuiCardHeader: { 16 | defaultProps: { 17 | titleTypographyProps: { variant: 'h6' }, 18 | subheaderTypographyProps: { variant: 'body2', marginTop: theme.spacing(0.5) }, 19 | }, 20 | styleOverrides: { 21 | root: { 22 | padding: theme.spacing(3, 3, 0), 23 | }, 24 | }, 25 | }, 26 | MuiCardContent: { 27 | styleOverrides: { 28 | root: { 29 | padding: theme.spacing(3), 30 | }, 31 | }, 32 | }, 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /src/theme/overrides/Checkbox.js: -------------------------------------------------------------------------------- 1 | // 2 | import { CheckboxIcon, CheckboxCheckedIcon, CheckboxIndeterminateIcon } from './CustomIcons'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function Checkbox(theme) { 7 | return { 8 | MuiCheckbox: { 9 | defaultProps: { 10 | icon: , 11 | checkedIcon: , 12 | indeterminateIcon: , 13 | }, 14 | 15 | styleOverrides: { 16 | root: { 17 | padding: theme.spacing(1), 18 | '&.Mui-checked.Mui-disabled, &.Mui-disabled': { 19 | color: theme.palette.action.disabled, 20 | }, 21 | '& .MuiSvgIcon-fontSizeMedium': { 22 | width: 24, 23 | height: 24, 24 | }, 25 | '& .MuiSvgIcon-fontSizeSmall': { 26 | width: 20, 27 | height: 20, 28 | }, 29 | svg: { 30 | fontSize: 24, 31 | '&[font-size=small]': { 32 | fontSize: 20, 33 | }, 34 | }, 35 | }, 36 | }, 37 | }, 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /src/theme/overrides/Chip.js: -------------------------------------------------------------------------------- 1 | // 2 | import { CloseIcon } from './CustomIcons'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function Chip(theme) { 7 | return { 8 | MuiChip: { 9 | defaultProps: { 10 | deleteIcon: , 11 | }, 12 | 13 | styleOverrides: { 14 | colorDefault: { 15 | '& .MuiChip-avatarMedium, .MuiChip-avatarSmall': { 16 | color: theme.palette.text.secondary, 17 | }, 18 | }, 19 | outlined: { 20 | borderColor: theme.palette.grey[500_32], 21 | '&.MuiChip-colorPrimary': { 22 | borderColor: theme.palette.primary.main, 23 | }, 24 | '&.MuiChip-colorSecondary': { 25 | borderColor: theme.palette.secondary.main, 26 | }, 27 | }, 28 | // 29 | avatarColorInfo: { 30 | color: theme.palette.info.contrastText, 31 | backgroundColor: theme.palette.info.dark, 32 | }, 33 | avatarColorSuccess: { 34 | color: theme.palette.success.contrastText, 35 | backgroundColor: theme.palette.success.dark, 36 | }, 37 | avatarColorWarning: { 38 | color: theme.palette.warning.contrastText, 39 | backgroundColor: theme.palette.warning.dark, 40 | }, 41 | avatarColorError: { 42 | color: theme.palette.error.contrastText, 43 | backgroundColor: theme.palette.error.dark, 44 | }, 45 | }, 46 | }, 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /src/theme/overrides/ControlLabel.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function ControlLabel(theme) { 4 | return { 5 | MuiFormControlLabel: { 6 | styleOverrides: { 7 | label: { 8 | ...theme.typography.body2, 9 | }, 10 | }, 11 | }, 12 | MuiFormHelperText: { 13 | styleOverrides: { 14 | root: { 15 | marginTop: theme.spacing(1), 16 | }, 17 | }, 18 | }, 19 | MuiFormLabel: { 20 | styleOverrides: { 21 | root: { 22 | color: theme.palette.text.disabled, 23 | }, 24 | }, 25 | }, 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/theme/overrides/CssBaseline.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function CssBaseline() { 4 | return { 5 | MuiCssBaseline: { 6 | styleOverrides: { 7 | '*': { 8 | margin: 0, 9 | padding: 0, 10 | boxSizing: 'border-box', 11 | }, 12 | html: { 13 | width: '100%', 14 | height: '100%', 15 | WebkitOverflowScrolling: 'touch', 16 | }, 17 | body: { 18 | width: '100%', 19 | height: '100%', 20 | }, 21 | '#root': { 22 | width: '100%', 23 | height: '100%', 24 | }, 25 | input: { 26 | '&[type=number]': { 27 | MozAppearance: 'textfield', 28 | '&::-webkit-outer-spin-button': { 29 | margin: 0, 30 | WebkitAppearance: 'none', 31 | }, 32 | '&::-webkit-inner-spin-button': { 33 | margin: 0, 34 | WebkitAppearance: 'none', 35 | }, 36 | }, 37 | }, 38 | img: { 39 | display: 'block', 40 | maxWidth: '100%', 41 | }, 42 | }, 43 | }, 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /src/theme/overrides/Dialog.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Dialog(theme) { 4 | return { 5 | MuiDialog: { 6 | styleOverrides: { 7 | paper: { 8 | boxShadow: theme.customShadows.dialog, 9 | '&.MuiPaper-rounded': { 10 | borderRadius: Number(theme.shape.borderRadius) * 2, 11 | }, 12 | '&.MuiDialog-paperFullScreen': { 13 | borderRadius: 0, 14 | }, 15 | '&.MuiDialog-paper .MuiDialogActions-root': { 16 | padding: theme.spacing(3), 17 | }, 18 | '@media (max-width: 600px)': { 19 | margin: theme.spacing(2), 20 | }, 21 | '@media (max-width: 663.95px)': { 22 | '&.MuiDialog-paperWidthSm.MuiDialog-paperScrollBody': { 23 | maxWidth: '100%', 24 | }, 25 | }, 26 | }, 27 | paperFullWidth: { 28 | width: '100%', 29 | }, 30 | }, 31 | }, 32 | MuiDialogTitle: { 33 | styleOverrides: { 34 | root: { 35 | padding: theme.spacing(3, 3, 0), 36 | }, 37 | }, 38 | }, 39 | MuiDialogContent: { 40 | styleOverrides: { 41 | root: { 42 | borderTop: 0, 43 | borderBottom: 0, 44 | padding: theme.spacing(3), 45 | }, 46 | }, 47 | }, 48 | MuiDialogActions: { 49 | styleOverrides: { 50 | root: { 51 | '& > :not(:first-of-type)': { 52 | marginLeft: theme.spacing(1.5), 53 | }, 54 | }, 55 | }, 56 | }, 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /src/theme/overrides/Drawer.js: -------------------------------------------------------------------------------- 1 | import { alpha } from '@mui/material'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function Drawer(theme) { 6 | const isLight = theme.palette.mode === 'light'; 7 | 8 | return { 9 | MuiDrawer: { 10 | styleOverrides: { 11 | modal: { 12 | '&[role="presentation"]': { 13 | '& .MuiDrawer-paperAnchorLeft': { 14 | boxShadow: `8px 24px 24px 12px ${alpha(theme.palette.grey[900], isLight ? 0.16 : 0.48)}`, 15 | }, 16 | '& .MuiDrawer-paperAnchorRight': { 17 | boxShadow: `-8px 24px 24px 12px ${alpha(theme.palette.grey[900], isLight ? 0.16 : 0.48)}`, 18 | }, 19 | }, 20 | }, 21 | }, 22 | }, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/theme/overrides/Fab.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Fab(theme) { 4 | return { 5 | MuiFab: { 6 | defaultProps: { 7 | color: 'primary', 8 | }, 9 | 10 | styleOverrides: { 11 | root: { 12 | boxShadow: theme.customShadows.z8, 13 | '&:hover': { 14 | boxShadow: 'none', 15 | backgroundColor: theme.palette.grey[400], 16 | }, 17 | }, 18 | primary: { 19 | boxShadow: theme.customShadows.primary, 20 | '&:hover': { 21 | backgroundColor: theme.palette.primary.dark, 22 | }, 23 | }, 24 | secondary: { 25 | boxShadow: theme.customShadows.secondary, 26 | '&:hover': { 27 | backgroundColor: theme.palette.secondary.dark, 28 | }, 29 | }, 30 | extended: { 31 | '& svg': { 32 | marginRight: theme.spacing(1), 33 | }, 34 | }, 35 | }, 36 | }, 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /src/theme/overrides/Input.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Input(theme) { 4 | return { 5 | MuiInputBase: { 6 | styleOverrides: { 7 | root: { 8 | '&.Mui-disabled': { 9 | '& svg': { color: theme.palette.text.disabled }, 10 | }, 11 | }, 12 | input: { 13 | '&::placeholder': { 14 | opacity: 1, 15 | color: theme.palette.text.disabled, 16 | }, 17 | }, 18 | }, 19 | }, 20 | MuiInput: { 21 | styleOverrides: { 22 | underline: { 23 | '&:before': { 24 | borderBottomColor: theme.palette.grey[500_56], 25 | }, 26 | }, 27 | }, 28 | }, 29 | MuiFilledInput: { 30 | styleOverrides: { 31 | root: { 32 | backgroundColor: theme.palette.grey[500_12], 33 | '&:hover': { 34 | backgroundColor: theme.palette.grey[500_16], 35 | }, 36 | '&.Mui-focused': { 37 | backgroundColor: theme.palette.action.focus, 38 | }, 39 | '&.Mui-disabled': { 40 | backgroundColor: theme.palette.action.disabledBackground, 41 | }, 42 | }, 43 | underline: { 44 | '&:before': { 45 | borderBottomColor: theme.palette.grey[500_56], 46 | }, 47 | }, 48 | }, 49 | }, 50 | MuiOutlinedInput: { 51 | styleOverrides: { 52 | root: { 53 | '& .MuiOutlinedInput-notchedOutline': { 54 | borderColor: theme.palette.grey[500_32], 55 | }, 56 | '&.Mui-disabled': { 57 | '& .MuiOutlinedInput-notchedOutline': { 58 | borderColor: theme.palette.action.disabledBackground, 59 | }, 60 | }, 61 | }, 62 | }, 63 | }, 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /src/theme/overrides/Link.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Link() { 4 | return { 5 | MuiLink: { 6 | defaultProps: { 7 | underline: 'hover', 8 | }, 9 | }, 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /src/theme/overrides/List.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function List(theme) { 4 | return { 5 | MuiListItemIcon: { 6 | styleOverrides: { 7 | root: { 8 | color: 'inherit', 9 | minWidth: 'auto', 10 | marginRight: theme.spacing(2), 11 | }, 12 | }, 13 | }, 14 | MuiListItemAvatar: { 15 | styleOverrides: { 16 | root: { 17 | minWidth: 'auto', 18 | marginRight: theme.spacing(2), 19 | }, 20 | }, 21 | }, 22 | MuiListItemText: { 23 | styleOverrides: { 24 | root: { 25 | marginTop: 0, 26 | marginBottom: 0, 27 | }, 28 | multiline: { 29 | marginTop: 0, 30 | marginBottom: 0, 31 | }, 32 | }, 33 | }, 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/theme/overrides/LoadingButton.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function LoadingButton() { 4 | return { 5 | MuiLoadingButton: { 6 | styleOverrides: { 7 | root: { 8 | '&.MuiButton-text': { 9 | '& .MuiLoadingButton-startIconPendingStart': { 10 | marginLeft: 0, 11 | }, 12 | '& .MuiLoadingButton-endIconPendingEnd': { 13 | marginRight: 0, 14 | }, 15 | }, 16 | }, 17 | }, 18 | }, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/theme/overrides/Menu.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Menu(theme) { 4 | return { 5 | MuiMenuItem: { 6 | styleOverrides: { 7 | root: { 8 | '&.Mui-selected': { 9 | backgroundColor: theme.palette.action.selected, 10 | '&:hover': { 11 | backgroundColor: theme.palette.action.hover, 12 | }, 13 | }, 14 | }, 15 | }, 16 | }, 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /src/theme/overrides/Pagination.js: -------------------------------------------------------------------------------- 1 | import { alpha } from '@mui/material/styles'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function Pagination(theme) { 6 | return { 7 | MuiPaginationItem: { 8 | styleOverrides: { 9 | root: { 10 | '&.Mui-selected': { 11 | fontWeight: theme.typography.fontWeightBold, 12 | }, 13 | }, 14 | textPrimary: { 15 | '&.Mui-selected': { 16 | color: theme.palette.primary.main, 17 | backgroundColor: alpha(theme.palette.primary.main, 0.08), 18 | '&:hover, &.Mui-focusVisible': { 19 | backgroundColor: `${alpha(theme.palette.primary.main, 0.24)} !important`, 20 | }, 21 | }, 22 | }, 23 | outlined: { 24 | border: `1px solid ${theme.palette.grey[500_32]}`, 25 | }, 26 | outlinedPrimary: { 27 | '&.Mui-selected': { 28 | backgroundColor: alpha(theme.palette.primary.main, 0.08), 29 | border: `1px solid ${alpha(theme.palette.primary.main, 0.24)}`, 30 | }, 31 | }, 32 | }, 33 | }, 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/theme/overrides/Paper.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Paper(theme) { 4 | return { 5 | MuiPaper: { 6 | defaultProps: { 7 | elevation: 0, 8 | }, 9 | 10 | variants: [ 11 | { 12 | props: { variant: 'outlined' }, 13 | style: { borderColor: theme.palette.grey[500_12] }, 14 | }, 15 | ], 16 | 17 | styleOverrides: { 18 | root: { 19 | backgroundImage: 'none', 20 | }, 21 | }, 22 | }, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/theme/overrides/Popover.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Popover(theme) { 4 | return { 5 | MuiPopover: { 6 | styleOverrides: { 7 | paper: { 8 | boxShadow: theme.customShadows.dropdown, 9 | borderRadius: Number(theme.shape.borderRadius) * 1.5, 10 | }, 11 | }, 12 | }, 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /src/theme/overrides/Progress.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Progress(theme) { 4 | const isLight = theme.palette.mode === 'light'; 5 | 6 | return { 7 | MuiLinearProgress: { 8 | styleOverrides: { 9 | root: { 10 | borderRadius: 4, 11 | overflow: 'hidden', 12 | }, 13 | bar: { 14 | borderRadius: 4, 15 | }, 16 | colorPrimary: { 17 | backgroundColor: theme.palette.primary[isLight ? 'lighter' : 'darker'], 18 | }, 19 | buffer: { 20 | backgroundColor: 'transparent', 21 | }, 22 | }, 23 | }, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /src/theme/overrides/Radio.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Radio(theme) { 4 | return { 5 | MuiRadio: { 6 | styleOverrides: { 7 | root: { 8 | padding: theme.spacing(1), 9 | svg: { 10 | fontSize: 24, 11 | '&[font-size=small]': { 12 | fontSize: 20, 13 | }, 14 | }, 15 | }, 16 | }, 17 | }, 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /src/theme/overrides/Rating.js: -------------------------------------------------------------------------------- 1 | // 2 | import { StarIcon } from './CustomIcons'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | const ICON_SMALL = { width: 20, height: 20 }; 7 | const ICON_LARGE = { width: 28, height: 28 }; 8 | 9 | export default function Rating(theme) { 10 | return { 11 | MuiRating: { 12 | defaultProps: { 13 | emptyIcon: , 14 | icon: , 15 | }, 16 | 17 | styleOverrides: { 18 | root: { 19 | '&.Mui-disabled': { 20 | opacity: 0.48, 21 | }, 22 | }, 23 | iconEmpty: { color: theme.palette.grey[500_48] }, 24 | sizeSmall: { '& svg': { ...ICON_SMALL } }, 25 | sizeLarge: { '& svg': { ...ICON_LARGE } }, 26 | }, 27 | }, 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /src/theme/overrides/Select.js: -------------------------------------------------------------------------------- 1 | // 2 | import { InputSelectIcon } from './CustomIcons'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | export default function Select() { 7 | return { 8 | MuiSelect: { 9 | defaultProps: { 10 | IconComponent: InputSelectIcon, 11 | }, 12 | }, 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /src/theme/overrides/Skeleton.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Skeleton(theme) { 4 | return { 5 | MuiSkeleton: { 6 | defaultProps: { 7 | animation: 'wave', 8 | }, 9 | 10 | styleOverrides: { 11 | root: { 12 | backgroundColor: theme.palette.background.neutral, 13 | }, 14 | }, 15 | }, 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /src/theme/overrides/Slider.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Slider(theme) { 4 | const isLight = theme.palette.mode === 'light'; 5 | 6 | return { 7 | MuiSlider: { 8 | defaultProps: { 9 | size: 'small', 10 | }, 11 | 12 | styleOverrides: { 13 | root: { 14 | '&.Mui-disabled': { 15 | color: theme.palette.action.disabled, 16 | }, 17 | }, 18 | markLabel: { 19 | fontSize: 13, 20 | color: theme.palette.text.disabled, 21 | }, 22 | valueLabel: { 23 | borderRadius: 8, 24 | backgroundColor: theme.palette.grey[isLight ? 800 : 700], 25 | }, 26 | }, 27 | }, 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /src/theme/overrides/Stepper.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Stepper(theme) { 4 | return { 5 | MuiStepConnector: { 6 | styleOverrides: { 7 | line: { 8 | borderColor: theme.palette.divider, 9 | }, 10 | }, 11 | }, 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /src/theme/overrides/SvgIcon.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function SvgIcon() { 4 | return { 5 | MuiSvgIcon: { 6 | styleOverrides: { 7 | fontSizeSmall: { 8 | width: 20, 9 | height: 20, 10 | fontSize: 'inherit', 11 | }, 12 | fontSizeLarge: { 13 | width: 32, 14 | height: 32, 15 | fontSize: 'inherit', 16 | }, 17 | }, 18 | }, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/theme/overrides/Switch.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Switch(theme) { 4 | const isLight = theme.palette.mode === 'light'; 5 | 6 | return { 7 | MuiSwitch: { 8 | styleOverrides: { 9 | thumb: { 10 | boxShadow: theme.customShadows.z1, 11 | }, 12 | track: { 13 | opacity: 1, 14 | backgroundColor: theme.palette.grey[500], 15 | }, 16 | switchBase: { 17 | left: 0, 18 | right: 'auto', 19 | '&:not(:.Mui-checked)': { 20 | color: theme.palette.grey[isLight ? 100 : 300], 21 | }, 22 | '&.Mui-checked.Mui-disabled, &.Mui-disabled': { 23 | color: theme.palette.grey[isLight ? 400 : 600], 24 | }, 25 | '&.Mui-disabled+.MuiSwitch-track': { 26 | opacity: 1, 27 | backgroundColor: `${theme.palette.action.disabledBackground} !important`, 28 | }, 29 | }, 30 | }, 31 | }, 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /src/theme/overrides/Tabs.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Tabs(theme) { 4 | return { 5 | MuiTab: { 6 | styleOverrides: { 7 | root: { 8 | padding: 0, 9 | fontWeight: theme.typography.fontWeightMedium, 10 | borderTopLeftRadius: theme.shape.borderRadius, 11 | borderTopRightRadius: theme.shape.borderRadius, 12 | '&.Mui-selected': { 13 | color: theme.palette.text.primary, 14 | }, 15 | '&:not(:last-of-type)': { 16 | marginRight: theme.spacing(5), 17 | }, 18 | '@media (min-width: 600px)': { 19 | minWidth: 48, 20 | }, 21 | }, 22 | labelIcon: { 23 | minHeight: 48, 24 | flexDirection: 'row', 25 | '& > *:first-of-type': { 26 | marginBottom: 0, 27 | marginRight: theme.spacing(1), 28 | }, 29 | }, 30 | wrapper: { 31 | flexDirection: 'row', 32 | whiteSpace: 'nowrap', 33 | }, 34 | textColorInherit: { 35 | opacity: 1, 36 | color: theme.palette.text.secondary, 37 | }, 38 | }, 39 | }, 40 | MuiTabPanel: { 41 | styleOverrides: { 42 | root: { 43 | padding: 0, 44 | }, 45 | }, 46 | }, 47 | MuiTabScrollButton: { 48 | styleOverrides: { 49 | root: { 50 | width: 48, 51 | borderRadius: '50%', 52 | }, 53 | }, 54 | }, 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /src/theme/overrides/Timeline.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Timeline(theme) { 4 | return { 5 | MuiTimelineDot: { 6 | styleOverrides: { 7 | root: { 8 | boxShadow: 'none', 9 | }, 10 | }, 11 | }, 12 | 13 | MuiTimelineConnector: { 14 | styleOverrides: { 15 | root: { 16 | backgroundColor: theme.palette.divider, 17 | }, 18 | }, 19 | }, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/theme/overrides/ToggleButton.js: -------------------------------------------------------------------------------- 1 | import { alpha } from '@mui/material/styles'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function ToggleButton(theme) { 6 | const style = (color) => ({ 7 | props: { color }, 8 | style: { 9 | '&:hover': { 10 | borderColor: alpha(theme.palette[color].main, 0.48), 11 | backgroundColor: alpha(theme.palette[color].main, theme.palette.action.hoverOpacity), 12 | }, 13 | '&.Mui-selected': { 14 | borderColor: alpha(theme.palette[color].main, 0.48), 15 | }, 16 | }, 17 | }); 18 | 19 | return { 20 | MuiToggleButton: { 21 | variants: [ 22 | { 23 | props: { color: 'standard' }, 24 | style: { 25 | '&.Mui-selected': { 26 | backgroundColor: theme.palette.action.selected, 27 | }, 28 | }, 29 | }, 30 | style('primary'), 31 | style('secondary'), 32 | style('info'), 33 | style('success'), 34 | style('warning'), 35 | style('error'), 36 | ], 37 | }, 38 | MuiToggleButtonGroup: { 39 | styleOverrides: { 40 | root: { 41 | borderRadius: theme.shape.borderRadius, 42 | backgroundColor: theme.palette.background.paper, 43 | border: `solid 1px ${theme.palette.grey[500_12]}`, 44 | '& .MuiToggleButton-root': { 45 | margin: 4, 46 | borderColor: 'transparent !important', 47 | borderRadius: `${theme.shape.borderRadius}px !important`, 48 | }, 49 | }, 50 | }, 51 | }, 52 | }; 53 | } 54 | -------------------------------------------------------------------------------- /src/theme/overrides/Tooltip.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Tooltip(theme) { 4 | const isLight = theme.palette.mode === 'light'; 5 | 6 | return { 7 | MuiTooltip: { 8 | styleOverrides: { 9 | tooltip: { 10 | backgroundColor: theme.palette.grey[isLight ? 800 : 700], 11 | }, 12 | arrow: { 13 | color: theme.palette.grey[isLight ? 800 : 700], 14 | }, 15 | }, 16 | }, 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /src/theme/overrides/TreeView.js: -------------------------------------------------------------------------------- 1 | import { TreeViewCollapseIcon, TreeViewExpandIcon, TreeViewEndIcon } from './CustomIcons'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export default function TreeView(theme) { 6 | return { 7 | MuiTreeView: { 8 | defaultProps: { 9 | defaultCollapseIcon: , 10 | defaultExpandIcon: , 11 | defaultEndIcon: , 12 | }, 13 | }, 14 | MuiTreeItem: { 15 | styleOverrides: { 16 | label: { ...theme.typography.body2 }, 17 | iconContainer: { width: 'auto' }, 18 | }, 19 | }, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/theme/overrides/Typography.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function Typography(theme) { 4 | return { 5 | MuiTypography: { 6 | styleOverrides: { 7 | paragraph: { 8 | marginBottom: theme.spacing(2), 9 | }, 10 | gutterBottom: { 11 | marginBottom: theme.spacing(1), 12 | }, 13 | }, 14 | }, 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /src/utils/axios.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | // config 3 | import { HOST_API } from '../config'; 4 | 5 | // ---------------------------------------------------------------------- 6 | 7 | const axiosInstance = axios.create({ 8 | baseURL: HOST_API, 9 | }); 10 | 11 | axiosInstance.interceptors.response.use( 12 | (response) => response, 13 | (error) => Promise.reject((error.response && error.response.data) || 'Something went wrong') 14 | ); 15 | 16 | export default axiosInstance; 17 | -------------------------------------------------------------------------------- /src/utils/createAvatar.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | const PRIMARY_NAME = ['A', 'N', 'H', 'L', 'Q', '9', '8']; 4 | const INFO_NAME = ['F', 'G', 'T', 'I', 'J', '1', '2', '3']; 5 | const SUCCESS_NAME = ['K', 'D', 'Y', 'B', 'O', '4', '5']; 6 | const WARNING_NAME = ['P', 'E', 'R', 'S', 'C', 'U', '6', '7']; 7 | const ERROR_NAME = ['V', 'W', 'X', 'M', 'Z']; 8 | 9 | function getFirstCharacter(name) { 10 | return name && name.charAt(0).toUpperCase(); 11 | } 12 | 13 | function getAvatarColor(name) { 14 | if (PRIMARY_NAME.includes(getFirstCharacter(name))) return 'primary'; 15 | if (INFO_NAME.includes(getFirstCharacter(name))) return 'info'; 16 | if (SUCCESS_NAME.includes(getFirstCharacter(name))) return 'success'; 17 | if (WARNING_NAME.includes(getFirstCharacter(name))) return 'warning'; 18 | if (ERROR_NAME.includes(getFirstCharacter(name))) return 'warning'; 19 | return 'default'; 20 | } 21 | 22 | export default function createAvatar(name) { 23 | return { 24 | name: getFirstCharacter(name), 25 | color: getAvatarColor(name), 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/utils/cssStyles.js: -------------------------------------------------------------------------------- 1 | import { alpha } from '@mui/material/styles'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | function getDirection(value = 'bottom') { 6 | return { 7 | top: 'to top', 8 | right: 'to right', 9 | bottom: 'to bottom', 10 | left: 'to left', 11 | }[value]; 12 | } 13 | 14 | // ---------------------------------------------------------------------- 15 | 16 | export default function cssStyles(theme) { 17 | return { 18 | bgBlur: (props) => { 19 | const color = props?.color || theme?.palette.background.default || '#000000'; 20 | 21 | const blur = props?.blur || 6; 22 | const opacity = props?.opacity || 0.8; 23 | 24 | return { 25 | backdropFilter: `blur(${blur}px)`, 26 | WebkitBackdropFilter: `blur(${blur}px)`, // Fix on Mobile 27 | backgroundColor: alpha(color, opacity), 28 | }; 29 | }, 30 | bgGradient: (props) => { 31 | const direction = getDirection(props?.direction); 32 | const startColor = props?.startColor || `${alpha('#000000', 0)} 0%`; 33 | const endColor = props?.endColor || '#000000 75%'; 34 | 35 | return { 36 | background: `linear-gradient(${direction}, ${startColor}, ${endColor});`, 37 | }; 38 | }, 39 | bgImage: (props) => { 40 | const url = props?.url || '/assets/bg_gradient.jpg'; 41 | const direction = getDirection(props?.direction); 42 | const startColor = props?.startColor || alpha(theme?.palette.grey[900] || '#000000', 0.88); 43 | const endColor = props?.endColor || alpha(theme?.palette.grey[900] || '#000000', 0.88); 44 | 45 | return { 46 | background: `linear-gradient(${direction}, ${startColor}, ${endColor}), url(${url})`, 47 | backgroundSize: 'cover', 48 | backgroundRepeat: 'no-repeat', 49 | backgroundPosition: 'center center', 50 | }; 51 | }, 52 | }; 53 | } 54 | -------------------------------------------------------------------------------- /src/utils/formatNumber.js: -------------------------------------------------------------------------------- 1 | import numeral from 'numeral'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export function fCurrency(number) { 6 | return numeral(number).format(Number.isInteger(number) ? '$0,0' : '$0,0.00'); 7 | } 8 | 9 | export function fPercent(number) { 10 | return numeral(number / 100).format('0.0%'); 11 | } 12 | 13 | export function fNumber(number) { 14 | return numeral(number).format(); 15 | } 16 | 17 | export function fShortenNumber(number) { 18 | return numeral(number).format('0.00a').replace('.00', ''); 19 | } 20 | 21 | export function fData(number) { 22 | return numeral(number).format('0.0 b'); 23 | } 24 | -------------------------------------------------------------------------------- /src/utils/formatTime.js: -------------------------------------------------------------------------------- 1 | import { format, getTime, formatDistanceToNow } from 'date-fns'; 2 | 3 | // ---------------------------------------------------------------------- 4 | 5 | export function fDate(date) { 6 | return format(new Date(date), 'dd MMMM yyyy'); 7 | } 8 | 9 | export function fDateTime(date) { 10 | return format(new Date(date), 'dd MMM yyyy HH:mm'); 11 | } 12 | 13 | export function fTimestamp(date) { 14 | return getTime(new Date(date)); 15 | } 16 | 17 | export function fDateTimeSuffix(date) { 18 | return format(new Date(date), 'dd/MM/yyyy hh:mm p'); 19 | } 20 | 21 | export function fToNow(date) { 22 | return formatDistanceToNow(new Date(date), { 23 | addSuffix: true 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /src/utils/getColorName.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function getColorName(hex) { 4 | let color; 5 | 6 | switch (hex) { 7 | case '#00AB55': 8 | color = 'Green'; 9 | break; 10 | case '#000000': 11 | color = 'Black'; 12 | break; 13 | case '#FFFFFF': 14 | color = 'White'; 15 | break; 16 | case '#FFC0CB': 17 | color = 'Pink'; 18 | break; 19 | case '#FF4842': 20 | color = 'Red'; 21 | break; 22 | case '#1890FF': 23 | color = 'Blue'; 24 | break; 25 | case '#94D82D': 26 | color = 'Greenyellow'; 27 | break; 28 | case '#FFC107': 29 | color = 'Orange'; 30 | break; 31 | default: 32 | color = hex; 33 | } 34 | 35 | return color; 36 | } 37 | -------------------------------------------------------------------------------- /src/utils/getFileData.js: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------- 2 | 3 | export default function getFileData(file, index) { 4 | if (typeof file === 'string') { 5 | return { 6 | key: index ? `${file}-${index}` : file, 7 | preview: file, 8 | }; 9 | } 10 | 11 | return { 12 | key: index ? `${file.name}-${index}` : file.name, 13 | name: file.name, 14 | size: file.size, 15 | path: file.path, 16 | type: file.type, 17 | preview: file.preview, 18 | lastModified: file.lastModified, 19 | lastModifiedDate: file.lastModifiedDate, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/utils/highlight.js: -------------------------------------------------------------------------------- 1 | import hljs from 'highlight.js'; 2 | import 'highlight.js/styles/atom-one-dark-reasonable.css'; 3 | 4 | // ---------------------------------------------------------------------- 5 | 6 | hljs.configure({ 7 | languages: ['javascript', 'jsx', 'sh', 'bash', 'html', 'scss', 'css', 'json'], 8 | }); 9 | 10 | if (typeof window !== 'undefined') { 11 | window.hljs = hljs; 12 | } 13 | -------------------------------------------------------------------------------- /src/utils/jwt.js: -------------------------------------------------------------------------------- 1 | import jwtDecode from 'jwt-decode'; 2 | // routes 3 | import { PATH_AUTH } from '../routes/paths'; 4 | // 5 | import axios from './axios'; 6 | 7 | // ---------------------------------------------------------------------- 8 | 9 | const isValidToken = (accessToken) => { 10 | if (!accessToken) { 11 | return false; 12 | } 13 | const decoded = jwtDecode(accessToken); 14 | 15 | const currentTime = Date.now() / 1000; 16 | 17 | return decoded.exp > currentTime; 18 | }; 19 | 20 | const handleTokenExpired = (exp) => { 21 | let expiredTimer; 22 | 23 | const currentTime = Date.now(); 24 | 25 | // Test token expires after 10s 26 | // const timeLeft = currentTime + 10000 - currentTime; // ~10s 27 | const timeLeft = exp * 1000 - currentTime; 28 | 29 | clearTimeout(expiredTimer); 30 | 31 | expiredTimer = setTimeout(() => { 32 | // eslint-disable-next-line no-alert 33 | alert('Token expired'); 34 | 35 | localStorage.removeItem('accessToken'); 36 | 37 | window.location.href = PATH_AUTH.login; 38 | }, timeLeft); 39 | }; 40 | 41 | const setSession = (accessToken) => { 42 | if (accessToken) { 43 | localStorage.setItem('accessToken', accessToken); 44 | axios.defaults.headers.common.Authorization = `Bearer ${accessToken}`; 45 | 46 | // This function below will handle when token is expired 47 | const { exp } = jwtDecode(accessToken); // ~5 days by server 48 | handleTokenExpired(exp); 49 | } else { 50 | localStorage.removeItem('accessToken'); 51 | delete axios.defaults.headers.common.Authorization; 52 | } 53 | }; 54 | 55 | export { isValidToken, setSession }; 56 | -------------------------------------------------------------------------------- /src/utils/mapboxgl.js: -------------------------------------------------------------------------------- 1 | import mapboxgl from 'mapbox-gl'; 2 | 3 | // eslint-disable-next-line 4 | mapboxgl.workerClass = require('worker-loader!mapbox-gl/dist/mapbox-gl-csp-worker').default; 5 | -------------------------------------------------------------------------------- /src/utils/uuidv4.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // ---------------------------------------------------------------------- 3 | 4 | export default function uuidv4() { 5 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 6 | const r = (Math.random() * 16) | 0, 7 | v = c === 'x' ? r : (r & 0x3) | 0x8; 8 | return v.toString(16); 9 | }); 10 | } 11 | --------------------------------------------------------------------------------