├── .gitignore
├── README.md
├── build
├── asset-manifest.json
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
├── robots.txt
└── static
│ ├── js
│ ├── 147.bb72a7f4.chunk.js
│ ├── 147.bb72a7f4.chunk.js.LICENSE.txt
│ ├── 147.bb72a7f4.chunk.js.map
│ ├── 207.53e720df.chunk.js
│ ├── 207.53e720df.chunk.js.map
│ ├── 338.ce6ba00d.chunk.js
│ ├── 338.ce6ba00d.chunk.js.map
│ ├── 339.44b407fa.chunk.js
│ ├── 339.44b407fa.chunk.js.map
│ ├── 345.c55149fb.chunk.js
│ ├── 345.c55149fb.chunk.js.map
│ ├── 376.81977eb6.chunk.js
│ ├── 376.81977eb6.chunk.js.map
│ ├── 472.f35afe9a.chunk.js
│ ├── 472.f35afe9a.chunk.js.map
│ ├── 572.087c84b7.chunk.js
│ ├── 572.087c84b7.chunk.js.map
│ ├── 631.8197571d.chunk.js
│ ├── 631.8197571d.chunk.js.map
│ ├── 678.8a7704c8.chunk.js
│ ├── 678.8a7704c8.chunk.js.map
│ ├── 787.35cea4b2.chunk.js
│ ├── 787.35cea4b2.chunk.js.map
│ ├── main.1ae3cbd8.js
│ ├── main.1ae3cbd8.js.LICENSE.txt
│ └── main.1ae3cbd8.js.map
│ └── media
│ └── logo.45af386bcce066c1c6ab.ico
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
└── src
├── App.js
├── assets
├── Illustration
│ └── NoChat.js
└── Images
│ └── logo.ico
├── components
├── AntSwitch.js
├── CallElement.js
├── Chat
│ ├── Footer.js
│ ├── Header.js
│ └── index.js
├── ChatElement.js
├── Iconify.js
├── Image
│ ├── Image.js
│ ├── getRatio.js
│ └── index.js
├── LoadingScreen.js
├── Scrollbar.js
├── Search
│ ├── Search.js
│ ├── SearchIconWrapper.js
│ ├── StyledInputBase.js
│ └── index.js
├── UserElement.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
├── hook-form
│ ├── FormProvider.js
│ ├── RHFAutocomplete.js
│ ├── RHFCodes.js
│ ├── RHFTextField.js
│ ├── RHFUpload.js
│ └── index.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
└── upload
│ ├── UploadAvatar.js
│ ├── index.js
│ └── preview
│ └── AvatarPreview.js
├── config.js
├── contexts
└── SettingsContext.js
├── data
└── index.js
├── hooks
├── useEventListener.js
├── useLocalStorage.js
├── useLocales.js
├── useResponsive.js
└── useSettings.js
├── index.js
├── layouts
├── auth
│ └── index.js
├── dashboard
│ ├── BottomNav.js
│ ├── ProfileMenu.js
│ ├── SideNav.js
│ └── index.js
└── main
│ └── index.js
├── pages
├── Page404.js
├── auth
│ ├── Login.js
│ ├── NewPassword.js
│ ├── Register.js
│ ├── ResetPassword.js
│ └── Verify.js
└── dashboard
│ ├── Call.js
│ ├── Chats.js
│ ├── Conversation.js
│ ├── GeneralApp.js
│ ├── Group.js
│ └── Settings
│ ├── Profile.js
│ └── index.js
├── redux
├── rootReducer.js
├── slices
│ ├── app.js
│ ├── audioCall.js
│ ├── auth.js
│ ├── conversation.js
│ └── videoCall.js
└── store.js
├── reportWebVitals.js
├── routes
├── index.js
└── paths.js
├── sections
├── Dashboard
│ ├── Audio
│ │ ├── CallDialog.js
│ │ └── CallNotification.js
│ ├── Contact.js
│ ├── Conversation.js
│ ├── CreateGroup.js
│ ├── Friends.js
│ ├── Settings
│ │ ├── ProfileForm.js
│ │ ├── ShortcutDialog.js
│ │ └── ThemeDialog.js
│ ├── SharedMessages.js
│ ├── StarredMessages.js
│ ├── StartCall.js
│ └── video
│ │ ├── CallDialog.js
│ │ └── CallNotification.js
└── auth
│ ├── AuthSocial.js
│ ├── LoginForm.js
│ ├── NewPasswordForm.js
│ ├── RegisterForm.js
│ ├── ResetPasswordForm.js
│ └── VerifyForm.js
├── socket.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
├── flattenArray.js
├── formatNumber.js
├── formatTime.js
├── getColorName.js
├── getColorPresets.js
├── getFileData.js
├── getFileFormat.js
├── getFontValue.js
├── highlight.js
├── jwt.js
├── s3.js
├── truncate.js
└── uuidv4.js
/.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.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/build/asset-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": {
3 | "main.js": "/static/js/main.1ae3cbd8.js",
4 | "static/js/338.ce6ba00d.chunk.js": "/static/js/338.ce6ba00d.chunk.js",
5 | "static/js/345.c55149fb.chunk.js": "/static/js/345.c55149fb.chunk.js",
6 | "static/js/376.81977eb6.chunk.js": "/static/js/376.81977eb6.chunk.js",
7 | "static/js/472.f35afe9a.chunk.js": "/static/js/472.f35afe9a.chunk.js",
8 | "static/js/207.53e720df.chunk.js": "/static/js/207.53e720df.chunk.js",
9 | "static/js/678.8a7704c8.chunk.js": "/static/js/678.8a7704c8.chunk.js",
10 | "static/js/787.35cea4b2.chunk.js": "/static/js/787.35cea4b2.chunk.js",
11 | "static/js/339.44b407fa.chunk.js": "/static/js/339.44b407fa.chunk.js",
12 | "static/js/147.bb72a7f4.chunk.js": "/static/js/147.bb72a7f4.chunk.js",
13 | "static/js/572.087c84b7.chunk.js": "/static/js/572.087c84b7.chunk.js",
14 | "static/js/631.8197571d.chunk.js": "/static/js/631.8197571d.chunk.js",
15 | "static/media/logo.ico": "/static/media/logo.45af386bcce066c1c6ab.ico",
16 | "index.html": "/index.html",
17 | "main.1ae3cbd8.js.map": "/static/js/main.1ae3cbd8.js.map",
18 | "338.ce6ba00d.chunk.js.map": "/static/js/338.ce6ba00d.chunk.js.map",
19 | "345.c55149fb.chunk.js.map": "/static/js/345.c55149fb.chunk.js.map",
20 | "376.81977eb6.chunk.js.map": "/static/js/376.81977eb6.chunk.js.map",
21 | "472.f35afe9a.chunk.js.map": "/static/js/472.f35afe9a.chunk.js.map",
22 | "207.53e720df.chunk.js.map": "/static/js/207.53e720df.chunk.js.map",
23 | "678.8a7704c8.chunk.js.map": "/static/js/678.8a7704c8.chunk.js.map",
24 | "787.35cea4b2.chunk.js.map": "/static/js/787.35cea4b2.chunk.js.map",
25 | "339.44b407fa.chunk.js.map": "/static/js/339.44b407fa.chunk.js.map",
26 | "147.bb72a7f4.chunk.js.map": "/static/js/147.bb72a7f4.chunk.js.map",
27 | "572.087c84b7.chunk.js.map": "/static/js/572.087c84b7.chunk.js.map",
28 | "631.8197571d.chunk.js.map": "/static/js/631.8197571d.chunk.js.map"
29 | },
30 | "entrypoints": [
31 | "static/js/main.1ae3cbd8.js"
32 | ]
33 | }
--------------------------------------------------------------------------------
/build/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app-latest/fc6bc01d83da7ab566c5699425b8129e5b33077e/build/favicon.ico
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 |
Chat App
--------------------------------------------------------------------------------
/build/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app-latest/fc6bc01d83da7ab566c5699425b8129e5b33077e/build/logo192.png
--------------------------------------------------------------------------------
/build/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app-latest/fc6bc01d83da7ab566c5699425b8129e5b33077e/build/logo512.png
--------------------------------------------------------------------------------
/build/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/build/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/build/static/js/147.bb72a7f4.chunk.js.LICENSE.txt:
--------------------------------------------------------------------------------
1 | /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
2 |
--------------------------------------------------------------------------------
/build/static/js/207.53e720df.chunk.js:
--------------------------------------------------------------------------------
1 | "use strict";(self.webpackChunkchat=self.webpackChunkchat||[]).push([[207],{5207:function(e,n,t){t.r(n);t(2791);var c=t(184);n.default=function(){return(0,c.jsx)(c.Fragment,{children:"404"})}}}]);
2 | //# sourceMappingURL=207.53e720df.chunk.js.map
--------------------------------------------------------------------------------
/build/static/js/207.53e720df.chunk.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"static/js/207.53e720df.chunk.js","mappings":"6HAOA,UALgB,WACd,OAAO,qCACR,C","sources":["pages/Page404.js"],"sourcesContent":["import React from \"react\";\n\nconst Page404 = () => {\n return <>404>;\n};\n\n\nexport default Page404;"],"names":[],"sourceRoot":""}
--------------------------------------------------------------------------------
/build/static/js/678.8a7704c8.chunk.js:
--------------------------------------------------------------------------------
1 | "use strict";(self.webpackChunkchat=self.webpackChunkchat||[]).push([[678],{9678:function(a,c,e){e.r(c);var t=e(7631);c.default=t.g}}]);
2 | //# sourceMappingURL=678.8a7704c8.chunk.js.map
--------------------------------------------------------------------------------
/build/static/js/678.8a7704c8.chunk.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"static/js/678.8a7704c8.chunk.js","mappings":"sHAEA,UAAeA,EAAf,C","sources":["components/animate/features.js"],"sourcesContent":["import { domMax } from 'framer-motion';\n\nexport default domMax;\n"],"names":["domMax"],"sourceRoot":""}
--------------------------------------------------------------------------------
/build/static/media/logo.45af386bcce066c1c6ab.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app-latest/fc6bc01d83da7ab566c5699425b8129e5b33077e/build/static/media/logo.45af386bcce066c1c6ab.ico
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chat",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@dhaiwat10/react-link-preview": "^1.15.0",
7 | "@emoji-mart/data": "^1.0.6",
8 | "@emoji-mart/react": "^1.0.1",
9 | "@emotion/react": "^11.10.4",
10 | "@emotion/styled": "^11.10.4",
11 | "@hookform/resolvers": "^2.9.10",
12 | "@iconify/react": "^4.0.0",
13 | "@mui/lab": "^5.0.0-alpha.113",
14 | "@mui/material": "^5.11.1",
15 | "@reduxjs/toolkit": "^1.9.0",
16 | "@testing-library/jest-dom": "^5.16.5",
17 | "@testing-library/react": "^13.4.0",
18 | "@testing-library/user-event": "^13.5.0",
19 | "aws-sdk": "^2.1348.0",
20 | "axios": "^1.2.6",
21 | "emoji-mart": "^5.2.2",
22 | "framer-motion": "^7.5.3",
23 | "phosphor-react": "^1.4.1",
24 | "prop-types": "^15.8.1",
25 | "react": "^18.2.0",
26 | "react-dom": "^18.2.0",
27 | "react-dropzone": "^14.2.3",
28 | "react-embed": "^3.6.0",
29 | "react-helmet-async": "^1.3.0",
30 | "react-hook-form": "^7.41.0",
31 | "react-i18next": "^11.18.6",
32 | "react-lazy-load-image-component": "^1.5.6",
33 | "react-redux": "^8.0.5",
34 | "react-router-dom": "^6.4.2",
35 | "react-scripts": "5.0.1",
36 | "redux": "^4.2.0",
37 | "redux-persist": "^6.0.0",
38 | "simplebar-react": "^2.4.3",
39 | "socket.io-client": "^4.6.0",
40 | "stylis-plugin-rtl": "^2.0.2",
41 | "uuidv4": "^6.2.13",
42 | "web-vitals": "^2.1.4",
43 | "yup": "^0.32.11",
44 | "zego-express-engine-webrtc": "^2.23.0"
45 | },
46 | "scripts": {
47 | "start": "react-scripts start",
48 | "build": "react-scripts build",
49 | "test": "react-scripts test",
50 | "eject": "react-scripts eject"
51 | },
52 | "eslintConfig": {
53 | "extends": [
54 | "react-app",
55 | "react-app/jest"
56 | ]
57 | },
58 | "browserslist": {
59 | "production": [
60 | ">0.2%",
61 | "not dead",
62 | "not op_mini all"
63 | ],
64 | "development": [
65 | "last 1 chrome version",
66 | "last 1 firefox version",
67 | "last 1 safari version"
68 | ]
69 | },
70 | "devDependencies": {
71 | "@faker-js/faker": "^7.5.0"
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app-latest/fc6bc01d83da7ab566c5699425b8129e5b33077e/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
19 |
20 |
24 |
33 | Chat App
34 |
35 |
36 |
37 |
38 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app-latest/fc6bc01d83da7ab566c5699425b8129e5b33077e/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app-latest/fc6bc01d83da7ab566c5699425b8129e5b33077e/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | // routes
2 | // theme
3 | // components
4 | import React, { useEffect } from "react";
5 | import { useDispatch, useSelector } from "react-redux";
6 | import Snackbar from "@mui/material/Snackbar";
7 | import MuiAlert from "@mui/material/Alert";
8 | import ThemeSettings from "./components/settings";
9 | import ThemeProvider from "./theme";
10 | import Router from "./routes";
11 | import { closeSnackBar } from "./redux/slices/app";
12 | import { socket } from "./socket";
13 |
14 | const vertical = "bottom";
15 | const horizontal = "center";
16 |
17 | const Alert = React.forwardRef((props, ref) => (
18 |
19 | ));
20 |
21 | function App() {
22 | const dispatch = useDispatch();
23 |
24 | const { severity, message, open } = useSelector(
25 | (state) => state.app.snackbar
26 | );
27 |
28 | return (
29 | <>
30 |
31 |
32 | {" "}
33 | {" "}
34 |
35 |
36 |
37 | {message && open ? (
38 | {
44 | console.log("This is clicked");
45 | dispatch(closeSnackBar());
46 | }}
47 | >
48 | {
50 | console.log("This is clicked");
51 | dispatch(closeSnackBar());
52 | }}
53 | severity={severity}
54 | sx={{ width: "100%" }}
55 | >
56 | {message}
57 |
58 |
59 | ) : (
60 | <>>
61 | )}
62 | >
63 | );
64 | }
65 |
66 | export default App;
67 |
--------------------------------------------------------------------------------
/src/assets/Images/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingmonk-yt/chat-app-latest/fc6bc01d83da7ab566c5699425b8129e5b33077e/src/assets/Images/logo.ico
--------------------------------------------------------------------------------
/src/components/AntSwitch.js:
--------------------------------------------------------------------------------
1 | import { Switch } from "@mui/material";
2 | import { styled } from "@mui/material/styles";
3 |
4 | const AntSwitch = styled(Switch)(({ theme }) => ({
5 | width: 40,
6 | height: 20,
7 | padding: 0,
8 | display: "flex",
9 | "&:active": {
10 | "& .MuiSwitch-thumb": {
11 | width: 15,
12 | },
13 | "& .MuiSwitch-switchBase.Mui-checked": {
14 | transform: "translateX(9px)",
15 | },
16 | },
17 | "& .MuiSwitch-switchBase": {
18 | padding: 2,
19 | "&.Mui-checked": {
20 | transform: "translateX(20px)",
21 | color: "#fff",
22 | "& + .MuiSwitch-track": {
23 | opacity: 1,
24 | backgroundColor: theme.palette.primary.main,
25 | },
26 | },
27 | },
28 | "& .MuiSwitch-thumb": {
29 | boxShadow: "0 2px 4px 0 rgb(0 35 11 / 20%)",
30 | width: 16,
31 | height: 16,
32 | borderRadius: 8,
33 | transition: theme.transitions.create(["width"], {
34 | duration: 200,
35 | }),
36 | },
37 | "& .MuiSwitch-track": {
38 | borderRadius: 20 / 2,
39 | opacity: 1,
40 | backgroundColor:
41 | theme.palette.mode === "dark"
42 | ? "rgba(255,255,255,.35)"
43 | : "rgba(0,0,0,.25)",
44 | boxSizing: "border-box",
45 | },
46 | }));
47 |
48 | export default AntSwitch;
49 |
--------------------------------------------------------------------------------
/src/components/Chat/index.js:
--------------------------------------------------------------------------------
1 | export {default as ChatHeader} from "./Header";
2 | export {default as ChatFooter} from "./Footer";
--------------------------------------------------------------------------------
/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/Image/Image.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { forwardRef } from 'react';
3 | import { LazyLoadImage } from 'react-lazy-load-image-component';
4 | // @mui
5 | import { Box } from '@mui/material';
6 |
7 | // ----------------------------------------------------------------------
8 |
9 | const Image = forwardRef(
10 | ({ disabledEffect = false, effect = 'blur', sx, ...other }, ref) => {
11 | const content = (
12 |
20 | );
21 |
22 | return (
23 |
39 | {content}
40 |
41 | );
42 | }
43 | );
44 |
45 | Image.propTypes = {
46 | sx: PropTypes.object,
47 | effect: PropTypes.string,
48 | disabledEffect: PropTypes.bool,
49 | };
50 |
51 | export default Image;
52 |
--------------------------------------------------------------------------------
/src/components/Image/getRatio.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function getRatio(ratio = '1/1') {
4 | return {
5 | '4/3': 'calc(100% / 4 * 3)',
6 | '3/4': 'calc(100% / 3 * 4)',
7 | '6/4': 'calc(100% / 6 * 4)',
8 | '4/6': 'calc(100% / 4 * 6)',
9 | '16/9': 'calc(100% / 16 * 9)',
10 | '9/16': 'calc(100% / 9 * 16)',
11 | '21/9': 'calc(100% / 21 * 9)',
12 | '9/21': 'calc(100% / 9 * 21)',
13 | '1/1': '100%',
14 | }[ratio];
15 | }
16 |
--------------------------------------------------------------------------------
/src/components/Image/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Image';
2 |
--------------------------------------------------------------------------------
/src/components/LoadingScreen.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const LoadingScreen = () => {
4 | return <>Loading...>;
5 | };
6 |
7 | export default LoadingScreen;
8 |
--------------------------------------------------------------------------------
/src/components/Scrollbar.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import SimpleBarReact from 'simplebar-react';
3 | // @mui
4 | import { alpha, styled } from '@mui/material/styles';
5 | import { Box } from '@mui/material';
6 |
7 | // ----------------------------------------------------------------------
8 |
9 | const RootStyle = styled('div')(() => ({
10 | flexGrow: 1,
11 | height: '100%',
12 | overflow: 'scroll',
13 | }));
14 |
15 | const SimpleBarStyle = styled(SimpleBarReact)(({ theme }) => ({
16 | // maxHeight: '100%',
17 | '& .simplebar-scrollbar': {
18 | '&:before': {
19 | backgroundColor: alpha(theme.palette.grey[600], 0.48),
20 | },
21 | '&.simplebar-visible:before': {
22 | opacity: 1,
23 | },
24 | },
25 | '& .simplebar-track.simplebar-vertical': {
26 | width: 10,
27 | },
28 | '& .simplebar-track.simplebar-horizontal .simplebar-scrollbar': {
29 | height: 6,
30 | },
31 | '& .simplebar-mask': {
32 | zIndex: 'inherit',
33 | },
34 | "& .simplebar-placeholder": {
35 | height: '0 !important',
36 | }
37 | }));
38 |
39 | // ----------------------------------------------------------------------
40 |
41 | Scrollbar.propTypes = {
42 | children: PropTypes.node.isRequired,
43 | sx: PropTypes.object,
44 | };
45 |
46 | export default function Scrollbar({ children, sx, ...other }) {
47 | const userAgent = typeof navigator === 'undefined' ? 'SSR' : navigator.userAgent;
48 |
49 | const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
50 |
51 | if (isMobile) {
52 | return (
53 |
54 | {children}
55 |
56 | );
57 | }
58 |
59 | return (
60 |
61 |
62 | {children}
63 |
64 |
65 | );
66 | }
67 |
68 | export {SimpleBarStyle};
69 |
--------------------------------------------------------------------------------
/src/components/Search/Search.js:
--------------------------------------------------------------------------------
1 | import { styled, alpha } from "@mui/material/styles";
2 |
3 | const Search = styled("div")(({ theme }) => ({
4 | position: "relative",
5 | borderRadius: 20,
6 | backgroundColor: alpha(theme.palette.background.paper, 1),
7 | marginRight: theme.spacing(2),
8 | marginLeft: 0,
9 | width: "100%",
10 | }));
11 |
12 | export default Search;
13 |
--------------------------------------------------------------------------------
/src/components/Search/SearchIconWrapper.js:
--------------------------------------------------------------------------------
1 | import { styled } from "@mui/material/styles";
2 |
3 | const SearchIconWrapper = styled("div")(({ theme }) => ({
4 | padding: theme.spacing(0, 2),
5 | height: "100%",
6 | position: "absolute",
7 | pointerEvents: "none",
8 | display: "flex",
9 | alignItems: "center",
10 | justifyContent: "center",
11 | }));
12 |
13 | export default SearchIconWrapper;
14 |
--------------------------------------------------------------------------------
/src/components/Search/StyledInputBase.js:
--------------------------------------------------------------------------------
1 | import { InputBase } from "@mui/material";
2 | import {styled} from "@mui/material/styles";
3 |
4 |
5 | const StyledInputBase = styled(InputBase)(({ theme }) => ({
6 | color: "inherit",
7 | "& .MuiInputBase-input": {
8 | padding: theme.spacing(1, 1, 1, 0),
9 | // vertical padding + font size from searchIcon
10 | paddingLeft: `calc(1em + ${theme.spacing(4)})`,
11 | width: "100%",
12 | },
13 | }));
14 |
15 | export default StyledInputBase;
--------------------------------------------------------------------------------
/src/components/Search/index.js:
--------------------------------------------------------------------------------
1 | export { default as Search } from "./Search";
2 | export { default as SearchIconWrapper } from "./SearchIconWrapper";
3 | export { default as StyledInputBase } from "./StyledInputBase";
4 |
--------------------------------------------------------------------------------
/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 |
55 | )}
56 |
57 | );
58 | }
59 |
--------------------------------------------------------------------------------
/src/components/animate/FabButtonAnimate.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { m } from 'framer-motion';
3 | import { forwardRef } from 'react';
4 | // @mui
5 | import { useTheme } from '@mui/material/styles';
6 | import { Box, Fab } from '@mui/material';
7 |
8 | // ----------------------------------------------------------------------
9 |
10 | const FabButtonAnimate = forwardRef(({ color = 'primary', size = 'large', children, sx, sxWrap, ...other }, ref) => {
11 | const theme = useTheme();
12 |
13 | if (color === 'default' || color === 'inherit' || color === 'primary' || color === 'secondary') {
14 | return (
15 |
16 |
17 | {children}
18 |
19 |
20 | );
21 | }
22 |
23 | return (
24 |
25 |
39 | {children}
40 |
41 |
42 | );
43 | });
44 |
45 | FabButtonAnimate.propTypes = {
46 | children: PropTypes.node.isRequired,
47 | color: PropTypes.oneOf(['inherit', 'default', 'primary', 'secondary', 'info', 'success', 'warning', 'error']),
48 | size: PropTypes.oneOf(['small', 'medium', 'large']),
49 | sx: PropTypes.object,
50 | sxWrap: PropTypes.object
51 | };
52 |
53 | export default FabButtonAnimate;
54 |
55 | // ----------------------------------------------------------------------
56 |
57 | const varSmall = {
58 | hover: { scale: 1.07 },
59 | tap: { scale: 0.97 }
60 | };
61 |
62 | const varMedium = {
63 | hover: { scale: 1.06 },
64 | tap: { scale: 0.98 }
65 | };
66 |
67 | const varLarge = {
68 | hover: { scale: 1.05 },
69 | tap: { scale: 0.99 }
70 | };
71 |
72 | AnimateWrap.propTypes = {
73 | children: PropTypes.node.isRequired,
74 | size: PropTypes.oneOf(['small', 'medium', 'large']),
75 | sxWrap: PropTypes.object
76 | };
77 |
78 | function AnimateWrap({ size, children, sxWrap }) {
79 | const isSmall = size === 'small';
80 | const isLarge = size === 'large';
81 |
82 | return (
83 |
93 | {children}
94 |
95 | );
96 | }
97 |
--------------------------------------------------------------------------------
/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 = false, ...other }) {
18 | const isMobile = useResponsive('down', 'sm');
19 |
20 | if (isMobile && 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/background.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export const varBgColor = (props) => {
4 | const colors = props?.colors || ['#19dcea', '#b22cff'];
5 | const duration = props?.duration || 5;
6 | const ease = props?.ease || 'linear';
7 |
8 | return {
9 | animate: {
10 | background: colors,
11 | transition: { duration, ease }
12 | }
13 | };
14 | };
15 |
16 | // ----------------------------------------------------------------------
17 |
18 | export const varBgKenburns = (props) => {
19 | const duration = props?.duration || 5;
20 | const ease = props?.ease || 'easeOut';
21 |
22 | return {
23 | top: {
24 | animate: {
25 | scale: [1, 1.25],
26 | y: [0, -15],
27 | transformOrigin: ['50% 16%', 'top'],
28 | transition: { duration, ease }
29 | }
30 | },
31 | right: {
32 | animate: {
33 | scale: [1, 1.25],
34 | x: [0, 20],
35 | y: [0, -15],
36 | transformOrigin: ['84% 50%', 'right'],
37 | transition: { duration, ease }
38 | }
39 | },
40 | bottom: {
41 | animate: {
42 | scale: [1, 1.25],
43 | y: [0, 15],
44 | transformOrigin: ['50% 84%', 'bottom'],
45 | transition: { duration, ease }
46 | }
47 | },
48 | left: {
49 | animate: {
50 | scale: [1, 1.25],
51 | x: [0, -20],
52 | y: [0, 15],
53 | transformOrigin: ['16% 50%', 'left'],
54 | transition: { duration, ease }
55 | }
56 | }
57 | };
58 | };
59 |
60 | // ----------------------------------------------------------------------
61 |
62 | export const varBgPan = (props) => {
63 | const colors = props?.colors || ['#ee7752', '#e73c7e', '#23a6d5', '#23d5ab'];
64 | const duration = props?.duration || 5;
65 | const ease = props?.ease || 'linear';
66 |
67 | const gradient = (deg) => `linear-gradient(${deg}deg, ${colors})`;
68 |
69 | return {
70 | top: {
71 | animate: {
72 | backgroundImage: [gradient(0), gradient(0)],
73 | backgroundPosition: ['center 99%', 'center 1%'],
74 | backgroundSize: ['100% 600%', '100% 600%'],
75 | transition: { duration, ease }
76 | }
77 | },
78 | right: {
79 | animate: {
80 | backgroundPosition: ['1% center', '99% center'],
81 | backgroundImage: [gradient(270), gradient(270)],
82 | backgroundSize: ['600% 100%', '600% 100%'],
83 | transition: { duration, ease }
84 | }
85 | },
86 | bottom: {
87 | animate: {
88 | backgroundImage: [gradient(0), gradient(0)],
89 | backgroundPosition: ['center 1%', 'center 99%'],
90 | backgroundSize: ['100% 600%', '100% 600%'],
91 | transition: { duration, ease }
92 | }
93 | },
94 | left: {
95 | animate: {
96 | backgroundPosition: ['99% center', '1% center'],
97 | backgroundImage: [gradient(270), gradient(270)],
98 | backgroundSize: ['600% 100%', '600% 100%'],
99 | transition: { duration, ease }
100 | }
101 | }
102 | };
103 | };
104 |
--------------------------------------------------------------------------------
/src/components/animate/variants/bounce.js:
--------------------------------------------------------------------------------
1 | import { varTranEnter, varTranExit } from './transition';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export const varBounce = (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 | in: {
14 | initial: {},
15 | animate: {
16 | scale: [0.3, 1.1, 0.9, 1.03, 0.97, 1],
17 | opacity: [0, 1, 1, 1, 1, 1],
18 | transition: varTranEnter({ durationIn, easeIn }),
19 | },
20 | exit: {
21 | scale: [0.9, 1.1, 0.3],
22 | opacity: [1, 1, 0],
23 | },
24 | },
25 | inUp: {
26 | initial: {},
27 | animate: {
28 | y: [720, -24, 12, -4, 0],
29 | scaleY: [4, 0.9, 0.95, 0.985, 1],
30 | opacity: [0, 1, 1, 1, 1],
31 | transition: { ...varTranEnter({ durationIn, easeIn }) },
32 | },
33 | exit: {
34 | y: [12, -24, 720],
35 | scaleY: [0.985, 0.9, 3],
36 | opacity: [1, 1, 0],
37 | transition: varTranExit({ durationOut, easeOut }),
38 | },
39 | },
40 | inDown: {
41 | initial: {},
42 | animate: {
43 | y: [-720, 24, -12, 4, 0],
44 | scaleY: [4, 0.9, 0.95, 0.985, 1],
45 | opacity: [0, 1, 1, 1, 1],
46 | transition: varTranEnter({ durationIn, easeIn }),
47 | },
48 | exit: {
49 | y: [-12, 24, -720],
50 | scaleY: [0.985, 0.9, 3],
51 | opacity: [1, 1, 0],
52 | transition: varTranExit({ durationOut, easeOut }),
53 | },
54 | },
55 | inLeft: {
56 | initial: {},
57 | animate: {
58 | x: [-720, 24, -12, 4, 0],
59 | scaleX: [3, 1, 0.98, 0.995, 1],
60 | opacity: [0, 1, 1, 1, 1],
61 | transition: varTranEnter({ durationIn, easeIn }),
62 | },
63 | exit: {
64 | x: [0, 24, -720],
65 | scaleX: [1, 0.9, 2],
66 | opacity: [1, 1, 0],
67 | transition: varTranExit({ durationOut, easeOut }),
68 | },
69 | },
70 | inRight: {
71 | initial: {},
72 | animate: {
73 | x: [720, -24, 12, -4, 0],
74 | scaleX: [3, 1, 0.98, 0.995, 1],
75 | opacity: [0, 1, 1, 1, 1],
76 | transition: varTranEnter({ durationIn, easeIn }),
77 | },
78 | exit: {
79 | x: [0, -24, 720],
80 | scaleX: [1, 0.9, 2],
81 | opacity: [1, 1, 0],
82 | transition: varTranExit({ durationOut, easeOut }),
83 | },
84 | },
85 |
86 | // OUT
87 | out: {
88 | animate: { scale: [0.9, 1.1, 0.3], opacity: [1, 1, 0] },
89 | },
90 | outUp: {
91 | animate: { y: [-12, 24, -720], scaleY: [0.985, 0.9, 3], opacity: [1, 1, 0] },
92 | },
93 | outDown: {
94 | animate: { y: [12, -24, 720], scaleY: [0.985, 0.9, 3], opacity: [1, 1, 0] },
95 | },
96 | outLeft: {
97 | animate: { x: [0, 24, -720], scaleX: [1, 0.9, 2], opacity: [1, 1, 0] },
98 | },
99 | outRight: {
100 | animate: { x: [0, -24, 720], scaleX: [1, 0.9, 2], opacity: [1, 1, 0] },
101 | },
102 | };
103 | };
104 |
--------------------------------------------------------------------------------
/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/fade.js:
--------------------------------------------------------------------------------
1 | import { varTranEnter, varTranExit } from './transition';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export const varFade = (props) => {
6 | const distance = props?.distance || 120;
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 },
16 | animate: { opacity: 1, transition: varTranEnter },
17 | exit: { opacity: 0, transition: varTranExit }
18 | },
19 | inUp: {
20 | initial: { y: distance, opacity: 0 },
21 | animate: { y: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
22 | exit: { y: distance, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
23 | },
24 | inDown: {
25 | initial: { y: -distance, opacity: 0 },
26 | animate: { y: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
27 | exit: { y: -distance, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
28 | },
29 | inLeft: {
30 | initial: { x: -distance, opacity: 0 },
31 | animate: { x: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
32 | exit: { x: -distance, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
33 | },
34 | inRight: {
35 | initial: { x: distance, opacity: 0 },
36 | animate: { x: 0, opacity: 1, transition: varTranEnter({ durationIn, easeIn }) },
37 | exit: { x: distance, opacity: 0, transition: varTranExit({ durationOut, easeOut }) }
38 | },
39 |
40 | // OUT
41 | out: {
42 | initial: { opacity: 1 },
43 | animate: { opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
44 | exit: { opacity: 1, transition: varTranExit({ durationOut, easeOut }) }
45 | },
46 | outUp: {
47 | initial: { y: 0, opacity: 1 },
48 | animate: { y: -distance, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
49 | exit: { y: 0, opacity: 1, transition: varTranExit({ durationOut, easeOut }) }
50 | },
51 | outDown: {
52 | initial: { y: 0, opacity: 1 },
53 | animate: { y: distance, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
54 | exit: { y: 0, opacity: 1, transition: varTranExit({ durationOut, easeOut }) }
55 | },
56 | outLeft: {
57 | initial: { x: 0, opacity: 1 },
58 | animate: { x: -distance, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
59 | exit: { x: 0, opacity: 1, transition: varTranExit({ durationOut, easeOut }) }
60 | },
61 | outRight: {
62 | initial: { x: 0, opacity: 1 },
63 | animate: { x: distance, opacity: 0, transition: varTranEnter({ durationIn, easeIn }) },
64 | exit: { x: 0, opacity: 1, transition: varTranExit({ durationOut, easeOut }) }
65 | }
66 | };
67 | };
68 |
--------------------------------------------------------------------------------
/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/slide.js:
--------------------------------------------------------------------------------
1 | //
2 | import { varTranEnter, varTranExit } from './transition';
3 |
4 | // ----------------------------------------------------------------------
5 |
6 | export const varSlide = (props) => {
7 | const distance = props?.distance || 160;
8 | const durationIn = props?.durationIn;
9 | const durationOut = props?.durationOut;
10 | const easeIn = props?.easeIn;
11 | const easeOut = props?.easeOut;
12 |
13 | return {
14 | // IN
15 | inUp: {
16 | initial: { y: distance },
17 | animate: { y: 0, transition: varTranEnter({ durationIn, easeIn }) },
18 | exit: { y: distance, transition: varTranExit({ durationOut, easeOut }) }
19 | },
20 | inDown: {
21 | initial: { y: -distance },
22 | animate: { y: 0, transition: varTranEnter({ durationIn, easeIn }) },
23 | exit: { y: -distance, transition: varTranExit({ durationOut, easeOut }) }
24 | },
25 | inLeft: {
26 | initial: { x: -distance },
27 | animate: { x: 0, transition: varTranEnter({ durationIn, easeIn }) },
28 | exit: { x: -distance, transition: varTranExit({ durationOut, easeOut }) }
29 | },
30 | inRight: {
31 | initial: { x: distance },
32 | animate: { x: 0, transition: varTranEnter({ durationIn, easeIn }) },
33 | exit: { x: distance, transition: varTranExit({ durationOut, easeOut }) }
34 | },
35 |
36 | // OUT
37 | outUp: {
38 | initial: { y: 0 },
39 | animate: { y: -distance, transition: varTranEnter({ durationIn, easeIn }) },
40 | exit: { y: 0, transition: varTranExit({ durationOut, easeOut }) }
41 | },
42 | outDown: {
43 | initial: { y: 0 },
44 | animate: { y: distance, transition: varTranEnter({ durationIn, easeIn }) },
45 | exit: { y: 0, transition: varTranExit({ durationOut, easeOut }) }
46 | },
47 | outLeft: {
48 | initial: { x: 0 },
49 | animate: { x: -distance, transition: varTranEnter({ durationIn, easeIn }) },
50 | exit: { x: 0, transition: varTranExit({ durationOut, easeOut }) }
51 | },
52 | outRight: {
53 | initial: { x: 0 },
54 | animate: { x: distance, transition: varTranEnter({ durationIn, easeIn }) },
55 | exit: { x: 0, transition: varTranExit({ durationOut, easeOut }) }
56 | }
57 | };
58 | };
59 |
--------------------------------------------------------------------------------
/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/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,
9 | methods: PropTypes.object,
10 | onSubmit: PropTypes.func,
11 | };
12 |
13 | export default function FormProvider({ children, onSubmit, methods }) {
14 | return (
15 |
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/hook-form/RHFAutocomplete.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | // form
3 | import { useFormContext, Controller } from 'react-hook-form';
4 | // @mui
5 | import { Autocomplete, TextField } from '@mui/material';
6 |
7 | // ----------------------------------------------------------------------
8 |
9 | RHFAutocomplete.propTypes = {
10 | name: PropTypes.string,
11 | label: PropTypes.string,
12 | helperText: PropTypes.node,
13 | };
14 |
15 | export default function RHFAutocomplete({ name, label, helperText, ...other }) {
16 | const { control, setValue } = useFormContext();
17 |
18 | return (
19 | (
23 | setValue(name, newValue, { shouldValidate: true })}
26 | renderInput={(params) => (
27 |
33 | )}
34 | {...other}
35 | />
36 | )}
37 | />
38 | );
39 | }
40 |
--------------------------------------------------------------------------------
/src/components/hook-form/RHFCodes.js:
--------------------------------------------------------------------------------
1 |
2 | import { useRef } from "react";
3 | // form
4 | import { useFormContext, Controller } from "react-hook-form";
5 | // @mui
6 | import { Stack, TextField } from "@mui/material";
7 |
8 |
9 | export default function RHFCodes({ keyName = "", inputs = [], ...other }) {
10 | const codesRef = useRef(null);
11 |
12 | const { control } = useFormContext();
13 |
14 | const handleChangeWithNextField = (event, handleChange) => {
15 | const { maxLength, value, name } = event.target;
16 |
17 | const fieldIndex = name.replace(keyName, "");
18 |
19 | const fieldIntIndex = Number(fieldIndex);
20 |
21 | const nextfield = document.querySelector(
22 | `input[name=${keyName}${fieldIntIndex + 1}]`
23 | );
24 |
25 | if (value.length > maxLength) {
26 | event.target.value = value[0];
27 | }
28 |
29 | if (value.length >= maxLength && fieldIntIndex < 6 && nextfield !== null) {
30 | nextfield.focus();
31 | }
32 |
33 | handleChange(event);
34 | };
35 |
36 | return (
37 |
38 | {inputs.map((name, index) => (
39 | (
44 | {
50 | handleChangeWithNextField(event, field.onChange);
51 | }}
52 | onFocus={(event) => event.currentTarget.select()}
53 | InputProps={{
54 | sx: {
55 | width: { xs: 36, sm: 56 },
56 | height: { xs: 36, sm: 56 },
57 | "& input": { p: 0, textAlign: "center" },
58 | },
59 | }}
60 | inputProps={{
61 | maxLength: 1,
62 | type: "number",
63 | }}
64 | {...other}
65 | />
66 | )}
67 | />
68 | ))}
69 |
70 | );
71 | }
72 |
--------------------------------------------------------------------------------
/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 | helperText: PropTypes.node,
12 | };
13 |
14 | export default function RHFTextField({ name, helperText, ...other }) {
15 | const { control } = useFormContext();
16 |
17 | return (
18 | (
22 |
31 | )}
32 | />
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/src/components/hook-form/RHFUpload.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 { UploadAvatar } from '../upload';
8 |
9 | // ----------------------------------------------------------------------
10 |
11 | RHFUploadAvatar.propTypes = {
12 | name: PropTypes.string,
13 | };
14 |
15 | // ----------------------------------------------------------------------
16 |
17 | export function RHFUploadAvatar({ name, ...other }) {
18 | const { control } = useFormContext();
19 |
20 | return (
21 | (
25 |
26 |
34 |
35 | {!!error && (
36 |
37 | {error.message}
38 |
39 | )}
40 |
41 | )}
42 | />
43 | );
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/src/components/hook-form/index.js:
--------------------------------------------------------------------------------
1 | export * from './RHFUpload';
2 | export { default } from './FormProvider';
3 |
4 |
5 | export { default as RHFTextField } from './RHFTextField';
6 |
--------------------------------------------------------------------------------
/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/ThemeContrast.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import { useMemo } from 'react';
3 | // @mui
4 | import { CssBaseline } from '@mui/material';
5 | import { alpha, ThemeProvider, createTheme, useTheme } from '@mui/material/styles';
6 | // hooks
7 | import useSettings from '../../hooks/useSettings';
8 | //
9 | import componentsOverride from '../../theme/overrides';
10 |
11 | // ----------------------------------------------------------------------
12 |
13 | ThemeContrast.propTypes = {
14 | children: PropTypes.node,
15 | };
16 |
17 | export default function ThemeContrast({ children }) {
18 | const defaultTheme = useTheme();
19 |
20 | const { themeContrast } = useSettings();
21 |
22 | const isLight = defaultTheme.palette.mode === 'light';
23 |
24 | const shadowColor = isLight ? defaultTheme.palette.grey[500] : defaultTheme.palette.common.black;
25 |
26 | const styles = {
27 | bgDefault: defaultTheme.palette.background.default,
28 | bgBold: isLight ? defaultTheme.palette.grey[100] : defaultTheme.palette.grey[900],
29 | cardDefault: defaultTheme.components?.MuiCard?.styleOverrides?.root,
30 | cardBold: {
31 | zIndex: 0,
32 | position: 'relative',
33 | borderRadius: Number(defaultTheme.shape.borderRadius) * 2,
34 | boxShadow: `0 0 1px 0 ${alpha(shadowColor, 0.48)}, 0 2px 4px -1px ${alpha(shadowColor, 0.24)}`,
35 | },
36 | };
37 |
38 | const themeOptions = useMemo(
39 | () => ({
40 | ...defaultTheme,
41 | palette: {
42 | ...defaultTheme.palette,
43 | background: {
44 | ...defaultTheme.palette.background,
45 | default: themeContrast === 'bold' ? styles.bgBold : styles.bgDefault,
46 | },
47 | },
48 | components: {
49 | MuiCard: {
50 | styleOverrides: {
51 | root: themeContrast === 'bold' ? styles.cardBold : styles.cardDefault,
52 | },
53 | },
54 | },
55 | }),
56 |
57 | [defaultTheme, themeContrast, styles.bgBold, styles.bgDefault, styles.cardBold, styles.cardDefault]
58 | );
59 |
60 | const theme = createTheme(themeOptions);
61 |
62 | theme.components = {
63 | ...componentsOverride(theme),
64 | MuiCard: themeOptions.components?.MuiCard,
65 | };
66 |
67 | return (
68 |
69 |
70 | {children}
71 |
72 | );
73 | }
74 |
--------------------------------------------------------------------------------
/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/SettingColorPresets.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { alpha, styled } from '@mui/material/styles';
3 | import { Box, Grid, RadioGroup, CardActionArea } from '@mui/material';
4 | // hooks
5 | import useSettings from '../../../hooks/useSettings';
6 | //
7 | import BoxMask from './BoxMask';
8 |
9 | // ----------------------------------------------------------------------
10 |
11 | const BoxStyle = styled(CardActionArea)(({ theme }) => ({
12 | height: 48,
13 | display: 'flex',
14 | alignItems: 'center',
15 | justifyContent: 'center',
16 | color: theme.palette.text.disabled,
17 | border: `solid 1px ${theme.palette.grey[500_12]}`,
18 | borderRadius: Number(theme.shape.borderRadius) * 1.25,
19 | }));
20 |
21 | // ----------------------------------------------------------------------
22 |
23 | export default function SettingColorPresets() {
24 | const { themeColorPresets, onChangeColor, colorOption } = useSettings();
25 |
26 | return (
27 |
28 |
29 | {colorOption.map((color) => {
30 | const colorName = color.name;
31 | const colorValue = color.value;
32 | const isSelected = themeColorPresets === colorName;
33 |
34 | return (
35 |
36 |
45 |
53 | theme.transitions.create('all', {
54 | easing: theme.transitions.easing.easeInOut,
55 | duration: theme.transitions.duration.shorter,
56 | }),
57 | ...(isSelected && { transform: 'none' }),
58 | }}
59 | />
60 |
61 |
62 |
63 |
64 | );
65 | })}
66 |
67 |
68 | );
69 | }
70 |
--------------------------------------------------------------------------------
/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/SettingDirection.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 SettingDirection() {
25 | const { themeDirection, onChangeDirection } = useSettings();
26 |
27 | return (
28 |
29 |
30 | {['ltr', 'rtl'].map((direction, index) => {
31 | const isSelected = themeDirection === direction;
32 |
33 | return (
34 |
35 | theme.customShadows.z20,
40 | }),
41 | }}
42 | >
43 |
48 |
49 |
50 |
51 | );
52 | })}
53 |
54 |
55 | );
56 | }
57 |
--------------------------------------------------------------------------------
/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 | }
30 | onClick={toggleFullScreen}
31 | sx={{
32 | fontSize: 14,
33 | ...(fullscreen && {
34 | bgcolor: (theme) => alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
35 | }),
36 | }}
37 | >
38 | {fullscreen ? 'Exit Fullscreen' : 'Fullscreen'}
39 |
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/drawer/SettingStretch.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { styled } from '@mui/material/styles';
3 | import { CardActionArea, Stack } from '@mui/material';
4 | // hooks
5 | import useSettings from '../../../hooks/useSettings';
6 | //
7 | import Iconify from '../../Iconify';
8 |
9 | // ----------------------------------------------------------------------
10 |
11 | const BoxStyle = styled(CardActionArea)(({ theme }) => ({
12 | padding: theme.spacing(2),
13 | color: theme.palette.text.disabled,
14 | border: `solid 1px ${theme.palette.grey[500_12]}`,
15 | backgroundColor: theme.palette.background.neutral,
16 | borderRadius: Number(theme.shape.borderRadius) * 1.25,
17 | }));
18 |
19 | // ----------------------------------------------------------------------
20 |
21 | export default function SettingStretch() {
22 | const { themeStretch, onToggleStretch } = useSettings();
23 |
24 | const ICON_SIZE = {
25 | width: themeStretch ? 24 : 18,
26 | height: themeStretch ? 24 : 18,
27 | };
28 |
29 | return (
30 | theme.palette.primary.main,
35 | }),
36 | }}
37 | >
38 | theme.customShadows.z12,
51 | transition: (theme) => theme.transitions.create('width'),
52 | ...(themeStretch && {
53 | width: 1,
54 | color: 'primary.main',
55 | }),
56 | }}
57 | >
58 |
59 |
60 |
61 |
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/src/components/settings/drawer/ToggleButton.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | // @mui
3 | import { alpha, styled } from '@mui/material/styles';
4 | import { Tooltip } from '@mui/material';
5 | // utils
6 | import cssStyles from '../../../utils/cssStyles';
7 | //
8 | import Iconify from '../../Iconify';
9 | import { IconButtonAnimate } from '../../animate';
10 |
11 | // ----------------------------------------------------------------------
12 |
13 | const RootStyle = styled('span')(({ theme }) => ({
14 | ...cssStyles(theme).bgBlur({ opacity: 0.64 }),
15 | right: 0,
16 | top: '50%',
17 | position: 'fixed',
18 | marginTop: theme.spacing(-3),
19 | padding: theme.spacing(0.5),
20 | zIndex: theme.zIndex.drawer + 2,
21 | borderRadius: '24px 0 20px 24px',
22 | boxShadow: `-12px 12px 32px -4px ${alpha(
23 | theme.palette.mode === 'light' ? theme.palette.grey[600] : theme.palette.common.black,
24 | 0.36
25 | )}`,
26 | }));
27 |
28 | const DotStyle = styled('span')(({ theme }) => ({
29 | top: 8,
30 | width: 8,
31 | height: 8,
32 | right: 10,
33 | borderRadius: '50%',
34 | position: 'absolute',
35 | backgroundColor: theme.palette.error.main,
36 | }));
37 |
38 | // ----------------------------------------------------------------------
39 |
40 | ToggleButton.propTypes = {
41 | notDefault: PropTypes.bool,
42 | onToggle: PropTypes.func,
43 | open: PropTypes.bool,
44 | };
45 |
46 | export default function ToggleButton({ notDefault, open, onToggle }) {
47 | return (
48 |
49 | {notDefault && !open && }
50 |
51 |
52 | theme.transitions.create('all'),
58 | '&:hover': {
59 | color: 'primary.main',
60 | bgcolor: (theme) => alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity),
61 | },
62 | }}
63 | >
64 |
65 |
66 |
67 |
68 | );
69 | }
70 |
--------------------------------------------------------------------------------
/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/upload/index.js:
--------------------------------------------------------------------------------
1 | export { default as AvatarPreview } from './preview/AvatarPreview';
2 | export { default as UploadAvatar } from './UploadAvatar';
3 |
--------------------------------------------------------------------------------
/src/components/upload/preview/AvatarPreview.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | //
3 | import Image from '../../Image';
4 |
5 | // ----------------------------------------------------------------------
6 |
7 | AvatarPreview.propTypes = {
8 | file: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
9 | };
10 |
11 | export default function AvatarPreview({ file }) {
12 | if (!file) {
13 | return null;
14 | }
15 |
16 | const imgUrl = typeof file === 'string' ? file : file.preview;
17 |
18 | return (
19 |
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { enUS, frFR, zhCN, viVN, arSD } from '@mui/material/locale';
3 |
4 | // routes
5 | import { PATH_DASHBOARD } from "./routes/paths";
6 |
7 | export const BASE_URL = "https://api.chat.codingmonk.in/";
8 |
9 | export const S3_BUCKET_NAME = 'codingmonk';
10 | export const AWS_ACCESS_KEY = 'AKIARPJQ4HSYLBIK2TDE';
11 | export const AWS_SECRET_ACCESS_KEY = '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';
12 | export const AWS_S3_REGION = 'ap-south-1'; // eg. ap-south-1
13 |
14 | export const defaultSettings = {
15 | themeMode: "light",
16 | themeDirection: "ltr",
17 | themeContrast: "default",
18 | themeLayout: "horizontal",
19 | themeColorPresets: "default",
20 | themeStretch: false,
21 | };
22 |
23 | export const NAVBAR = {
24 | BASE_WIDTH: 260,
25 | DASHBOARD_WIDTH: 280,
26 | DASHBOARD_COLLAPSE_WIDTH: 88,
27 | //
28 | DASHBOARD_ITEM_ROOT_HEIGHT: 48,
29 | DASHBOARD_ITEM_SUB_HEIGHT: 40,
30 | DASHBOARD_ITEM_HORIZONTAL_HEIGHT: 32,
31 | };
32 |
33 | export const allLangs = [
34 | {
35 | label: 'English',
36 | value: 'en',
37 | systemValue: enUS,
38 | icon: '/assets/icons/flags/ic_flag_en.svg',
39 | },
40 | {
41 | label: 'French',
42 | value: 'fr',
43 | systemValue: frFR,
44 | icon: '/assets/icons/flags/ic_flag_fr.svg',
45 | },
46 | {
47 | label: 'Vietnamese',
48 | value: 'vn',
49 | systemValue: viVN,
50 | icon: '/assets/icons/flags/ic_flag_vn.svg',
51 | },
52 | {
53 | label: 'Chinese',
54 | value: 'cn',
55 | systemValue: zhCN,
56 | icon: '/assets/icons/flags/ic_flag_cn.svg',
57 | },
58 | {
59 | label: 'Arabic (Sudan)',
60 | value: 'ar',
61 | systemValue: arSD,
62 | icon: '/assets/icons/flags/ic_flag_sa.svg',
63 | },
64 | ];
65 |
66 | export const defaultLang = allLangs[0]; // English
67 |
68 |
69 |
70 | // DEFAULT ROOT PATH
71 | export const DEFAULT_PATH = PATH_DASHBOARD.general.app; // as '/app'
72 |
--------------------------------------------------------------------------------
/src/hooks/useEventListener.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef, useLayoutEffect } from 'react';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
6 |
7 | function useEventListener(eventName, handler, element, options) {
8 | // Create a ref that stores handler
9 | const savedHandler = useRef(handler);
10 |
11 | useIsomorphicLayoutEffect(() => {
12 | savedHandler.current = handler;
13 | }, [handler]);
14 |
15 | useEffect(() => {
16 | // Define the listening target
17 | const targetElement = element?.current || window;
18 | if (!(targetElement && targetElement.addEventListener)) {
19 | return;
20 | }
21 |
22 | // Create event listener that calls handler function stored in ref
23 | const eventListener = (event) => savedHandler.current(event);
24 |
25 | targetElement.addEventListener(eventName, eventListener, options);
26 |
27 | // Remove event listener on cleanup
28 | // eslint-disable-next-line consistent-return
29 | return () => {
30 | targetElement.removeEventListener(eventName, eventListener);
31 | };
32 | }, [eventName, element, options]);
33 | }
34 |
35 | export default useEventListener;
36 |
--------------------------------------------------------------------------------
/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/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/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import { BrowserRouter } from 'react-router-dom';
4 | import { HelmetProvider } from "react-helmet-async";
5 | import App from "./App";
6 | import reportWebVitals from "./reportWebVitals";
7 |
8 | import { Provider as ReduxProvider } from 'react-redux';
9 |
10 | // contexts
11 | import SettingsProvider from "./contexts/SettingsContext";
12 | import { store } from "./redux/store";
13 |
14 | const root = ReactDOM.createRoot(document.getElementById("root"));
15 |
16 | root.render(
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | );
29 |
30 | // If you want to start measuring performance in your app, pass a function
31 | // to log results (for example: reportWebVitals(console.log))
32 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
33 | reportWebVitals();
34 |
--------------------------------------------------------------------------------
/src/layouts/auth/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Container, Stack } from "@mui/material";
3 | import { Navigate, Outlet } from "react-router-dom";
4 |
5 | import Logo from "../../assets/Images/logo.ico";
6 | import { useSelector } from "react-redux";
7 |
8 | const AuthLayout = () => {
9 | const { isLoggedIn } = useSelector((state) => state.auth);
10 |
11 | if (isLoggedIn) {
12 | return ;
13 | }
14 |
15 | return (
16 | <>
17 |
18 |
19 |
24 |
25 |
26 |
27 |
28 |
29 | >
30 | );
31 | };
32 |
33 | export default AuthLayout;
34 |
--------------------------------------------------------------------------------
/src/layouts/dashboard/BottomNav.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useTheme } from "@mui/material/styles";
3 | import { Box, IconButton, Stack } from "@mui/material";
4 | import ProfileMenu from "./ProfileMenu";
5 | import { Nav_Buttons } from "../../data";
6 |
7 | const BottomNav = () => {
8 | const theme = useTheme();
9 |
10 | const [selectedTab, setSelectedTab] = React.useState(0);
11 |
12 | const handleChangeTab = (index) => {
13 | setSelectedTab(index);
14 | };
15 |
16 | return (
17 |
28 |
36 | {Nav_Buttons.map((el) => {
37 | return el.index === selectedTab ? (
38 |
39 |
40 | {el.icon}
41 |
42 |
43 | ) : (
44 | {
46 | handleChangeTab(el.index);
47 | }}
48 | sx={{
49 | width: "max-content",
50 | color:
51 | theme.palette.mode === "light"
52 | ? "#080707"
53 | : theme.palette.text.primary,
54 | }}
55 | >
56 | {el.icon}
57 |
58 | );
59 | })}
60 |
61 |
62 |
63 | );
64 | };
65 |
66 | export default BottomNav;
67 |
--------------------------------------------------------------------------------
/src/layouts/dashboard/ProfileMenu.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Avatar, Box, Fade, Menu, MenuItem, Stack } from "@mui/material";
3 |
4 | import { faker } from "@faker-js/faker";
5 |
6 | import { Profile_Menu } from "../../data";
7 | import { useDispatch, useSelector } from "react-redux";
8 | import { LogoutUser } from "../../redux/slices/auth";
9 | import { socket } from "../../socket";
10 | import { useNavigate } from "react-router-dom";
11 | import { AWS_S3_REGION, S3_BUCKET_NAME } from "../../config";
12 |
13 | const ProfileMenu = () => {
14 | const {user} = useSelector((state) => state.app);
15 | const navigate = useNavigate();
16 | const dispatch = useDispatch();
17 | const [anchorEl, setAnchorEl] = React.useState(null);
18 | const openMenu = Boolean(anchorEl);
19 | const handleClick = (event) => {
20 | setAnchorEl(event.currentTarget);
21 | };
22 | const handleClose = () => {
23 | setAnchorEl(null);
24 | };
25 |
26 | const user_id = window.localStorage.getItem("user_id");
27 |
28 | const user_name = user?.firstName;
29 | const user_img = `https://${S3_BUCKET_NAME}.s3.${AWS_S3_REGION}.amazonaws.com/${user?.avatar}`;
30 |
31 | return (
32 | <>
33 |
42 |
91 | >
92 | );
93 | };
94 |
95 | export default ProfileMenu;
96 |
--------------------------------------------------------------------------------
/src/layouts/main/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useSelector } from "react-redux";
3 | import { Navigate, Outlet } from "react-router-dom";
4 |
5 | const MainLayout = () => {
6 |
7 | const {isLoggedIn} = useSelector((state) => state.auth);
8 |
9 | if (!isLoggedIn) {
10 | return ;
11 | }
12 | return (
13 | <>
14 | Main Layout
15 |
16 |
17 | >
18 | );
19 | };
20 |
21 | export default MainLayout;
22 |
--------------------------------------------------------------------------------
/src/pages/Page404.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const Page404 = () => {
4 | return <>404>;
5 | };
6 |
7 |
8 | export default Page404;
--------------------------------------------------------------------------------
/src/pages/auth/Login.js:
--------------------------------------------------------------------------------
1 | import { Link as RouterLink } from "react-router-dom";
2 | // sections
3 | import { Stack, Typography, Link } from "@mui/material";
4 | import AuthSocial from "../../sections/auth/AuthSocial";
5 | import Login from "../../sections/auth/LoginForm";
6 |
7 | // ----------------------------------------------------------------------
8 |
9 | export default function LoginPage() {
10 | return (
11 | <>
12 |
13 | Login to Tawk
14 |
15 |
16 | New user?
17 |
18 |
23 | Create an account
24 |
25 |
26 |
27 | {/* Form */}
28 |
29 |
30 |
31 | >
32 | );
33 | }
34 |
--------------------------------------------------------------------------------
/src/pages/auth/NewPassword.js:
--------------------------------------------------------------------------------
1 | import { Stack, Typography, Link } from "@mui/material";
2 | import { Link as RouterLink } from "react-router-dom";
3 | import React from "react";
4 | import { CaretLeft } from "phosphor-react";
5 | import NewPasswordForm from "../../sections/auth/NewPasswordForm";
6 |
7 | const NewPassword = () => {
8 | return (
9 | <>
10 |
11 |
12 | Reset Password
13 |
14 |
15 |
16 | Please set your new password.
17 |
18 |
19 |
20 | {/* NewPasswordForm */}
21 |
22 |
23 |
24 |
36 |
37 | Return to sign in
38 |
39 | >
40 | );
41 | };
42 |
43 | export default NewPassword;
44 |
--------------------------------------------------------------------------------
/src/pages/auth/Register.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link as RouterLink } from 'react-router-dom';
3 | // @mui
4 | import { Stack, Typography, Link } from '@mui/material';
5 |
6 | import RegisterForm from "../../sections/auth/RegisterForm";
7 | import AuthSocial from '../../sections/auth/AuthSocial';
8 |
9 | // ----------------------------------------------------------------------
10 |
11 | export default function Register() {
12 | return (
13 | <>
14 |
15 | Get started with Tawk.
16 |
17 |
18 | Already have an account?
19 |
20 |
21 | Sign in
22 |
23 |
24 |
25 | {/* Form */}
26 |
27 |
28 |
32 | {'By signing up, I agree to '}
33 |
34 | Terms of Service
35 |
36 | {' and '}
37 |
38 | Privacy Policy
39 |
40 | .
41 |
42 |
43 |
44 | >
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/src/pages/auth/ResetPassword.js:
--------------------------------------------------------------------------------
1 | import { Stack, Typography, Link } from "@mui/material";
2 | import { Link as RouterLink } from "react-router-dom";
3 | import React from "react";
4 | import { CaretLeft } from "phosphor-react";
5 | import AuthResetPasswordForm from "../../sections/auth/ResetPasswordForm";
6 |
7 | const ResetPassword = () => {
8 | return (
9 | <>
10 |
11 |
12 | Forgot your password?
13 |
14 |
15 |
16 | Please enter the email address associated with your account and We
17 | will email you a link to reset your password.
18 |
19 |
20 |
21 | {/* Reset Password Form */}
22 |
23 |
24 |
36 |
37 | Return to sign in
38 |
39 | >
40 | );
41 | };
42 |
43 | export default ResetPassword;
44 |
--------------------------------------------------------------------------------
/src/pages/auth/Verify.js:
--------------------------------------------------------------------------------
1 | import { Link as RouterLink } from "react-router-dom";
2 | // sections
3 | import { Stack, Typography, Link } from "@mui/material";
4 | import AuthSocial from "../../sections/auth/AuthSocial";
5 | import Login from "../../sections/auth/LoginForm";
6 | import VerifyForm from "../../sections/auth/VerifyForm";
7 |
8 | // ----------------------------------------------------------------------
9 |
10 | export default function LoginPage() {
11 | return (
12 | <>
13 |
14 | Please Verify OTP
15 |
16 |
17 |
18 | Sent to email (shreyanshshah242@gmail.com)
19 |
20 |
21 |
22 | {/* Form */}
23 |
24 | >
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/src/pages/dashboard/GeneralApp.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useTheme } from "@mui/material/styles";
3 | import { Box, Stack, Typography } from "@mui/material";
4 |
5 | import { Link, useSearchParams } from "react-router-dom";
6 | import ChatComponent from "./Conversation";
7 | import Chats from "./Chats";
8 | import Contact from "../../sections/dashboard/Contact";
9 | import NoChat from "../../assets/Illustration/NoChat";
10 | import { useSelector } from "react-redux";
11 | import StarredMessages from "../../sections/dashboard/StarredMessages";
12 | import Media from "../../sections/dashboard/SharedMessages";
13 |
14 | const GeneralApp = () => {
15 | const [searchParams] = useSearchParams();
16 |
17 | const theme = useTheme();
18 |
19 | const { sideBar, room_id, chat_type } = useSelector((state) => state.app);
20 |
21 | return (
22 | <>
23 |
24 |
25 |
42 | {chat_type === "individual" &&
43 | room_id !== null ? (
44 |
45 | ) : (
46 |
52 |
53 |
54 | Select a conversation or start a{" "}
55 |
62 | new one
63 |
64 |
65 |
66 | )}
67 |
68 | {sideBar.open &&
69 | (() => {
70 | switch (sideBar.type) {
71 | case "CONTACT":
72 | return ;
73 |
74 | case "STARRED":
75 | return ;
76 |
77 | case "SHARED":
78 | return ;
79 |
80 | default:
81 | break;
82 | }
83 | })()}
84 |
85 | >
86 | );
87 | };
88 |
89 | export default GeneralApp;
90 |
--------------------------------------------------------------------------------
/src/pages/dashboard/Settings/Profile.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from "react";
2 | import { Box, IconButton, Stack, Typography } from "@mui/material";
3 | import { CaretLeft } from "phosphor-react";
4 | import ProfileForm from "../../../sections/dashboard/Settings/ProfileForm";
5 | import { useDispatch } from "react-redux";
6 | import { FetchUserProfile } from "../../../redux/slices/app";
7 |
8 | const Profile = () => {
9 | const dispatch = useDispatch();
10 |
11 | useEffect(() => {
12 | dispatch(FetchUserProfile());
13 | }, []);
14 |
15 | return (
16 | <>
17 |
18 | {/* Left Pane */}
19 |
26 | theme.palette.mode === "light"
27 | ? "#F8FAFF"
28 | : theme.palette.background,
29 |
30 | boxShadow: "0px 0px 2px rgba(0, 0, 0, 0.25)",
31 | }}
32 | >
33 |
34 | {/* Header */}
35 |
36 |
37 |
38 |
39 |
40 | Profile
41 |
42 |
43 | {/* Profile Edit Form */}
44 |
45 |
46 |
47 |
48 | {/* Right Pane */}
49 |
54 | theme.palette.mode === "light"
55 | ? "#FFF"
56 | : theme.palette.background.paper,
57 | borderBottom: "6px solid #0162C4",
58 | }}
59 | >
60 |
61 | >
62 | );
63 | };
64 |
65 | export default Profile;
66 |
--------------------------------------------------------------------------------
/src/redux/rootReducer.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 | import storage from 'redux-persist/lib/storage';
3 | // slices
4 | import appReducer from './slices/app';
5 | import audioCallReducer from './slices/audioCall';
6 | import videoCallReducer from './slices/videoCall';
7 | import authReducer from './slices/auth';
8 | import conversationReducer from './slices/conversation';
9 |
10 | // ----------------------------------------------------------------------
11 |
12 | const rootPersistConfig = {
13 | key: 'root',
14 | storage,
15 | keyPrefix: 'redux-',
16 | // whitelist: [],
17 | // blacklist: [],
18 | };
19 |
20 | const rootReducer = combineReducers({
21 | app: appReducer,
22 | auth: authReducer,
23 | conversation: conversationReducer,
24 | audioCall: audioCallReducer,
25 | videoCall: videoCallReducer,
26 | });
27 |
28 | export { rootPersistConfig, rootReducer };
29 |
--------------------------------------------------------------------------------
/src/redux/slices/videoCall.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 | import { socket } from "../../socket";
3 | import axios from "../../utils/axios";
4 |
5 | const initialState = {
6 | open_video_dialog: false,
7 | open_video_notification_dialog: false,
8 | call_queue: [], // can have max 1 call at any point of time
9 | incoming: false,
10 | };
11 |
12 | const slice = createSlice({
13 | name: "videoCall",
14 | initialState,
15 | reducers: {
16 | pushToVideoCallQueue(state, action) {
17 | // check video_call_queue in redux store
18 |
19 | if (state.call_queue.length === 0) {
20 | state.call_queue.push(action.payload.call);
21 | if (action.payload.incoming) {
22 | state.open_video_notification_dialog = true; // this will open up the call dialog
23 | state.incoming = true;
24 | }
25 | else {
26 | state.open_video_dialog = true;
27 | state.incoming = false;
28 | }
29 | } else {
30 | // if queue is not empty then emit user_is_busy => in turn server will send this event to sender of call
31 | socket.emit("user_is_busy_video_call", { ...action.payload });
32 | }
33 |
34 | // Ideally queue should be managed on server side
35 | },
36 | resetVideoCallQueue(state, action) {
37 | state.call_queue = [];
38 | state.open_video_notification_dialog = false;
39 | state.incoming = false;
40 | },
41 | closeNotificationDialog(state, action) {
42 | state.open_video_notification_dialog = false;
43 | },
44 | updateCallDialog(state, action) {
45 | state.open_video_dialog = action.payload.state;
46 | state.open_video_notification_dialog = false;
47 | },
48 | },
49 | });
50 |
51 | // Reducer
52 | export default slice.reducer;
53 |
54 | // ----------------------------------------------------------------------
55 |
56 | export const StartVideoCall = (id) => {
57 | return async (dispatch, getState) => {
58 | dispatch(slice.actions.resetVideoCallQueue());
59 | axios
60 | .post(
61 | "/user/start-video-call",
62 | { id },
63 | {
64 | headers: {
65 | "Content-Type": "application/json",
66 | Authorization: `Bearer ${getState().auth.token}`,
67 | },
68 | }
69 | )
70 | .then((response) => {
71 | console.log(response);
72 | dispatch(
73 | slice.actions.pushToVideoCallQueue({
74 | call: response.data.data,
75 | incoming: false,
76 | })
77 | );
78 | })
79 | .catch((err) => {
80 | console.log(err);
81 | });
82 | };
83 | };
84 |
85 | export const PushToVideoCallQueue = (call) => {
86 | return async (dispatch, getState) => {
87 | dispatch(slice.actions.pushToVideoCallQueue({call, incoming: true}));
88 | };
89 | };
90 |
91 | export const ResetVideoCallQueue = () => {
92 | return async (dispatch, getState) => {
93 | dispatch(slice.actions.resetVideoCallQueue());
94 | };
95 | };
96 |
97 | export const CloseVideoNotificationDialog = () => {
98 | return async (dispatch, getState) => {
99 | dispatch(slice.actions.closeNotificationDialog());
100 | };
101 | };
102 |
103 | export const UpdateVideoCallDialog = ({ state }) => {
104 | return async (dispatch, getState) => {
105 | dispatch(slice.actions.updateCallDialog({ state }));
106 | };
107 | };
108 |
--------------------------------------------------------------------------------
/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/index.js:
--------------------------------------------------------------------------------
1 | import { Suspense, lazy } from "react";
2 | import { Navigate, useRoutes } from "react-router-dom";
3 |
4 | // layouts
5 | import DashboardLayout from "../layouts/dashboard";
6 | import AuthLayout from "../layouts/auth";
7 |
8 | // config
9 | import { DEFAULT_PATH } from "../config";
10 | import LoadingScreen from "../components/LoadingScreen";
11 |
12 | const Loadable = (Component) => (props) => {
13 | return (
14 | }>
15 |
16 |
17 | );
18 | };
19 |
20 | export default function Router() {
21 | return useRoutes([
22 | {
23 | path: "/auth",
24 | element: ,
25 | children: [
26 | { path: "login", element: },
27 | { path: "register", element: },
28 | { path: "reset-password", element: },
29 | { path: "new-password", element: },
30 | {path: "verify", element: },
31 | ],
32 | },
33 | {
34 | path: "/",
35 | element: ,
36 | children: [
37 | { element: , index: true },
38 | { path: "app", element: },
39 | { path: "group", element: },
40 | { path: "settings", element: },
41 | { path: "conversation", element: },
42 | { path: "chats", element: },
43 | { path: "contact", element: },
44 | { path: "profile", element: },
45 |
46 | {path: "call", element: },
47 |
48 | { path: "404", element: },
49 | { path: "*", element: },
50 | ],
51 | },
52 |
53 | { path: "*", element: },
54 | ]);
55 | }
56 |
57 | const GeneralApp = Loadable(
58 | lazy(() => import("../pages/dashboard/GeneralApp"))
59 | );
60 | const Conversation = Loadable(
61 | lazy(() => import("../pages/dashboard/Conversation"))
62 | );
63 | const Chats = Loadable(lazy(() => import("../pages/dashboard/Chats")));
64 | const Group = Loadable(lazy(() => import("../pages/dashboard/Group")));
65 | const CallPage = Loadable(lazy(() => import("../pages/dashboard/Call")));
66 | const Contact = Loadable(lazy(() => import("../sections/dashboard/Contact")));
67 | const Page404 = Loadable(lazy(() => import("../pages/Page404")));
68 |
69 | const LoginPage = Loadable(lazy(() => import("../pages/auth/Login")));
70 | const VerifyPage = Loadable(lazy(() => import("../pages/auth/Verify")));
71 | const RegisterPage = Loadable(lazy(() => import("../pages/auth/Register")));
72 | const ResetPasswordPage = Loadable(
73 | lazy(() => import("../pages/auth/ResetPassword"))
74 | );
75 | const NewPasswordPage = Loadable(
76 | lazy(() => import("../pages/auth/NewPassword"))
77 | );
78 |
79 | // Settings
80 | const Settings = Loadable(lazy(() => import("../pages/dashboard/Settings")));
81 | const Profile = Loadable(
82 | lazy(() => import("../pages/dashboard/Settings/Profile"))
83 | );
84 |
--------------------------------------------------------------------------------
/src/routes/paths.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | function path(root, sublink) {
4 | return `${root}${sublink}`;
5 | }
6 |
7 | const ROOTS_DASHBOARD = "/";
8 |
9 | export const PATH_DASHBOARD = {
10 | root: ROOTS_DASHBOARD,
11 | general: {
12 | app: path(ROOTS_DASHBOARD, "app"),
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/src/sections/Dashboard/Audio/CallNotification.js:
--------------------------------------------------------------------------------
1 | import { faker } from "@faker-js/faker";
2 | import {
3 | Avatar,
4 | Button,
5 | Dialog,
6 | DialogActions,
7 | DialogContent,
8 | Slide,
9 | Stack,
10 | } from "@mui/material";
11 | import React from "react";
12 | import { useDispatch, useSelector } from "react-redux";
13 | import {
14 | ResetAudioCallQueue,
15 | UpdateAudioCallDialog,
16 | } from "../../../redux/slices/audioCall";
17 | import { socket } from "../../../socket";
18 | import { AWS_S3_REGION, S3_BUCKET_NAME } from "../../../config";
19 |
20 | const Transition = React.forwardRef(function Transition(props, ref) {
21 | return ;
22 | });
23 |
24 | const CallNotification = ({ open, handleClose }) => {
25 | const dispatch = useDispatch();
26 |
27 | const { user } = useSelector((state) => state.app);
28 | const [call_details] = useSelector((state) => state.audioCall.call_queue);
29 |
30 | const handleAccept = () => {
31 | socket.emit("audio_call_accepted", { ...call_details });
32 | dispatch(UpdateAudioCallDialog({ state: true }));
33 | };
34 |
35 | const handleDeny = () => {
36 | //
37 | socket.emit("audio_call_denied", { ...call_details });
38 | dispatch(ResetAudioCallQueue());
39 | handleClose();
40 | };
41 |
42 | return (
43 | <>
44 |
76 | >
77 | );
78 | };
79 |
80 | export default CallNotification;
81 |
--------------------------------------------------------------------------------
/src/sections/Dashboard/CreateGroup.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import * as Yup from "yup";
3 | import {
4 | Button,
5 | Dialog,
6 | DialogContent,
7 | DialogTitle,
8 | Slide,
9 | Stack,
10 | } from "@mui/material";
11 |
12 | import { yupResolver } from "@hookform/resolvers/yup";
13 | import { useForm } from "react-hook-form";
14 | import FormProvider from "../../components/hook-form/FormProvider";
15 | import { RHFTextField } from "../../components/hook-form";
16 | import RHFAutocomplete from "../../components/hook-form/RHFAutocomplete";
17 |
18 | const Transition = React.forwardRef(function Transition(props, ref) {
19 | return ;
20 | });
21 |
22 | const TAGS_OPTION = [
23 | "Toy Story 3",
24 | "Logan",
25 | "Full Metal Jacket",
26 | "Dangal",
27 | "The Sting",
28 | "2001: A Space Odyssey",
29 | "Singin' in the Rain",
30 | "Toy Story",
31 | "Bicycle Thieves",
32 | "The Kid",
33 | "Inglourious Basterds",
34 | "Snatch",
35 | "3 Idiots",
36 | ];
37 |
38 | const CreateGroupForm = ({ handleClose }) => {
39 | const NewGroupSchema = Yup.object().shape({
40 | title: Yup.string().required("Title is required"),
41 |
42 | members: Yup.array().min(2, "Must have at least 2 members"),
43 | });
44 |
45 | const defaultValues = {
46 | title: "",
47 |
48 | tags: [],
49 | };
50 |
51 | const methods = useForm({
52 | resolver: yupResolver(NewGroupSchema),
53 | defaultValues,
54 | });
55 |
56 | const {
57 | reset,
58 | watch,
59 | setValue,
60 | handleSubmit,
61 | formState: { isSubmitting, isValid },
62 | } = methods;
63 |
64 | const onSubmit = async (data) => {
65 | try {
66 | // API Call
67 | console.log("DATA", data);
68 | } catch (error) {
69 | console.error(error);
70 | }
71 | };
72 |
73 | return (
74 |
75 |
76 |
77 | option)}
83 | ChipProps={{ size: "medium" }}
84 | />
85 |
91 |
92 |
95 |
96 |
97 |
98 | );
99 | };
100 |
101 | const CreateGroup = ({ open, handleClose }) => {
102 | return (
103 |
120 | );
121 | };
122 |
123 | export default CreateGroup;
124 |
--------------------------------------------------------------------------------
/src/sections/Dashboard/Friends.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from "react";
2 | import { Dialog, DialogContent, Slide, Stack, Tab, Tabs } from "@mui/material";
3 | import { useDispatch, useSelector } from "react-redux";
4 | import {
5 | FetchFriendRequests,
6 | FetchFriends,
7 | FetchUsers,
8 | } from "../../redux/slices/app";
9 | import { FriendElement, FriendRequestElement, UserElement } from "../../components/UserElement";
10 |
11 | const Transition = React.forwardRef(function Transition(props, ref) {
12 | return ;
13 | });
14 |
15 | const UsersList = () => {
16 | const dispatch = useDispatch();
17 |
18 | const { users } = useSelector((state) => state.app);
19 |
20 | useEffect(() => {
21 | dispatch(FetchUsers());
22 | }, []);
23 |
24 | return (
25 | <>
26 | {users.map((el, idx) => {
27 | return ;
28 | })}
29 | >
30 | );
31 | };
32 |
33 | const FriendsList = () => {
34 | const dispatch = useDispatch();
35 |
36 | const { friends } = useSelector((state) => state.app);
37 |
38 | useEffect(() => {
39 | dispatch(FetchFriends());
40 | }, []);
41 |
42 | return (
43 | <>
44 | {friends.map((el, idx) => {
45 | return ;
46 | })}
47 | >
48 | );
49 | };
50 |
51 | const RequestsList = () => {
52 | const dispatch = useDispatch();
53 |
54 | const { friendRequests } = useSelector((state) => state.app);
55 |
56 | useEffect(() => {
57 | dispatch(FetchFriendRequests());
58 | }, []);
59 |
60 | return (
61 | <>
62 | {friendRequests.map((el, idx) => {
63 | return ;
64 | })}
65 | >
66 | );
67 | };
68 |
69 | const Friends = ({ open, handleClose }) => {
70 | const [value, setValue] = React.useState(0);
71 |
72 | const handleChange = (event, newValue) => {
73 | setValue(newValue);
74 | };
75 |
76 | return (
77 |
117 | );
118 | };
119 |
120 | export default Friends;
121 |
--------------------------------------------------------------------------------
/src/sections/Dashboard/Settings/ProfileForm.js:
--------------------------------------------------------------------------------
1 | import React, { useCallback, useState } from "react";
2 | import * as Yup from "yup";
3 | // form
4 | import { useForm } from "react-hook-form";
5 | import { yupResolver } from "@hookform/resolvers/yup";
6 | import FormProvider from "../../../components/hook-form/FormProvider";
7 | import { RHFTextField, RHFUploadAvatar } from "../../../components/hook-form";
8 | import { Stack } from "@mui/material";
9 | import { LoadingButton } from "@mui/lab";
10 | import { useDispatch, useSelector } from "react-redux";
11 | import { UpdateUserProfile } from "../../../redux/slices/app";
12 | import { AWS_S3_REGION, S3_BUCKET_NAME } from "../../../config";
13 |
14 | const ProfileForm = () => {
15 | const dispatch = useDispatch();
16 | const [file, setFile] = useState();
17 | const { user } = useSelector((state) => state.app);
18 |
19 | const ProfileSchema = Yup.object().shape({
20 | firstName: Yup.string().required("Name is required"),
21 | about: Yup.string().required("About is required"),
22 | avatar: Yup.string().required("Avatar is required").nullable(true),
23 | });
24 |
25 | const defaultValues = {
26 | firstName: user?.firstName,
27 | about: user?.about,
28 | avatar: `https://${S3_BUCKET_NAME}.s3.${AWS_S3_REGION}.amazonaws.com/${user?.avatar}`,
29 | };
30 |
31 | const methods = useForm({
32 | resolver: yupResolver(ProfileSchema),
33 | defaultValues,
34 | });
35 |
36 | const {
37 | reset,
38 | watch,
39 | control,
40 | setValue,
41 | handleSubmit,
42 | formState: { isSubmitting, isSubmitSuccessful },
43 | } = methods;
44 |
45 | const values = watch();
46 |
47 | const onSubmit = async (data) => {
48 | try {
49 | // Send API request
50 | console.log("DATA", data);
51 | dispatch(
52 | UpdateUserProfile({
53 | firstName: data?.firstName,
54 | about: data?.about,
55 | avatar: file,
56 | })
57 | );
58 | } catch (error) {
59 | console.error(error);
60 | }
61 | };
62 |
63 | const handleDrop = useCallback(
64 | (acceptedFiles) => {
65 | const file = acceptedFiles[0];
66 |
67 | setFile(file);
68 |
69 | const newFile = Object.assign(file, {
70 | preview: URL.createObjectURL(file),
71 | });
72 |
73 | if (file) {
74 | setValue("avatar", newFile, { shouldValidate: true });
75 | }
76 | },
77 | [setValue]
78 | );
79 |
80 | return (
81 |
82 |
83 |
84 |
85 |
90 |
91 |
92 |
93 |
100 | Save
101 |
102 |
103 |
104 |
105 | );
106 | };
107 |
108 | export default ProfileForm;
109 |
--------------------------------------------------------------------------------
/src/sections/Dashboard/Settings/ThemeDialog.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | Dialog,
4 | Slide,
5 | Button,
6 | DialogActions,
7 | DialogContent,
8 | DialogTitle,
9 | Radio,
10 | RadioGroup,
11 | FormControl,
12 | FormControlLabel,
13 | } from "@mui/material";
14 |
15 | const Transition = React.forwardRef(function Transition(props, ref) {
16 | return ;
17 | });
18 |
19 | const ThemeDialog = ({ open, handleClose }) => {
20 | return (
21 | <>
22 |
59 | >
60 | );
61 | };
62 |
63 | export default ThemeDialog;
64 |
--------------------------------------------------------------------------------
/src/sections/Dashboard/StarredMessages.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useTheme } from "@mui/material/styles";
3 | import { Box, IconButton, Stack, Typography } from "@mui/material";
4 | import { ArrowLeft } from "phosphor-react";
5 | import useResponsive from "../../hooks/useResponsive";
6 | import { useDispatch } from "react-redux";
7 | import { UpdateSidebarType } from "../../redux/slices/app";
8 | import { Conversation } from "../../pages/dashboard/Conversation";
9 |
10 | const StarredMessages = () => {
11 | const dispatch = useDispatch();
12 |
13 | const theme = useTheme();
14 |
15 | const isDesktop = useResponsive("up", "md");
16 |
17 | return (
18 |
19 |
20 |
30 |
36 | {
38 | dispatch(UpdateSidebarType("CONTACT"));
39 | }}
40 | >
41 |
42 |
43 | Starred Messages
44 |
45 |
46 |
55 |
56 |
57 |
58 |
59 | );
60 | };
61 |
62 | export default StarredMessages;
63 |
--------------------------------------------------------------------------------
/src/sections/Dashboard/StartCall.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from "react";
2 | import {
3 | Dialog,
4 | DialogContent,
5 | DialogTitle,
6 | Slide,
7 | Stack,
8 | } from "@mui/material";
9 | import {
10 | Search,
11 | SearchIconWrapper,
12 | StyledInputBase,
13 | } from "../../components/Search";
14 | import { MagnifyingGlass } from "phosphor-react";
15 | import { CallElement } from "../../components/CallElement";
16 | import { CallList } from "../../data";
17 | import { useDispatch, useSelector } from "react-redux";
18 | import { FetchAllUsers } from "../../redux/slices/app";
19 | import {faker} from "@faker-js/faker";
20 |
21 | const Transition = React.forwardRef(function Transition(props, ref) {
22 | return ;
23 | });
24 |
25 | const StartCall = ({ open, handleClose }) => {
26 | const {all_users} = useSelector((state) => state.app);
27 | const dispatch = useDispatch();
28 | useEffect(() => {
29 | dispatch(FetchAllUsers());
30 | }, []);
31 |
32 | console.log(CallList, all_users, "Call List Info");
33 |
34 | const list = all_users.map((el) => ({
35 | id: el?._id,
36 | name: `${el?.firstName} ${el?.lastName}`,
37 | image: faker.image.avatar(),
38 | }));
39 |
40 | return (
41 |
73 | );
74 | };
75 |
76 | export default StartCall;
77 |
--------------------------------------------------------------------------------
/src/sections/Dashboard/video/CallNotification.js:
--------------------------------------------------------------------------------
1 | import { faker } from "@faker-js/faker";
2 | import {
3 | Avatar,
4 | Button,
5 | Dialog,
6 | DialogActions,
7 | DialogContent,
8 | Slide,
9 | Stack,
10 | } from "@mui/material";
11 | import React from "react";
12 | import { useDispatch, useSelector } from "react-redux";
13 | import {
14 | ResetVideoCallQueue,
15 | UpdateVideoCallDialog,
16 | } from "../../../redux/slices/videoCall";
17 | import { socket } from "../../../socket";
18 | import { AWS_S3_REGION, S3_BUCKET_NAME } from "../../../config";
19 |
20 | const Transition = React.forwardRef(function Transition(props, ref) {
21 | return ;
22 | });
23 |
24 | const CallNotification = ({ open, handleClose }) => {
25 | const dispatch = useDispatch();
26 | const { user } = useSelector((state) => state.app);
27 | const [call_details] = useSelector((state) => state.videoCall.call_queue);
28 |
29 | const handleAccept = () => {
30 | socket.emit("video_call_accepted", { ...call_details });
31 | dispatch(UpdateVideoCallDialog({ state: true }));
32 | };
33 |
34 | const handleDeny = () => {
35 | //
36 | socket.emit("video_call_denied", { ...call_details });
37 | dispatch(ResetVideoCallQueue());
38 | handleClose();
39 | };
40 |
41 | return (
42 | <>
43 |
75 | >
76 | );
77 | };
78 |
79 | export default CallNotification;
80 |
--------------------------------------------------------------------------------
/src/sections/auth/AuthSocial.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { Divider, IconButton, Stack } from '@mui/material';
3 | import { GithubLogo, GoogleLogo, TwitterLogo } from 'phosphor-react';
4 |
5 | // ----------------------------------------------------------------------
6 |
7 | export default function AuthSocial() {
8 |
9 |
10 | const handleGoogleLogin = async () => {
11 |
12 | };
13 |
14 | const handleGithubLogin = async () => {
15 |
16 | };
17 |
18 | const handleTwitterLogin = async () => {
19 |
20 | };
21 |
22 | return (
23 |
24 |
34 | OR
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | );
52 | }
53 |
--------------------------------------------------------------------------------
/src/sections/auth/ResetPasswordForm.js:
--------------------------------------------------------------------------------
1 | import * as Yup from "yup";
2 | // form
3 | import { yupResolver } from "@hookform/resolvers/yup";
4 | import { useForm } from "react-hook-form";
5 | // components
6 | import FormProvider, { RHFTextField } from "../../components/hook-form";
7 | import { Button } from "@mui/material";
8 | import { useDispatch, useSelector } from "react-redux";
9 | import { ForgotPassword } from "../../redux/slices/auth";
10 | import { LoadingButton } from "@mui/lab";
11 |
12 | // ----------------------------------------------------------------------
13 |
14 | export default function AuthResetPasswordForm() {
15 | const { isLoading } = useSelector((state) => state.auth);
16 | const dispatch = useDispatch();
17 | const ResetPasswordSchema = Yup.object().shape({
18 | email: Yup.string()
19 | .required("Email is required")
20 | .email("Email must be a valid email address"),
21 | });
22 |
23 | const methods = useForm({
24 | resolver: yupResolver(ResetPasswordSchema),
25 | defaultValues: { email: "demo@tawk.com" },
26 | });
27 |
28 | const { handleSubmit } = methods;
29 |
30 | const onSubmit = async (data) => {
31 | try {
32 | // Send API Request
33 | dispatch(ForgotPassword(data));
34 | } catch (error) {
35 | console.error(error);
36 | }
37 | };
38 |
39 | return (
40 |
41 |
42 |
43 |
53 | theme.palette.mode === "light" ? "common.white" : "grey.800",
54 | "&:hover": {
55 | bgcolor: "text.primary",
56 | color: (theme) =>
57 | theme.palette.mode === "light" ? "common.white" : "grey.800",
58 | },
59 | }}
60 | >
61 | Send Request
62 |
63 |
64 | );
65 | }
66 |
--------------------------------------------------------------------------------
/src/sections/auth/VerifyForm.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import * as Yup from "yup";
3 | // form
4 | import { useForm } from "react-hook-form";
5 | import { yupResolver } from "@hookform/resolvers/yup";
6 | // @mui
7 | import { Stack, IconButton, InputAdornment, Button } from "@mui/material";
8 | // components
9 | import FormProvider, { RHFTextField } from "../../components/hook-form";
10 | import { Eye, EyeSlash } from "phosphor-react";
11 | import RHFCodes from "../../components/hook-form/RHFCodes";
12 | import { useDispatch, useSelector } from "react-redux";
13 | import { VerifyEmail } from "../../redux/slices/auth";
14 |
15 | // ----------------------------------------------------------------------
16 |
17 | export default function VerifyForm() {
18 | const dispatch = useDispatch();
19 | const { email } = useSelector((state) => state.auth);
20 | const VerifyCodeSchema = Yup.object().shape({
21 | code1: Yup.string().required("Code is required"),
22 | code2: Yup.string().required("Code is required"),
23 | code3: Yup.string().required("Code is required"),
24 | code4: Yup.string().required("Code is required"),
25 | code5: Yup.string().required("Code is required"),
26 | code6: Yup.string().required("Code is required"),
27 | });
28 |
29 | const defaultValues = {
30 | code1: "",
31 | code2: "",
32 | code3: "",
33 | code4: "",
34 | code5: "",
35 | code6: "",
36 | };
37 |
38 | const methods = useForm({
39 | mode: "onChange",
40 | resolver: yupResolver(VerifyCodeSchema),
41 | defaultValues,
42 | });
43 |
44 | const {
45 | handleSubmit,
46 | formState: { isSubmitting, errors },
47 | } = methods;
48 |
49 | const onSubmit = async (data) => {
50 | try {
51 | // Send API Request
52 | dispatch(
53 | VerifyEmail({
54 | email,
55 | otp: `${data.code1}${data.code2}${data.code3}${data.code4}${data.code5}${data.code6}`,
56 | })
57 | );
58 | } catch (error) {
59 | console.error(error);
60 | }
61 | };
62 |
63 | return (
64 |
65 |
66 |
70 |
71 |
90 |
91 |
92 | );
93 | }
94 |
--------------------------------------------------------------------------------
/src/socket.js:
--------------------------------------------------------------------------------
1 | import io from "socket.io-client"; // Add this
2 |
3 | let socket;
4 |
5 | const connectSocket = (user_id) => {
6 | socket = io("https://api.chat.codingmonk.in/", {
7 | query: `user_id=${user_id}`,
8 | });
9 | } // Add this -- our server will run on port 4000, so we connect to it from here
10 |
11 | export {socket, connectSocket};
12 |
--------------------------------------------------------------------------------
/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 {
6 | createTheme,
7 | ThemeProvider as MUIThemeProvider,
8 | StyledEngineProvider,
9 | } from "@mui/material/styles";
10 | // hooks
11 | import useSettings from "../hooks/useSettings.js";
12 | //
13 | import palette from "./palette";
14 | import typography from "./typography";
15 | import breakpoints from "./breakpoints";
16 | import componentsOverride from "./overrides";
17 | import shadows, { customShadows } from "./shadows";
18 |
19 | // ----------------------------------------------------------------------
20 |
21 | ThemeProvider.propTypes = {
22 | children: PropTypes.node,
23 | };
24 |
25 | export default function ThemeProvider({ children }) {
26 | const { themeMode, themeDirection } = useSettings();
27 |
28 | const isLight = themeMode === "light";
29 |
30 | const themeOptions = useMemo(
31 | () => ({
32 | palette: isLight ? palette.light : palette.dark,
33 | typography,
34 | breakpoints,
35 | shape: { borderRadius: 8 },
36 | direction: themeDirection,
37 | shadows: isLight ? shadows.light : shadows.dark,
38 | customShadows: isLight ? customShadows.light : customShadows.dark,
39 | }),
40 | [isLight, themeDirection]
41 | );
42 |
43 | const theme = createTheme(themeOptions);
44 |
45 | theme.components = componentsOverride(theme);
46 |
47 | return (
48 |
49 |
50 |
51 | {children}
52 |
53 |
54 | );
55 | }
56 |
--------------------------------------------------------------------------------
/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/Alert.js:
--------------------------------------------------------------------------------
1 | import { ErrorIcon, InfoIcon, SuccessIcon, WarningIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Alert(theme) {
6 | const isLight = theme.palette.mode === 'light';
7 |
8 | const standardStyle = (color) => ({
9 | color: theme.palette[color][isLight ? 'darker' : 'lighter'],
10 | backgroundColor: theme.palette[color][isLight ? 'lighter' : 'darker'],
11 | '& .MuiAlert-icon': {
12 | color: theme.palette[color][isLight ? 'main' : 'light'],
13 | },
14 | });
15 |
16 | const filledStyle = (color) => ({
17 | color: theme.palette[color].contrastText,
18 | });
19 |
20 | const outlinedStyle = (color) => ({
21 | color: theme.palette[color][isLight ? 'darker' : 'lighter'],
22 | border: `solid 1px ${theme.palette[color][isLight ? 'light' : 'dark']}`,
23 | backgroundColor: theme.palette[color][isLight ? 'lighter' : 'darker'],
24 | '& .MuiAlert-icon': {
25 | color: theme.palette[color][isLight ? 'main' : 'light'],
26 | },
27 | });
28 |
29 | return {
30 | MuiAlert: {
31 | defaultProps: {
32 | iconMapping: {
33 | info: ,
34 | success: ,
35 | warning: ,
36 | error: ,
37 | },
38 | },
39 |
40 | styleOverrides: {
41 | message: {
42 | '& .MuiAlertTitle-root': {
43 | marginBottom: theme.spacing(0.5),
44 | },
45 | },
46 | action: {
47 | '& button:not(:first-of-type)': {
48 | marginLeft: theme.spacing(1),
49 | },
50 | },
51 |
52 | standardInfo: standardStyle('info'),
53 | standardSuccess: standardStyle('success'),
54 | standardWarning: standardStyle('warning'),
55 | standardError: standardStyle('error'),
56 |
57 | filledInfo: filledStyle('info'),
58 | filledSuccess: filledStyle('success'),
59 | filledWarning: filledStyle('warning'),
60 | filledError: filledStyle('error'),
61 |
62 | outlinedInfo: outlinedStyle('info'),
63 | outlinedSuccess: outlinedStyle('success'),
64 | outlinedWarning: outlinedStyle('warning'),
65 | outlinedError: outlinedStyle('error'),
66 | },
67 | },
68 | };
69 | }
70 |
--------------------------------------------------------------------------------
/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 | import { CheckboxIcon, CheckboxCheckedIcon, CheckboxIndeterminateIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Checkbox(theme) {
6 | return {
7 | MuiCheckbox: {
8 | defaultProps: {
9 | icon: ,
10 | checkedIcon: ,
11 | indeterminateIcon: ,
12 | },
13 |
14 | styleOverrides: {
15 | root: {
16 | padding: theme.spacing(1),
17 | '&.Mui-checked.Mui-disabled, &.Mui-disabled': {
18 | color: theme.palette.action.disabled,
19 | },
20 | '& .MuiSvgIcon-fontSizeMedium': {
21 | width: 24,
22 | height: 24,
23 | },
24 | '& .MuiSvgIcon-fontSizeSmall': {
25 | width: 20,
26 | height: 20,
27 | },
28 | svg: {
29 | fontSize: 24,
30 | '&[font-size=small]': {
31 | fontSize: 20,
32 | },
33 | },
34 | },
35 | },
36 | },
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/src/theme/overrides/Chip.js:
--------------------------------------------------------------------------------
1 | import { CloseIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Chip(theme) {
6 | return {
7 | MuiChip: {
8 | defaultProps: {
9 | deleteIcon: ,
10 | },
11 |
12 | styleOverrides: {
13 | colorDefault: {
14 | '& .MuiChip-avatarMedium, .MuiChip-avatarSmall': {
15 | color: theme.palette.text.secondary,
16 | },
17 | },
18 | outlined: {
19 | borderColor: theme.palette.grey[500_32],
20 | '&.MuiChip-colorPrimary': {
21 | borderColor: theme.palette.primary.main,
22 | },
23 | '&.MuiChip-colorSecondary': {
24 | borderColor: theme.palette.secondary.main,
25 | },
26 | },
27 | //
28 | avatarColorInfo: {
29 | color: theme.palette.info.contrastText,
30 | backgroundColor: theme.palette.info.dark,
31 | },
32 | avatarColorSuccess: {
33 | color: theme.palette.success.contrastText,
34 | backgroundColor: theme.palette.success.dark,
35 | },
36 | avatarColorWarning: {
37 | color: theme.palette.warning.contrastText,
38 | backgroundColor: theme.palette.warning.dark,
39 | },
40 | avatarColorError: {
41 | color: theme.palette.error.contrastText,
42 | backgroundColor: theme.palette.error.dark,
43 | },
44 | },
45 | },
46 | };
47 | }
48 |
--------------------------------------------------------------------------------
/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/DataGrid.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function DataGrid(theme) {
4 | return {
5 | MuiDataGrid: {
6 | styleOverrides: {
7 | root: {
8 | borderRadius: 0,
9 | border: `1px solid transparent`,
10 | '& .MuiTablePagination-root': {
11 | borderTop: 0,
12 | },
13 | },
14 | cell: {
15 | borderBottom: `1px solid ${theme.palette.divider}`,
16 | },
17 | columnSeparator: {
18 | color: theme.palette.divider,
19 | },
20 | toolbarContainer: {
21 | padding: theme.spacing(2),
22 | backgroundColor: theme.palette.background.neutral,
23 | '& .MuiButton-root': {
24 | marginRight: theme.spacing(1.5),
25 | color: theme.palette.text.primary,
26 | '&:hover': {
27 | backgroundColor: theme.palette.action.hover,
28 | },
29 | },
30 | },
31 | paper: {
32 | boxShadow: theme.customShadows.dropdown,
33 | },
34 | menu: {
35 | '& .MuiPaper-root': {
36 | boxShadow: theme.customShadows.dropdown,
37 | },
38 | '& .MuiMenuItem-root': {
39 | ...theme.typography.body2,
40 | '& .MuiListItemIcon-root': {
41 | minWidth: 'auto',
42 | },
43 | },
44 | },
45 | panelFooter: {
46 | padding: theme.spacing(2),
47 | justifyContent: 'flex-end',
48 | borderTop: `1px solid ${theme.palette.divider}`,
49 | '& .MuiButton-root': {
50 | '&:first-of-type': {
51 | marginRight: theme.spacing(1.5),
52 | color: theme.palette.text.primary,
53 | '&:hover': {
54 | backgroundColor: theme.palette.action.hover,
55 | },
56 | },
57 | '&:last-of-type': {
58 | color: theme.palette.common.white,
59 | backgroundColor: theme.palette.primary.main,
60 | '&:hover': {
61 | backgroundColor: theme.palette.primary.dark,
62 | },
63 | },
64 | },
65 | },
66 | filterForm: {
67 | padding: theme.spacing(1.5, 0),
68 | '& .MuiFormControl-root': {
69 | margin: theme.spacing(0, 0.5),
70 | },
71 | '& .MuiInput-root': {
72 | marginTop: theme.spacing(3),
73 | '&::before, &::after': {
74 | display: 'none',
75 | },
76 | '& .MuiNativeSelect-select, .MuiInput-input': {
77 | ...theme.typography.body2,
78 | padding: theme.spacing(0.75, 1),
79 | borderRadius: theme.shape.borderRadius,
80 | backgroundColor: theme.palette.background.neutral,
81 | },
82 | '& .MuiSvgIcon-root': {
83 | right: 4,
84 | },
85 | },
86 | },
87 | },
88 | },
89 | };
90 | }
91 |
--------------------------------------------------------------------------------
/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 | fontSize: 14,
9 | fontWeight: 600,
10 | '&.Mui-selected': {
11 | backgroundColor: theme.palette.action.selected,
12 | '&:hover': {
13 | backgroundColor: theme.palette.action.hover,
14 | },
15 | },
16 | },
17 | },
18 | },
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/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 | import { StarIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | const ICON_SMALL = { width: 20, height: 20 };
6 | const ICON_LARGE = { width: 28, height: 28 };
7 |
8 | export default function Rating(theme) {
9 | return {
10 | MuiRating: {
11 | defaultProps: {
12 | emptyIcon: ,
13 | icon: ,
14 | },
15 |
16 | styleOverrides: {
17 | root: {
18 | '&.Mui-disabled': {
19 | opacity: 0.48,
20 | },
21 | },
22 | iconEmpty: { color: theme.palette.grey[500_48] },
23 | sizeSmall: { '& svg': { ...ICON_SMALL } },
24 | sizeLarge: { '& svg': { ...ICON_LARGE } },
25 | },
26 | },
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/src/theme/overrides/Select.js:
--------------------------------------------------------------------------------
1 | import { InputSelectIcon } from './CustomIcons';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | export default function Select() {
6 | return {
7 | MuiSelect: {
8 | defaultProps: {
9 | IconComponent: InputSelectIcon,
10 | },
11 | },
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/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/Table.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Table(theme) {
4 | return {
5 | MuiTableRow: {
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 | MuiTableCell: {
18 | styleOverrides: {
19 | root: {
20 | borderBottom: 'none',
21 | },
22 | head: {
23 | color: theme.palette.text.secondary,
24 | backgroundColor: theme.palette.background.neutral,
25 | '&:first-of-type': {
26 | paddingLeft: theme.spacing(3),
27 | borderTopLeftRadius: theme.shape.borderRadius,
28 | borderBottomLeftRadius: theme.shape.borderRadius,
29 | boxShadow: `inset 8px 0 0 ${theme.palette.background.paper}`,
30 | },
31 | '&:last-of-type': {
32 | paddingRight: theme.spacing(3),
33 | borderTopRightRadius: theme.shape.borderRadius,
34 | borderBottomRightRadius: theme.shape.borderRadius,
35 | boxShadow: `inset -8px 0 0 ${theme.palette.background.paper}`,
36 | },
37 | },
38 | stickyHeader: {
39 | backgroundColor: theme.palette.background.paper,
40 | backgroundImage: `linear-gradient(to bottom, ${theme.palette.background.neutral} 0%, ${theme.palette.background.neutral} 100%)`,
41 | },
42 | body: {
43 | '&:first-of-type': {
44 | paddingLeft: theme.spacing(3),
45 | },
46 | '&:last-of-type': {
47 | paddingRight: theme.spacing(3),
48 | },
49 | },
50 | },
51 | },
52 | MuiTablePagination: {
53 | styleOverrides: {
54 | root: {
55 | borderTop: `solid 1px ${theme.palette.divider}`,
56 | },
57 | toolbar: {
58 | height: 64,
59 | },
60 | select: {
61 | '&:focus': {
62 | borderRadius: theme.shape.borderRadius,
63 | },
64 | },
65 | selectIcon: {
66 | width: 20,
67 | height: 20,
68 | marginTop: -4,
69 | },
70 | },
71 | },
72 | };
73 | }
74 |
--------------------------------------------------------------------------------
/src/theme/overrides/Tabs.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function Tabs(theme) {
4 | return {
5 | MuiTabs: {
6 | styleOverrides: {
7 | scrollButtons: {
8 | width: 48,
9 | borderRadius: '50%',
10 | },
11 | },
12 | },
13 | MuiTab: {
14 | styleOverrides: {
15 | root: {
16 | padding: 0,
17 | fontWeight: theme.typography.fontWeightMedium,
18 | borderTopLeftRadius: theme.shape.borderRadius,
19 | borderTopRightRadius: theme.shape.borderRadius,
20 | '&.Mui-selected': {
21 | color: theme.palette.text.primary,
22 | },
23 | '&:not(:last-of-type)': {
24 | marginRight: theme.spacing(5),
25 | },
26 | '@media (min-width: 600px)': {
27 | minWidth: 48,
28 | },
29 | },
30 | labelIcon: {
31 | minHeight: 48,
32 | flexDirection: 'row',
33 | '& > *:first-of-type': {
34 | marginBottom: 0,
35 | marginRight: theme.spacing(1),
36 | },
37 | },
38 | wrapped: {
39 | flexDirection: 'row',
40 | whiteSpace: 'nowrap',
41 | },
42 | textColorInherit: {
43 | opacity: 1,
44 | color: theme.palette.text.secondary,
45 | },
46 | },
47 | },
48 | MuiTabPanel: {
49 | styleOverrides: {
50 | root: {
51 | padding: 0,
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 | article: {
14 | fontWeight: 700
15 | }
16 | },
17 | },
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/src/theme/overrides/index.js:
--------------------------------------------------------------------------------
1 | import Fab from './Fab';
2 | import Card from './Card';
3 | import Chip from './Chip';
4 | import Tabs from './Tabs';
5 | import Menu from './Menu';
6 | import Link from './Link';
7 | import Lists from './List';
8 | import Table from './Table';
9 | import Alert from './Alert';
10 | import Badge from './Badge';
11 | import Paper from './Paper';
12 | import Input from './Input';
13 | import Radio from './Radio';
14 | import Drawer from './Drawer';
15 | import Dialog from './Dialog';
16 | import Avatar from './Avatar';
17 | import Rating from './Rating';
18 | import Slider from './Slider';
19 | import Button from './Button';
20 | import Switch from './Switch';
21 | import Select from './Select';
22 | import SvgIcon from './SvgIcon';
23 | import Tooltip from './Tooltip';
24 | import Popover from './Popover';
25 | import Stepper from './Stepper';
26 | import DataGrid from './DataGrid';
27 | import Skeleton from './Skeleton';
28 | import Backdrop from './Backdrop';
29 | import Progress from './Progress';
30 | import Timeline from './Timeline';
31 | import TreeView from './TreeView';
32 | import Checkbox from './Checkbox';
33 | import Accordion from './Accordion';
34 | import Typography from './Typography';
35 | import Pagination from './Pagination';
36 | import Breadcrumbs from './Breadcrumbs';
37 | import ButtonGroup from './ButtonGroup';
38 | import CssBaseline from './CssBaseline';
39 | import Autocomplete from './Autocomplete';
40 | import ToggleButton from './ToggleButton';
41 | import ControlLabel from './ControlLabel';
42 | import LoadingButton from './LoadingButton';
43 |
44 | // ----------------------------------------------------------------------
45 |
46 | export default function ComponentsOverrides(theme) {
47 | return Object.assign(
48 | Fab(theme),
49 | Tabs(theme),
50 | Chip(theme),
51 | Card(theme),
52 | Menu(theme),
53 | Link(theme),
54 | Input(theme),
55 | Radio(theme),
56 | Badge(theme),
57 | Lists(theme),
58 | Table(theme),
59 | Paper(theme),
60 | Alert(theme),
61 | Switch(theme),
62 | Select(theme),
63 | Button(theme),
64 | Rating(theme),
65 | Dialog(theme),
66 | Avatar(theme),
67 | Slider(theme),
68 | Drawer(theme),
69 | Stepper(theme),
70 | Tooltip(theme),
71 | Popover(theme),
72 | SvgIcon(theme),
73 | Checkbox(theme),
74 | DataGrid(theme),
75 | Skeleton(theme),
76 | Timeline(theme),
77 | TreeView(theme),
78 | Backdrop(theme),
79 | Progress(theme),
80 | Accordion(theme),
81 | Typography(theme),
82 | Pagination(theme),
83 | ButtonGroup(theme),
84 | Breadcrumbs(theme),
85 | CssBaseline(theme),
86 | Autocomplete(theme),
87 | ControlLabel(theme),
88 | ToggleButton(theme),
89 | LoadingButton(theme)
90 | );
91 | }
92 |
--------------------------------------------------------------------------------
/src/theme/typography.js:
--------------------------------------------------------------------------------
1 | import { pxToRem, responsiveFontSizes } from '../utils/getFontValue';
2 |
3 | // ----------------------------------------------------------------------
4 |
5 | const FONT_PRIMARY = 'Manrope, Public Sans, sans-serif'; // Google Font
6 | // const FONT_SECONDARY = 'CircularStd, sans-serif'; // Local Font
7 |
8 | const typography = {
9 | fontFamily: FONT_PRIMARY,
10 | fontWeightRegular: 400,
11 | fontWeightMedium: 600,
12 | fontWeightBold: 700,
13 | h1: {
14 | fontWeight: 700,
15 | lineHeight: 80 / 64,
16 | fontSize: pxToRem(40),
17 | letterSpacing: 2,
18 | ...responsiveFontSizes({ sm: 52, md: 58, lg: 64 }),
19 | },
20 | h2: {
21 | fontWeight: 700,
22 | lineHeight: 64 / 48,
23 | fontSize: pxToRem(32),
24 | ...responsiveFontSizes({ sm: 40, md: 44, lg: 48 }),
25 | },
26 | h3: {
27 | fontWeight: 700,
28 | lineHeight: 1.5,
29 | fontSize: pxToRem(24),
30 | ...responsiveFontSizes({ sm: 26, md: 30, lg: 32 }),
31 | },
32 | h4: {
33 | fontWeight: 700,
34 | lineHeight: 1.5,
35 | fontSize: pxToRem(20),
36 | ...responsiveFontSizes({ sm: 20, md: 24, lg: 24 }),
37 | },
38 | h5: {
39 | fontWeight: 700,
40 | lineHeight: 1.5,
41 | fontSize: pxToRem(18),
42 | ...responsiveFontSizes({ sm: 19, md: 20, lg: 20 }),
43 | },
44 | h6: {
45 | fontWeight: 700,
46 | lineHeight: 28 / 18,
47 | fontSize: pxToRem(17),
48 | ...responsiveFontSizes({ sm: 18, md: 18, lg: 18 }),
49 | },
50 | subtitle1: {
51 | fontWeight: 600,
52 | lineHeight: 1.5,
53 | fontSize: pxToRem(16),
54 | },
55 | subtitle2: {
56 | fontWeight: 700,
57 | lineHeight: 22 / 14,
58 | fontSize: pxToRem(14),
59 | },
60 | body1: {
61 | lineHeight: 1.5,
62 | fontSize: pxToRem(16),
63 | },
64 | body2: {
65 | lineHeight: 22 / 14,
66 | fontSize: pxToRem(14),
67 | fontWeight: 600,
68 | },
69 | caption: {
70 | lineHeight: 1.5,
71 | fontSize: pxToRem(12),
72 | fontWeight: 600,
73 | },
74 | overline: {
75 | fontWeight: 700,
76 | lineHeight: 1.5,
77 | fontSize: pxToRem(12),
78 | textTransform: 'uppercase',
79 | },
80 | button: {
81 | fontWeight: 700,
82 | lineHeight: 24 / 14,
83 | fontSize: pxToRem(14),
84 | textTransform: 'capitalize',
85 | },
86 | article: {
87 | fontWeight: 700,
88 | }
89 | };
90 |
91 | export default typography;
92 |
--------------------------------------------------------------------------------
/src/utils/axios.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | // config
3 | import { BASE_URL } from '../config';
4 |
5 | // ----------------------------------------------------------------------
6 |
7 | const axiosInstance = axios.create({ baseURL: BASE_URL });
8 |
9 | axiosInstance.interceptors.response.use(
10 | (response) => response,
11 | (error) => Promise.reject((error.response && error.response.data) || 'Something went wrong')
12 | );
13 |
14 | export default axiosInstance;
15 |
--------------------------------------------------------------------------------
/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 | const blur = props?.blur || 6;
21 | const opacity = props?.opacity || 0.8;
22 |
23 | return {
24 | backdropFilter: `blur(${blur}px)`,
25 | WebkitBackdropFilter: `blur(${blur}px)`, // Fix on Mobile
26 | backgroundColor: alpha(color, opacity),
27 | };
28 | },
29 | bgGradient: (props) => {
30 | const direction = getDirection(props?.direction);
31 | const startColor = props?.startColor || `${alpha('#000000', 0)} 0%`;
32 | const endColor = props?.endColor || '#000000 75%';
33 |
34 | return {
35 | background: `linear-gradient(${direction}, ${startColor}, ${endColor});`,
36 | };
37 | },
38 | bgImage: (props) => {
39 | const url = props?.url || '/assets/bg_gradient.jpg';
40 | const direction = getDirection(props?.direction);
41 | const startColor = props?.startColor || alpha(theme?.palette.grey[900] || '#000000', 0.88);
42 | const endColor = props?.endColor || alpha(theme?.palette.grey[900] || '#000000', 0.88);
43 |
44 | return {
45 | background: `linear-gradient(${direction}, ${startColor}, ${endColor}), url(${url})`,
46 | backgroundSize: 'cover',
47 | backgroundRepeat: 'no-repeat',
48 | backgroundPosition: 'center center',
49 | };
50 | },
51 | };
52 | }
53 |
--------------------------------------------------------------------------------
/src/utils/flattenArray.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------
2 |
3 | export default function flattenArray(list, key = 'children') {
4 | let children = [];
5 |
6 | const flatten = list?.map((item) => {
7 | if (item[key] && item[key].length) {
8 | children = [...children, ...item[key]];
9 | }
10 | return item;
11 | });
12 |
13 | return flatten?.concat(children.length ? flattenArray(children, key) : children);
14 | }
15 |
--------------------------------------------------------------------------------
/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/getColorPresets.js:
--------------------------------------------------------------------------------
1 | // theme
2 | import palette from "../theme/palette";
3 |
4 | export const colorPresets = [
5 | // DEFAULT
6 | {
7 | name: "default",
8 | ...palette.light.primary,
9 | },
10 | // PURPLE
11 | {
12 | name: "purple",
13 | lighter: "#EBD6FD",
14 | light: "#B985F4",
15 | main: "#7635dc",
16 | dark: "#431A9E",
17 | darker: "#200A69",
18 | contrastText: "#fff",
19 | },
20 | // CYAN
21 | {
22 | name: "cyan",
23 | lighter: "#D1FFFC",
24 | light: "#76F2FF",
25 | main: "#1CCAFF",
26 | dark: "#0E77B7",
27 | darker: "#053D7A",
28 | contrastText: palette.light.grey[800],
29 | },
30 | // BLUE
31 | {
32 | name: "blue",
33 | lighter: "#D1E9FC",
34 | light: "#76B0F1",
35 | main: "#2065D1",
36 | dark: "#103996",
37 | darker: "#061B64",
38 |
39 | contrastText: "#fff",
40 | },
41 | // ORANGE
42 | {
43 | name: "orange",
44 | lighter: "#FEF4D4",
45 | light: "#FED680",
46 | main: "#fda92d",
47 | dark: "#B66816",
48 | darker: "#793908",
49 | contrastText: palette.light.grey[800],
50 | },
51 | // RED
52 | {
53 | name: "red",
54 | lighter: "#FFE3D5",
55 | light: "#FFC1AC",
56 | main: "#FF3030",
57 | dark: "#B71833",
58 | darker: "#7A0930",
59 | contrastText: "#fff",
60 | },
61 | ];
62 |
63 | export const defaultPreset = colorPresets[0];
64 | export const purplePreset = colorPresets[1];
65 | export const cyanPreset = colorPresets[2];
66 | export const bluePreset = colorPresets[3];
67 | export const orangePreset = colorPresets[4];
68 | export const redPreset = colorPresets[5];
69 |
70 | export default function getColorPresets(presetsKey) {
71 | return {
72 | purple: purplePreset,
73 | cyan: cyanPreset,
74 | blue: bluePreset,
75 | orange: orangePreset,
76 | red: redPreset,
77 | default: defaultPreset,
78 | }[presetsKey];
79 | }
80 |
--------------------------------------------------------------------------------
/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/getFileFormat.js:
--------------------------------------------------------------------------------
1 | // components
2 | import Image from '../components/Image';
3 | import Iconify from '../components/Iconify';
4 |
5 | // ----------------------------------------------------------------------
6 |
7 | const FORMAT_IMG = ['jpg', 'jpeg', 'gif', 'bmp', 'png'];
8 | const FORMAT_VIDEO = ['m4v', 'avi', 'mpg', 'mp4', 'webm'];
9 | const FORMAT_WORD = ['doc', 'docx'];
10 | const FORMAT_EXCEL = ['xls', 'xlsx'];
11 | const FORMAT_POWERPOINT = ['ppt', 'pptx'];
12 | const FORMAT_PDF = ['pdf'];
13 | const FORMAT_PHOTOSHOP = ['psd'];
14 | const FORMAT_ILLUSTRATOR = ['ai', 'esp'];
15 |
16 | export function getFileType(fileUrl = '') {
17 | return (fileUrl && fileUrl.split('.').pop()) || '';
18 | }
19 |
20 | export function getFileName(fileUrl) {
21 | return fileUrl.substring(fileUrl.lastIndexOf('/') + 1).replace(/\.[^/.]+$/, '');
22 | }
23 |
24 | export function getFileFullName(fileUrl) {
25 | return fileUrl.split('/').pop();
26 | }
27 |
28 | export function getFileFormat(fileUrl) {
29 | let format;
30 |
31 | switch (fileUrl.includes(getFileType(fileUrl))) {
32 | case FORMAT_IMG.includes(getFileType(fileUrl)):
33 | format = 'image';
34 | break;
35 | case FORMAT_VIDEO.includes(getFileType(fileUrl)):
36 | format = 'video';
37 | break;
38 | case FORMAT_WORD.includes(getFileType(fileUrl)):
39 | format = 'word';
40 | break;
41 | case FORMAT_EXCEL.includes(getFileType(fileUrl)):
42 | format = 'excel';
43 | break;
44 | case FORMAT_POWERPOINT.includes(getFileType(fileUrl)):
45 | format = 'powerpoint';
46 | break;
47 | case FORMAT_PDF.includes(getFileType(fileUrl)):
48 | format = 'pdf';
49 | break;
50 | case FORMAT_PHOTOSHOP.includes(getFileType(fileUrl)):
51 | format = 'photoshop';
52 | break;
53 | case FORMAT_ILLUSTRATOR.includes(getFileType(fileUrl)):
54 | format = 'illustrator';
55 | break;
56 | default:
57 | format = getFileType(fileUrl);
58 | }
59 |
60 | return format;
61 | }
62 |
63 | const getIcon = (name) => (
64 |
69 | );
70 |
71 | export function getFileThumb(fileUrl) {
72 | let thumb;
73 | switch (getFileFormat(fileUrl)) {
74 | case 'video':
75 | thumb = getIcon('format_video');
76 | break;
77 | case 'word':
78 | thumb = getIcon('format_word');
79 | break;
80 | case 'excel':
81 | thumb = getIcon('format_excel');
82 | break;
83 | case 'powerpoint':
84 | thumb = getIcon('format_powerpoint');
85 | break;
86 | case 'pdf':
87 | thumb = getIcon('format_pdf');
88 | break;
89 | case 'photoshop':
90 | thumb = getIcon('format_photoshop');
91 | break;
92 | case 'illustrator':
93 | thumb = getIcon('format_ai');
94 | break;
95 | case 'image':
96 | thumb = ;
97 | break;
98 | default:
99 | thumb = ;
100 | }
101 | return thumb;
102 | }
103 |
--------------------------------------------------------------------------------
/src/utils/getFontValue.js:
--------------------------------------------------------------------------------
1 | // @mui
2 | import { useTheme } from '@mui/material/styles';
3 | // hooks
4 | import useResponsive from '../hooks/useResponsive';
5 |
6 | // ----------------------------------------------------------------------
7 |
8 | export default function GetFontValue(variant) {
9 | const theme = useTheme();
10 |
11 | const breakpoints = useWidth();
12 |
13 | const key = theme.breakpoints.up(breakpoints === 'xl' ? 'lg' : breakpoints);
14 |
15 | const hasResponsive =
16 | variant === 'h1' ||
17 | variant === 'h2' ||
18 | variant === 'h3' ||
19 | variant === 'h4' ||
20 | variant === 'h5' ||
21 | variant === 'h6';
22 |
23 | const getFont =
24 | hasResponsive && theme.typography[variant][key] ? theme.typography[variant][key] : theme.typography[variant];
25 |
26 | const fontSize = remToPx(getFont.fontSize);
27 |
28 | const lineHeight = Number(theme.typography[variant].lineHeight) * fontSize;
29 |
30 | const { fontWeight } = theme.typography[variant];
31 |
32 | const { letterSpacing } = theme.typography[variant];
33 |
34 | return { fontSize, lineHeight, fontWeight, letterSpacing };
35 | }
36 |
37 | // ----------------------------------------------------------------------
38 |
39 | export function remToPx(value) {
40 | return Math.round(parseFloat(value) * 16);
41 | }
42 |
43 | export function pxToRem(value) {
44 | return `${value / 16}rem`;
45 | }
46 |
47 | export function responsiveFontSizes({ sm, md, lg }) {
48 | return {
49 | '@media (min-width:600px)': {
50 | fontSize: pxToRem(sm),
51 | },
52 | '@media (min-width:900px)': {
53 | fontSize: pxToRem(md),
54 | },
55 | '@media (min-width:1200px)': {
56 | fontSize: pxToRem(lg),
57 | },
58 | };
59 | }
60 |
61 | // ----------------------------------------------------------------------
62 |
63 | function useWidth() {
64 | const theme = useTheme();
65 |
66 | const keys = [...theme.breakpoints.keys].reverse();
67 |
68 | return (
69 | keys.reduce((output, key) => {
70 | // eslint-disable-next-line react-hooks/rules-of-hooks
71 | const matches = useResponsive('up', key);
72 |
73 | return !output && matches ? key : output;
74 | }, null) || 'xs'
75 | );
76 | }
77 |
--------------------------------------------------------------------------------
/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); // ~3 days by codingmonks 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/s3.js:
--------------------------------------------------------------------------------
1 | import AWS from 'aws-sdk';
2 | import { AWS_ACCESS_KEY, AWS_S3_REGION, AWS_SECRET_ACCESS_KEY } from '../config';
3 |
4 | const S3 = new AWS.S3({
5 | signatureVersion: 'v4',
6 | region: AWS_S3_REGION,
7 | accessKeyId: AWS_ACCESS_KEY, // YOUR AWS ACCESS KEY
8 | secretAccessKey: AWS_SECRET_ACCESS_KEY, // YOUR AWS SECRET ACCESS KEY
9 | });
10 |
11 |
12 | export default S3;
--------------------------------------------------------------------------------
/src/utils/truncate.js:
--------------------------------------------------------------------------------
1 | function truncateString(str, num) {
2 | if (str.length > num) {
3 | return str.slice(0, num) + "...";
4 | } else {
5 | return str;
6 | }
7 | }
8 |
9 | export default truncateString;
10 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------