├── public ├── _redirects ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── manifest.json └── index.html ├── src ├── images │ ├── auth │ │ ├── login.png │ │ └── register.png │ ├── avatar_default.jpg │ ├── newsList │ │ ├── cover_1.jpg │ │ ├── cover_2.jpg │ │ ├── cover_3.jpg │ │ ├── cover_4.jpg │ │ └── cover_5.jpg │ ├── illustration_avatar.png │ ├── ic_flag_fr.svg │ ├── ic_flag_en.svg │ ├── ic_flag_de.svg │ └── 404.svg ├── setupTests.js ├── App.css ├── components │ ├── Dashboard │ │ ├── DashCardBox.js │ │ ├── DashCard.js │ │ ├── DashCardHeader.js │ │ ├── TasksItem.js │ │ ├── Tasks.js │ │ ├── OrderTimelineItem.js │ │ ├── InfoCards.js │ │ ├── SocialTrafficItem.js │ │ ├── NewsUpdateItem.js │ │ ├── SocialTraffic.js │ │ ├── ConversionRate.js │ │ ├── ChartCurrentSubject.js │ │ ├── OrderTimeline.js │ │ ├── CurrentVisits.js │ │ ├── ChartSiteVisits.js │ │ ├── NewsUpdate.js │ │ └── InfoCard.js │ ├── UI │ │ ├── MenuArrow.js │ │ └── IntroModal.js │ ├── Product │ │ ├── DrawerContentCard.js │ │ ├── ProductList.js │ │ ├── ProductPrice.js │ │ ├── ProductColorPreview.js │ │ ├── FixedCartCount.js │ │ ├── DrawerContent.js │ │ ├── ProductListItem.js │ │ ├── ProductActionBar.js │ │ └── DrawerContentBody.js │ ├── Blog │ │ ├── BlogSocialInfo.js │ │ ├── BlogHeader.js │ │ ├── BlogFilters.js │ │ └── Blogs.js │ ├── AuthPages │ │ ├── SectionDivider.js │ │ ├── LeftPanel.js │ │ ├── ButtonGroup.js │ │ ├── FormRegister.js │ │ └── FormLogin.js │ ├── User │ │ ├── UserHeader.js │ │ ├── TableToolbar.js │ │ ├── UserTableHead.js │ │ ├── UserMore.js │ │ └── UserTable.js │ ├── Drawer │ │ └── CustomListItem.js │ └── MainHeader │ │ ├── SelectLanguage.js │ │ ├── UserMenu.js │ │ └── Notifications.js ├── layout │ ├── AuthLayout.js │ ├── DashboardLayout.js │ ├── MainHeader.js │ └── SideDrawer.js ├── reportWebVitals.js ├── index.js ├── pages │ ├── Blog.js │ ├── Products.js │ ├── User.js │ ├── 404.js │ ├── Dashboard.js │ ├── Login.js │ └── Register.js ├── theme.js ├── App.js ├── routes.js └── api │ ├── userApi.js │ ├── blogApi.js │ └── productApi.js ├── .gitignore ├── package.json └── README.md /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/images/auth/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/src/images/auth/login.png -------------------------------------------------------------------------------- /src/images/auth/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/src/images/auth/register.png -------------------------------------------------------------------------------- /src/images/avatar_default.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/src/images/avatar_default.jpg -------------------------------------------------------------------------------- /src/images/newsList/cover_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/src/images/newsList/cover_1.jpg -------------------------------------------------------------------------------- /src/images/newsList/cover_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/src/images/newsList/cover_2.jpg -------------------------------------------------------------------------------- /src/images/newsList/cover_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/src/images/newsList/cover_3.jpg -------------------------------------------------------------------------------- /src/images/newsList/cover_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/src/images/newsList/cover_4.jpg -------------------------------------------------------------------------------- /src/images/newsList/cover_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/src/images/newsList/cover_5.jpg -------------------------------------------------------------------------------- /src/images/illustration_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TutulDevs/mui-practice/HEAD/src/images/illustration_avatar.png -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | ::-webkit-scrollbar { 2 | width: 2px; 3 | } 4 | 5 | /* Track */ 6 | ::-webkit-scrollbar-track { 7 | background: rgb(223, 223, 223); 8 | } 9 | 10 | /* Handle */ 11 | ::-webkit-scrollbar-thumb { 12 | background: rgb(0, 171, 85); 13 | } 14 | 15 | /* Handle on hover */ 16 | ::-webkit-scrollbar-thumb:hover { 17 | background: purple; 18 | } 19 | -------------------------------------------------------------------------------- /src/components/Dashboard/DashCardBox.js: -------------------------------------------------------------------------------- 1 | import { Box } from "@material-ui/core"; 2 | 3 | const DashCardBox = (props) => { 4 | return ( 5 | 11 | {props.children} 12 | 13 | ); 14 | }; 15 | 16 | export default DashCardBox; 17 | -------------------------------------------------------------------------------- /src/layout/AuthLayout.js: -------------------------------------------------------------------------------- 1 | import { Box } from "@mui/system"; 2 | 3 | const AuthLayout = (props) => { 4 | return ( 5 | 14 | {props.children} 15 | 16 | ); 17 | }; 18 | 19 | export default AuthLayout; 20 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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/components/UI/MenuArrow.js: -------------------------------------------------------------------------------- 1 | import { StopSharp } from "@material-ui/icons"; 2 | import { styled } from "@material-ui/styles"; 3 | 4 | const Arrow = styled(StopSharp)(({ theme }) => ({ 5 | top: `-${theme.spacing(2)}px`, 6 | right: theme.spacing(1.75), 7 | position: "absolute", 8 | transform: "rotate(45deg)", 9 | color: theme.palette.green.darker, 10 | })); 11 | 12 | const MenuArrow = () => ; 13 | 14 | export default MenuArrow; 15 | -------------------------------------------------------------------------------- /src/images/ic_flag_fr.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Dashboard/DashCard.js: -------------------------------------------------------------------------------- 1 | import { Card } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | 4 | const CardStyle = styled(Card)(({ theme }) => ({ 5 | borderRadius: theme.spacing(1.5), 6 | boxShadow: 7 | "rgb(145 158 171 / 24%) 0px 0px 2px 0px, rgb(145 158 171 / 24%) 0px 16px 32px -4px", 8 | })); 9 | 10 | const DashCard = (props) => { 11 | return {props.children}; 12 | }; 13 | 14 | export default DashCard; 15 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/components/Product/DrawerContentCard.js: -------------------------------------------------------------------------------- 1 | import { Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | 5 | // section Header 6 | const SectionHeaderStyle = styled(Typography)(({ theme }) => ({ 7 | fontSize: 18, 8 | fontWeight: 500, 9 | marginTop: theme.spacing(2.25), 10 | marginBottom: theme.spacing(1), 11 | })); 12 | 13 | const DrawerContentCard = ({ title, children }) => { 14 | return ( 15 | <> 16 | {title} 17 | 18 | {children} 19 | 20 | ); 21 | }; 22 | 23 | export default DrawerContentCard; 24 | -------------------------------------------------------------------------------- /src/components/Dashboard/DashCardHeader.js: -------------------------------------------------------------------------------- 1 | import { CardHeader } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | 4 | const CardHeaderStyle = styled(CardHeader)(({ theme }) => ({ 5 | padding: "24px 24px 0 24px", 6 | 7 | "& .MuiCardHeader-title": { 8 | fontSize: theme.spacing(2.5), 9 | fontWeight: 600, 10 | }, 11 | "& .MuiCardHeader-subheader": { 12 | fontSize: theme.spacing(2), 13 | fontWeight: 300, 14 | color: theme.palette.gray.main, 15 | }, 16 | })); 17 | 18 | const DashCardHeader = (props) => { 19 | return ; 20 | }; 21 | 22 | export default DashCardHeader; 23 | -------------------------------------------------------------------------------- /src/components/Product/ProductList.js: -------------------------------------------------------------------------------- 1 | import { Grid } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { products } from "../../api/productApi"; 4 | import ProductListItem from "./ProductListItem"; 5 | 6 | // grid style 7 | const GridStyle = styled(Grid)(({ theme }) => ({ 8 | marginTop: theme.spacing(3), 9 | })); 10 | 11 | const ProductList = () => { 12 | return ( 13 | 14 | {products.map((product) => ( 15 | 16 | 17 | 18 | ))} 19 | 20 | ); 21 | }; 22 | 23 | export default ProductList; 24 | -------------------------------------------------------------------------------- /src/components/Product/ProductPrice.js: -------------------------------------------------------------------------------- 1 | import { Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | 4 | // style 5 | const TextStyle = styled(Typography)(({ theme }) => ({ 6 | fontSize: 18, 7 | "& .disabledText": { 8 | fontSize: 16, 9 | color: theme.palette.text.secondary, 10 | marginRight: theme.spacing(0.5), 11 | textDecoration: "line-through", 12 | }, 13 | })); 14 | 15 | const ProductPrice = ({ price, priceSale }) => { 16 | return ( 17 | 18 | {priceSale && ( 19 | ${priceSale.toFixed(2)} 20 | )} 21 | 22 | ${price.toFixed(2)} 23 | 24 | ); 25 | }; 26 | 27 | export default ProductPrice; 28 | -------------------------------------------------------------------------------- /src/components/Blog/BlogSocialInfo.js: -------------------------------------------------------------------------------- 1 | import { Typography } from "@material-ui/core"; 2 | import { Box } from "@mui/system"; 3 | 4 | // icon 5 | import { FaCommentDots, FaEye, FaShare } from "react-icons/fa"; 6 | 7 | const BlogSocialInfo = ({ comments, views, shares, color }) => { 8 | return ( 9 | 13 | 14 | {comments} 15 | 16 | 17 | {views} 18 | 19 | 20 | {shares} 21 | 22 | 23 | ); 24 | }; 25 | 26 | export default BlogSocialInfo; 27 | -------------------------------------------------------------------------------- /src/components/AuthPages/SectionDivider.js: -------------------------------------------------------------------------------- 1 | import { Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | 5 | const SectionDividerStyle = styled(Box)(({ theme }) => ({ 6 | display: "flex", 7 | justifyContent: "center", 8 | alignItems: "center", 9 | 10 | "& .line": { 11 | flex: 1, 12 | height: 2, 13 | backgroundColor: theme.palette.gray.light, 14 | }, 15 | "& .MuiTypography-button": { 16 | padding: `0 ${theme.spacing(2)}px`, 17 | }, 18 | })); 19 | 20 | const SectionDivider = () => { 21 | return ( 22 | 23 | 24 | 25 | {" "} 26 | OR{" "} 27 | 28 | 29 | 30 | ); 31 | }; 32 | 33 | export default SectionDivider; 34 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | import CssBaseline from "@material-ui/core/CssBaseline"; 5 | import { ThemeProvider } from "@material-ui/core/styles"; 6 | import { BrowserRouter } from "react-router-dom"; 7 | import App from "./App"; 8 | import theme from "./theme"; 9 | import reportWebVitals from "./reportWebVitals"; 10 | 11 | ReactDOM.render( 12 | 13 | {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */} 14 | 15 | 16 | 17 | 18 | , 19 | document.getElementById("root") 20 | ); 21 | 22 | // If you want to start measuring performance in your app, pass a function 23 | // to log results (for example: reportWebVitals(console.log)) 24 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 25 | reportWebVitals(); 26 | -------------------------------------------------------------------------------- /src/pages/Blog.js: -------------------------------------------------------------------------------- 1 | import { Container } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | 4 | // components 5 | import BlogHeader from "../components/Blog/BlogHeader"; 6 | import BlogFilters from "../components/Blog/BlogFilters"; 7 | import Blogs from "../components/Blog/Blogs"; 8 | import { Helmet } from "react-helmet"; 9 | 10 | // style 11 | const ContainerStyle = styled(Container)(({ theme }) => ({ 12 | padding: 0, 13 | paddingTop: theme.spacing(2), 14 | })); 15 | 16 | const Blog = () => { 17 | return ( 18 | <> 19 | {/* Helmet */} 20 | 21 | Blogs | MUI Dash 22 | 23 | 24 | 25 | {/* Header */} 26 | 27 | 28 | {/* Blog Filters */} 29 | 30 | 31 | {/* All blogs */} 32 | 33 | 34 | 35 | ); 36 | }; 37 | 38 | export default Blog; 39 | -------------------------------------------------------------------------------- /src/components/User/UserHeader.js: -------------------------------------------------------------------------------- 1 | import { Button, Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | import { BiPlus } from "react-icons/bi"; 5 | 6 | // style 7 | const BoxStyle = styled(Box)(({ theme }) => ({ 8 | margin: `${theme.spacing(2)}px 0`, 9 | display: "flex", 10 | justifyContent: "space-between", 11 | alignItems: "center", 12 | 13 | "& .MuiTypography-root": { 14 | fontSize: 30, 15 | fontWeight: 500, 16 | }, 17 | 18 | "& .MuiButton-root": { 19 | fontSize: 10, 20 | fontWeight: 600, 21 | color: theme.palette.common.white, 22 | backgroundColor: theme.palette.success.main, 23 | boxShadow: theme.shadows[5], 24 | 25 | "&:hover": { 26 | boxShadow: "none", 27 | }, 28 | }, 29 | })); 30 | 31 | const UserHeader = () => { 32 | return ( 33 | 34 | User 35 | 36 | 39 | 40 | ); 41 | }; 42 | 43 | export default UserHeader; 44 | -------------------------------------------------------------------------------- /src/components/AuthPages/LeftPanel.js: -------------------------------------------------------------------------------- 1 | import { Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | 5 | // styles 6 | const LeftPaneStyle = styled(Box)(({ theme }) => ({ 7 | display: "flex", 8 | flexDirection: "column", 9 | justifyContent: "center", 10 | padding: `${theme.spacing(2)}px ${theme.spacing(3)}px`, 11 | borderRadius: theme.spacing(2), 12 | boxShadow: 13 | "rgb(145 158 171 / 24%) 0px 0px 2px 0px, rgb(145 158 171 / 24%) 0px 16px 32px -4px", 14 | 15 | "& .MuiTypography-h3": { 16 | fontSize: 30, 17 | fontWeight: 500, 18 | marginBottom: 48, 19 | }, 20 | "& img": { 21 | alignSelf: "center", 22 | width: "100%", 23 | maxWidth: 400, 24 | objectFit: "cover", 25 | }, 26 | 27 | [theme.breakpoints.down("sm")]: { 28 | display: "none", 29 | }, 30 | })); 31 | 32 | const LeftPanel = ({ title, img, imgAlt }) => { 33 | return ( 34 | 35 | {title} 36 | 37 | 38 | 39 | ); 40 | }; 41 | 42 | export default LeftPanel; 43 | -------------------------------------------------------------------------------- /src/components/Product/ProductColorPreview.js: -------------------------------------------------------------------------------- 1 | import { Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | 5 | // style 6 | const WrapperStyle = styled(Box)(() => ({ 7 | display: "flex", 8 | justifyContent: "flex-end", 9 | alignItems: "center", 10 | })); 11 | 12 | const DotStyle = styled(Box)(({ theme }) => ({ 13 | marginLeft: "-4px", 14 | width: theme.spacing(2), 15 | height: theme.spacing(2), 16 | border: `2px solid ${theme.palette.common.white}`, 17 | borderRadius: "50%", 18 | boxShadow: `inset -1px 1px 2px rgba(0,0,0,0.25)`, 19 | })); 20 | 21 | const ProductColorPreview = ({ colors, limit }) => { 22 | const showColors = colors.slice(0, limit); 23 | const moreColors = colors.length - limit; 24 | 25 | return ( 26 | 27 | {/* Dots */} 28 | {showColors.map((color, idx) => ( 29 | 30 | ))} 31 | 32 | {colors.length > limit && ( 33 | +{moreColors} 34 | )} 35 | 36 | ); 37 | }; 38 | 39 | export default ProductColorPreview; 40 | -------------------------------------------------------------------------------- /src/components/Dashboard/TasksItem.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Checkbox, FormControlLabel } from "@mui/material"; 4 | 5 | const TasksItem = ({ id, status, label }) => { 6 | const [checked, setChecked] = useState(status); 7 | const handleChange = (e) => setChecked(e.target.checked); 8 | 9 | // style 10 | const FormControlLabelStyle = styled(FormControlLabel)(({ theme }) => ({ 11 | "& .MuiCheckbox-root": { 12 | transition: "all 0.5s ease", 13 | color: theme.palette.success.main, 14 | "&:hover": { 15 | backgroundColor: theme.palette.green.lighter, 16 | }, 17 | }, 18 | 19 | "& .Mui-checked ": { 20 | color: `${theme.palette.green.darker} !important`, 21 | }, 22 | 23 | "& .MuiFormControlLabel-label": { 24 | color: checked ? theme.palette.text.disabled : "inherit", 25 | textDecoration: checked ? "line-through" : null, 26 | }, 27 | })); 28 | 29 | return ( 30 | } 33 | label={label} 34 | /> 35 | ); 36 | }; 37 | 38 | export default TasksItem; 39 | -------------------------------------------------------------------------------- /src/images/ic_flag_en.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/theme.js: -------------------------------------------------------------------------------- 1 | import { createTheme } from "@material-ui/core"; 2 | 3 | // custom theme 4 | const theme = createTheme({ 5 | palette: { 6 | primary: { 7 | main: "#556cd6", 8 | }, 9 | background: { 10 | default: "#ffffff", 11 | }, 12 | green: { 13 | main: "rgb(0, 82, 73)", 14 | light: "rgb(200, 250, 205)", 15 | lighter: "rgba(0, 171, 85, 0.08)", 16 | dark: "rgb(0, 123, 85)", 17 | darker: "rgb(0, 171, 85)", 18 | }, 19 | blue: { 20 | main: "rgb(4, 41, 122)", 21 | dark: "rgb(12, 83, 183)", 22 | light: "rgb(208, 242, 255)", 23 | }, 24 | yellow: { 25 | main: "rgb(122, 79, 1)", 26 | dark: "rgb(183, 129, 3)", 27 | light: "rgb(255, 247, 205)", 28 | }, 29 | maroon: { 30 | main: "rgb(122, 12, 46)", 31 | dark: "rgb(183, 33, 54)", 32 | light: "rgb(255, 231, 217)", 33 | }, 34 | gray: { 35 | main: "rgb(99, 115, 129)", 36 | light: "rgb(223, 223, 223)", 37 | lighter: "rgb(244, 246, 248)", 38 | }, 39 | red: { 40 | main: "rgb(255, 72, 66)", 41 | }, 42 | mixins: { 43 | toolbar: { 44 | minHeight: 64, 45 | }, 46 | }, 47 | }, 48 | }); 49 | 50 | export default theme; 51 | -------------------------------------------------------------------------------- /src/images/ic_flag_de.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Dashboard/Tasks.js: -------------------------------------------------------------------------------- 1 | import { FormGroup } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import DashCard from "./DashCard"; 4 | import DashCardHeader from "./DashCardHeader"; 5 | import TasksItem from "./TasksItem"; 6 | 7 | // style 8 | const FormGroupStyle = styled(FormGroup)(({ theme }) => ({ 9 | padding: theme.spacing(3), 10 | paddingBottom: theme.spacing(2), 11 | })); 12 | 13 | // list of tasks 14 | const TASK_LIST = [ 15 | { id: "chk_1", label: "Create FireStone Logo", status: false }, 16 | { id: "chk_2", label: "Add SCSS and JS files if required", status: false }, 17 | { id: "chk_3", label: "Stakeholder Meeting", status: false }, 18 | { id: "chk_4", label: "Scoping & Estimations", status: true }, 19 | { id: "chk_5", label: "Sprint Showcase", status: false }, 20 | ]; 21 | 22 | const Tasks = () => { 23 | return ( 24 | 25 | 26 | 27 | 28 | {TASK_LIST.map((el) => ( 29 | 35 | ))} 36 | 37 | 38 | ); 39 | }; 40 | 41 | export default Tasks; 42 | -------------------------------------------------------------------------------- /src/components/AuthPages/ButtonGroup.js: -------------------------------------------------------------------------------- 1 | import { Button } from "@material-ui/core"; 2 | import { Box } from "@mui/system"; 3 | 4 | // icons 5 | import { RiFacebookFill, RiGoogleFill, RiTwitterFill } from "react-icons/ri"; 6 | 7 | // icons list 8 | const items = [ 9 | { 10 | title: "Google", 11 | icon: , 12 | color: "rgb(223, 62, 48)", 13 | }, 14 | { 15 | title: "Facebook", 16 | icon: , 17 | color: "rgb(24, 119, 242)", 18 | }, 19 | { 20 | title: "Twitter", 21 | icon: , 22 | color: "rgb(28, 156, 234)", 23 | }, 24 | ]; 25 | 26 | const AuthButtonGroup = () => { 27 | return ( 28 | 36 | {items.map(({ title, icon, color }) => ( 37 | 50 | ))} 51 | 52 | ); 53 | }; 54 | 55 | export default AuthButtonGroup; 56 | -------------------------------------------------------------------------------- /src/components/Dashboard/OrderTimelineItem.js: -------------------------------------------------------------------------------- 1 | import { Typography } from "@material-ui/core"; 2 | import { 3 | TimelineConnector, 4 | TimelineContent, 5 | TimelineDot, 6 | TimelineItem, 7 | TimelineSeparator, 8 | } from "@material-ui/lab"; 9 | import { styled } from "@material-ui/styles"; 10 | 11 | const OrderTimelineItem = ({ type, title, time, isLast }) => { 12 | const TimelineDotStyle = styled(TimelineDot)(({ theme }) => ({ 13 | boxShadow: "none", 14 | backgroundColor: 15 | type === "order1" 16 | ? theme.palette.primary.main 17 | : type === "order2" 18 | ? theme.palette.success.main 19 | : type === "order3" 20 | ? theme.palette.warning.main 21 | : type === "order4" 22 | ? theme.palette.info.main 23 | : "salmon", 24 | })); 25 | 26 | return ( 27 | 28 | 29 | 30 | {isLast ? null : } 31 | 32 | 33 | {title} 34 | 35 | {time} 36 | 37 | 38 | 39 | ); 40 | }; 41 | 42 | export default OrderTimelineItem; 43 | -------------------------------------------------------------------------------- /src/components/Dashboard/InfoCards.js: -------------------------------------------------------------------------------- 1 | import { Box, styled } from "@material-ui/core"; 2 | 3 | // etc 4 | import InfoCard from "./InfoCard"; 5 | import { 6 | AiFillAndroid, 7 | AiFillApple, 8 | AiFillWindows, 9 | AiFillBug, 10 | } from "react-icons/ai"; 11 | 12 | // info card item list 13 | const items = [ 14 | { 15 | id: "green", 16 | icon: , 17 | count: "714k", 18 | title: "Weekly Sales", 19 | }, 20 | { id: "blue", icon: , count: "1.35m", title: "New Users" }, 21 | { 22 | id: "yellow", 23 | icon: , 24 | count: "1.72m", 25 | title: "Item Orders", 26 | }, 27 | { id: "maroon", icon: , count: "234", title: "Bug Reports" }, 28 | ]; 29 | 30 | const ContainerStyle = styled(Box)(({ theme }) => ({ 31 | marginTop: theme.spacing(7.5), 32 | display: "grid", 33 | gap: theme.spacing(3), 34 | gridTemplateColumns: "repeat( auto-fit, minmax(200px, 1fr) )", 35 | })); 36 | 37 | const InfoCards = () => { 38 | return ( 39 | 40 | {items.map((el) => ( 41 | 48 | ))} 49 | 50 | ); 51 | }; 52 | 53 | export default InfoCards; 54 | -------------------------------------------------------------------------------- /src/components/Product/FixedCartCount.js: -------------------------------------------------------------------------------- 1 | import { Badge, Button } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { HiShoppingCart } from "react-icons/hi"; 4 | 5 | // style 6 | const ButtonStyle = styled(Button)(({ theme }) => ({ 7 | backgroundColor: theme.palette.common.white, 8 | padding: "14px 0px 8px 0px", 9 | border: `1px solid ${theme.palette.gray.light}`, 10 | borderRight: 0, 11 | borderRadius: `16px 0 0 16px`, 12 | boxShadow: `rgb(145 158 171 / 24%) 0px 0px 2px 0px, rgb(145 158 171 / 24%) 0px 20px 40px -4px`, 13 | transition: "all 0.3s ease", 14 | 15 | position: "fixed", 16 | right: 0, 17 | top: `${theme.mixins.toolbar.minHeight * 2}px`, 18 | zIndex: 999, 19 | 20 | "&:hover": { 21 | boxShadow: "none", 22 | backgroundColor: "inherit", 23 | opacity: 0.75, 24 | }, 25 | 26 | // badge 27 | "& .MuiBadge-badge": { 28 | backgroundColor: theme.palette.red.main, 29 | color: theme.palette.common.white, 30 | top: "-3px", 31 | fontSize: theme.spacing(1.75), 32 | }, 33 | })); 34 | 35 | const FixedCartCounter = ({ itemAmout }) => { 36 | return ( 37 | 38 | 39 | 40 | 41 | 42 | ); 43 | }; 44 | 45 | export default FixedCartCounter; 46 | -------------------------------------------------------------------------------- /src/pages/Products.js: -------------------------------------------------------------------------------- 1 | import { Container, Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Helmet } from "react-helmet"; 4 | 5 | // components 6 | import FixedCartCounter from "../components/Product/FixedCartCount"; 7 | import ProductActionBar from "../components/Product/ProductActionBar"; 8 | import ProductList from "../components/Product/ProductList"; 9 | 10 | // style 11 | const ContainerStyle = styled(Container)(({ theme }) => ({ 12 | padding: 0, 13 | paddingTop: theme.spacing(2), 14 | 15 | // product header 16 | // h3 17 | "& .productHeader": { 18 | fontSize: 30, 19 | fontWeight: 500, 20 | }, 21 | })); 22 | 23 | const Products = () => { 24 | return ( 25 | <> 26 | {/* Helmet */} 27 | 28 | Products | MUI Dash 29 | 30 | 31 | {/* Fixed counter for cart */} 32 | 33 | 34 | {/* main container */} 35 | 36 | {/* Header */} 37 | 38 | Products 39 | 40 | 41 | {/* Action bar */} 42 | 43 | 44 | {/* Products list */} 45 | 46 | 47 | 48 | ); 49 | }; 50 | 51 | export default Products; 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mui-practice", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.4.1", 7 | "@emotion/styled": "^11.3.0", 8 | "@material-ui/core": "^4.12.3", 9 | "@material-ui/lab": "^4.0.0-alpha.60", 10 | "@mui/icons-material": "^5.0.0-rc.0", 11 | "@mui/material": "^5.0.0-rc.0", 12 | "@testing-library/jest-dom": "^5.14.1", 13 | "@testing-library/react": "^11.2.7", 14 | "@testing-library/user-event": "^12.8.3", 15 | "apexcharts": "^3.28.1", 16 | "react": "^17.0.2", 17 | "react-apexcharts": "^1.3.9", 18 | "react-dom": "^17.0.2", 19 | "react-helmet": "^6.1.0", 20 | "react-hook-form": "^7.15.3", 21 | "react-icons": "^4.2.0", 22 | "react-router-dom": "^5.2.0", 23 | "react-scripts": "4.0.3", 24 | "web-vitals": "^1.1.2" 25 | }, 26 | "scripts": { 27 | "start": "react-scripts start", 28 | "build": "react-scripts build", 29 | "test": "react-scripts test", 30 | "eject": "react-scripts eject" 31 | }, 32 | "eslintConfig": { 33 | "extends": [ 34 | "react-app", 35 | "react-app/jest" 36 | ] 37 | }, 38 | "browserslist": { 39 | "production": [ 40 | ">0.2%", 41 | "not dead", 42 | "not op_mini all" 43 | ], 44 | "development": [ 45 | "last 1 chrome version", 46 | "last 1 firefox version", 47 | "last 1 safari version" 48 | ] 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/components/Blog/BlogHeader.js: -------------------------------------------------------------------------------- 1 | import { Button, Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | import { AiOutlinePlus } from "react-icons/ai"; 5 | 6 | // style 7 | const BoxStyle = styled(Box)(({ theme }) => ({ 8 | // root 9 | display: "flex", 10 | justifyContent: "space-between", 11 | alignItems: "center", 12 | 13 | // h3 14 | "& .MuiTypography-h3": { 15 | fontSize: 30, 16 | fontWeight: 500, 17 | }, 18 | 19 | // button style 20 | "& .MuiButton-contained": { 21 | backgroundColor: theme.palette.success.main, 22 | color: theme.palette.common.white, 23 | fontWeight: 600, 24 | textTransform: "capitalize", 25 | padding: `${theme.spacing(0.75)}px ${theme.spacing(2)}px`, 26 | boxShadow: `rgb(0 171 85 / 24%) 0px 8px 16px 0px`, 27 | "&:hover": { 28 | backgroundColor: theme.palette.success.dark, 29 | boxShadow: "none", 30 | }, 31 | }, 32 | 33 | // text after the + icon 34 | "& .text": { 35 | marginLeft: theme.spacing(0.5), 36 | }, 37 | })); 38 | 39 | const BlogHeader = () => { 40 | return ( 41 | 42 | Blog 43 | 44 | 48 | 49 | ); 50 | }; 51 | 52 | export default BlogHeader; 53 | -------------------------------------------------------------------------------- /src/components/Dashboard/SocialTrafficItem.js: -------------------------------------------------------------------------------- 1 | import { styled } from "@material-ui/styles"; 2 | import { Box } from "@mui/system"; 3 | import { Typography } from "@material-ui/core"; 4 | 5 | const SocialTrafficItem = ({ icon, amount, title }) => { 6 | const BoxItemStyle = styled(Box)(({ theme }) => ({ 7 | border: `1px solid ${theme.palette.gray.light}`, 8 | borderRadius: 8, 9 | minHeight: 150, 10 | padding: theme.spacing(1), 11 | display: "flex", 12 | flexDirection: "column", 13 | justifyContent: "center", 14 | alignItems: "center", 15 | 16 | "& .MuiTypography-h5": { 17 | color: 18 | title === "Facebook" 19 | ? "rgb(24, 119, 242)" 20 | : title === "Google" 21 | ? "rgb(223, 62, 48)" 22 | : title === "LinkedIn" 23 | ? "rgb(0, 96, 151)" 24 | : title === "Twitter" 25 | ? "rgb(28, 156, 234)" 26 | : "salmon", 27 | }, 28 | 29 | "& .MuiTypography-h6": { 30 | fontSize: 20, 31 | fontWeight: 600, 32 | }, 33 | "& .MuiTypography-caption": { 34 | color: theme.palette.text.secondary, 35 | }, 36 | })); 37 | 38 | return ( 39 | 40 | 41 | {icon} 42 | 43 | 44 | 45 | {amount} 46 | 47 | 48 | {title} 49 | 50 | ); 51 | }; 52 | 53 | export default SocialTrafficItem; 54 | -------------------------------------------------------------------------------- /src/components/Dashboard/NewsUpdateItem.js: -------------------------------------------------------------------------------- 1 | import { Link as RouterLink } from "react-router-dom"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Avatar, Box, Typography, Link } from "@material-ui/core"; 4 | 5 | const BoxContainerStyle = styled(Box)(({ theme }) => ({ 6 | display: "flex", 7 | 8 | "& .MuiAvatar-root": { 9 | borderRadius: theme.spacing(1), 10 | marginTop: theme.spacing(0.75), 11 | }, 12 | "& h3": { 13 | fontWeight: 500, 14 | }, 15 | "& .MuiTypography-caption": { 16 | color: theme.palette.text.secondary, 17 | }, 18 | "& .MuiTypography-body2": { 19 | backgroundColor: theme.palette.gray.lighter, 20 | color: theme.palette.gray.main, 21 | fontWeight: 500, 22 | lineHeight: 1, 23 | display: "inline-block", 24 | borderRadius: 25, 25 | padding: "4px 6px", 26 | }, 27 | })); 28 | 29 | const NewsUpdateItem = (props) => { 30 | return ( 31 | 32 | 33 | 34 | 35 | 36 | 37 | {props.title} 38 | 39 | 40 | 41 | 42 | {props.subtitle} 43 | 44 | 45 | {props.postingTime} 46 | 47 | 48 | ); 49 | }; 50 | 51 | export default NewsUpdateItem; 52 | -------------------------------------------------------------------------------- /src/components/Dashboard/SocialTraffic.js: -------------------------------------------------------------------------------- 1 | import { styled } from "@material-ui/styles"; 2 | import { Box } from "@mui/system"; 3 | import DashCard from "./DashCard"; 4 | import DashCardHeader from "./DashCardHeader"; 5 | import SocialTrafficItem from "./SocialTrafficItem"; 6 | 7 | // icons 8 | import { 9 | RiFacebookFill, 10 | RiGoogleFill, 11 | RiLinkedinFill, 12 | RiTwitterFill, 13 | } from "react-icons/ri"; 14 | 15 | const BoxContainerStyle = styled(Box)(({ theme }) => ({ 16 | padding: theme.spacing(3), 17 | display: "grid", 18 | gap: theme.spacing(2), 19 | gridTemplateColumns: `repeat(2, 1fr)`, 20 | })); 21 | 22 | // items list 23 | const list = [ 24 | { 25 | title: "Facebook", 26 | amount: "47.10k", 27 | icon: , 28 | }, 29 | { 30 | title: "Google", 31 | amount: "65.60k", 32 | icon: , 33 | }, 34 | { 35 | title: "LinkedIn", 36 | amount: "84.14k", 37 | icon: , 38 | }, 39 | { 40 | title: "Twitter", 41 | amount: "15.70k", 42 | icon: , 43 | }, 44 | ]; 45 | 46 | const SocialTraffic = () => { 47 | return ( 48 | 49 | 50 | 51 | 52 | {list.map((el) => ( 53 | 59 | ))} 60 | 61 | 62 | ); 63 | }; 64 | 65 | export default SocialTraffic; 66 | -------------------------------------------------------------------------------- /src/pages/User.js: -------------------------------------------------------------------------------- 1 | import { Container, useMediaQuery } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | import { Helmet } from "react-helmet"; 5 | import UserHeader from "../components/User/UserHeader"; 6 | import UserTable from "../components/User/UserTable"; 7 | 8 | // box style 9 | const BoxStyle = styled(Box)(({ theme }) => ({ 10 | margin: `${theme.spacing(4)}px auto`, 11 | borderRadius: theme.spacing(2), 12 | boxShadow: `rgb(145 158 171 / 24%) 0px 0px 2px 0px, rgb(145 158 171 / 24%) 0px 16px 32px -4px`, 13 | overflow: "hidden", 14 | 15 | //border: "2px solid teal", 16 | })); 17 | 18 | const User = () => { 19 | // media queries 20 | const less400 = useMediaQuery("(max-width:400px)"); 21 | const less480 = useMediaQuery("(max-width:480px)"); 22 | const less600 = useMediaQuery("(max-width:600px)"); 23 | const less768 = useMediaQuery("(max-width:768px)"); 24 | 25 | return ( 26 | <> 27 | 28 | Users | MUI Dash 29 | 30 | 31 | 32 | {/* User Header */} 33 | 34 | 35 | {/* User Table */} 36 | 37 | 50 | 51 | 52 | 53 | 54 | ); 55 | }; 56 | 57 | export default User; 58 | -------------------------------------------------------------------------------- /src/components/Drawer/CustomListItem.js: -------------------------------------------------------------------------------- 1 | import { NavLink } from "react-router-dom"; 2 | import { styled, ListItem, ListItemIcon, Typography } from "@material-ui/core"; 3 | import { makeStyles } from "@material-ui/styles"; 4 | 5 | const useStyles = makeStyles((theme) => ({ 6 | activeClass: { 7 | color: `${theme.palette.green.darker} !important`, 8 | backgroundColor: theme.palette.green.lighter, 9 | borderRight: `3px solid ${theme.palette.green.darker}`, 10 | "& .MuiTypography-subtitle1": { 11 | fontWeight: 600, 12 | }, 13 | }, 14 | })); 15 | 16 | const ListItemStyle = styled(ListItem)(() => ({ 17 | padding: 0, 18 | })); 19 | 20 | const CustomLinkStyle = styled(NavLink)(({ theme }) => ({ 21 | width: "100%", 22 | padding: "8px 8px 8px 32px", 23 | display: "flex", 24 | alignItems: "center", 25 | textDecoration: "none", 26 | color: theme.palette.gray.main, 27 | 28 | "& .MuiListItemIcon-root": { 29 | minWidth: "auto", 30 | marginRight: theme.spacing(2), 31 | color: "inherit", 32 | fontSize: 18, 33 | }, 34 | "& h6": { 35 | fontSize: 15, 36 | fontWeight: 400, 37 | }, 38 | })); 39 | 40 | const CustomListItem = (props) => { 41 | const classes = useStyles(); 42 | 43 | return ( 44 | 45 | 46 | {props.icon} 47 | 48 | 49 | {props.title} 50 | 51 | 52 | 53 | ); 54 | }; 55 | 56 | export default CustomListItem; 57 | 58 | // 59 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { Redirect, Route, Switch } from "react-router-dom"; 3 | import "./App.css"; 4 | 5 | // components 6 | import DashboardLayout from "./layout/DashboardLayout"; 7 | import Dashboard from "./pages/Dashboard"; 8 | import ErrorPage from "./pages/404"; 9 | import Login from "./pages/Login"; 10 | import Register from "./pages/Register"; 11 | import Blog from "./pages/Blog"; 12 | import Products from "./pages/Products"; 13 | import User from "./pages/User"; 14 | import IntroModal from "./components/UI/IntroModal"; 15 | 16 | const App = () => { 17 | const [showModal, setShowModal] = useState(false); 18 | const toggleShowModal = () => setShowModal(!showModal); 19 | 20 | // show on mount 21 | useEffect(() => setShowModal(true), []); 22 | 23 | return ( 24 | <> 25 | {/* Modal */} 26 | 27 | 28 | {/* Dashboard Layout */} 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ); 51 | }; 52 | 53 | export default App; 54 | -------------------------------------------------------------------------------- /src/layout/DashboardLayout.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { makeStyles } from "@material-ui/styles"; 3 | import { Box, styled, Toolbar } from "@material-ui/core"; 4 | 5 | import MainHeader from "./MainHeader"; 6 | import SideDrawer from "./SideDrawer"; 7 | 8 | const useStyles = makeStyles((theme) => ({ 9 | drawerPaper: { 10 | width: drawerWidth, 11 | display: "grid", 12 | gridTemplateRows: "auto auto 1fr auto", 13 | }, 14 | })); 15 | 16 | const MainStyle = styled("main")(({ theme }) => ({ 17 | flexGrow: 1, 18 | minHeight: "100vh", 19 | padding: theme.spacing(2.5), 20 | })); 21 | 22 | const DashboardLayout = (props) => { 23 | // window width 24 | const { window } = props; 25 | const [toggleMenu, setToggleMenu] = useState(false); 26 | const classes = useStyles(); 27 | 28 | // toggle drawer 29 | const handleToggleDrawer = () => setToggleMenu(!toggleMenu); 30 | const handleToggleClose = () => setToggleMenu(false); 31 | 32 | // I don't know the work of container yet 33 | const container = 34 | window !== undefined ? () => window().document.body : undefined; 35 | 36 | return ( 37 | 38 | {/* App Bar */} 39 | 40 | 41 | {/* Drawer */} 42 | 48 | 49 | {/* Content */} 50 | 51 | 52 | {/* Main parts */} 53 | {props.children} 54 | 55 | 56 | ); 57 | }; 58 | 59 | export default DashboardLayout; 60 | 61 | export const drawerWidth = 240; 62 | -------------------------------------------------------------------------------- /src/components/Dashboard/ConversionRate.js: -------------------------------------------------------------------------------- 1 | import ReactApexChart from "react-apexcharts"; 2 | import DashCard from "./DashCard"; 3 | import DashCardBox from "./DashCardBox"; 4 | import DashCardHeader from "./DashCardHeader"; 5 | 6 | const SERIES_DATA = [ 7 | { 8 | data: [400, 430, 448, 470, 540, 580, 690, 1100, 1200, 1380], 9 | }, 10 | ]; 11 | 12 | const chartOptions = { 13 | chart: { toolbar: { show: false } }, 14 | //markers: { show: false }, 15 | xaxis: { 16 | categories: [ 17 | "Italy", 18 | "Japan", 19 | "China", 20 | "Canada", 21 | "France", 22 | "Germany", 23 | "South Korea", 24 | "Netherlands", 25 | "United States", 26 | "United Kingdom", 27 | ], 28 | }, 29 | plotOptions: { 30 | bar: { 31 | barHeight: "25%", 32 | borderRadius: 4, 33 | horizontal: true, 34 | colors: { 35 | ranges: [ 36 | { 37 | color: "#ff0", 38 | }, 39 | ], 40 | }, 41 | }, 42 | }, 43 | dataLabels: { enabled: false }, 44 | tooltip: { 45 | marker: { show: false }, 46 | 47 | x: { show: false }, 48 | y: { 49 | title: { 50 | formatter: (sname) => `#${sname}`, 51 | }, 52 | }, 53 | }, 54 | }; 55 | 56 | const ConversionRate = () => { 57 | return ( 58 | 59 | 63 | 64 | 65 | 71 | 72 | 73 | ); 74 | }; 75 | 76 | export default ConversionRate; 77 | -------------------------------------------------------------------------------- /src/components/Dashboard/ChartCurrentSubject.js: -------------------------------------------------------------------------------- 1 | import { styled } from "@material-ui/styles"; 2 | import DashCard from "./DashCard"; 3 | import DashCardHeader from "./DashCardHeader"; 4 | import { Box } from "@mui/system"; 5 | import ReactApexChart from "react-apexcharts"; 6 | 7 | const DivStyle = styled(Box)(({ theme }) => ({ 8 | paddingTop: theme.spacing(1), 9 | "& .apexcharts-legend": { 10 | borderTop: `1px solid ${theme.palette.gray.light}`, 11 | padding: `20px 4px 4px 4px`, 12 | }, 13 | })); 14 | 15 | // series data for radar 16 | const SERIES_DATA = [ 17 | { 18 | name: "Series 1", 19 | data: [80, 50, 30, 40, 100, 20], 20 | }, 21 | { 22 | name: "Series 2", 23 | data: [20, 30, 40, 80, 20, 80], 24 | }, 25 | { 26 | name: "Series 3", 27 | data: [44, 76, 78, 13, 43, 10], 28 | }, 29 | ]; 30 | 31 | const ChartCurrentSubject = () => { 32 | const chartOptions = { 33 | chart: { toolbar: { show: false } }, 34 | stroke: { width: 2 }, 35 | legend: { 36 | position: "bottom", 37 | horizontalAlign: "center", 38 | }, 39 | markers: { size: 0 }, 40 | xaxis: { 41 | categories: [ 42 | "English", 43 | "History", 44 | "Physics", 45 | "Geography", 46 | "Chinese", 47 | "Math", 48 | ], 49 | }, 50 | fill: { 51 | opacity: 0.5, 52 | }, 53 | }; 54 | 55 | return ( 56 | 57 | 58 | 59 | 60 | 66 | 67 | 68 | ); 69 | }; 70 | 71 | export default ChartCurrentSubject; 72 | -------------------------------------------------------------------------------- /src/components/Dashboard/OrderTimeline.js: -------------------------------------------------------------------------------- 1 | import { Timeline } from "@material-ui/lab"; 2 | import { styled } from "@material-ui/styles"; 3 | import DashCard from "./DashCard"; 4 | import DashCardHeader from "./DashCardHeader"; 5 | import OrderTimelineItem from "./OrderTimelineItem"; 6 | 7 | const TimelineStyle = styled(Timeline)(({ theme }) => ({ 8 | paddingLeft: theme.spacing(6), 9 | 10 | "& .MuiTimelineItem-missingOppositeContent:before": { 11 | display: "none", 12 | }, 13 | "& .MuiTimelineContent-root": { 14 | paddingTop: 3, 15 | }, 16 | })); 17 | 18 | // timeline list 19 | const timelineList = [ 20 | { 21 | title: "1983, orders, $4220", 22 | time: "08 Aug 2021 21:53", 23 | type: "order1", 24 | }, 25 | { 26 | title: "12 Invoices have been paid", 27 | time: "29 Jun 2021 08:40", 28 | type: "order2", 29 | }, 30 | { 31 | title: "Order #37745 from September", 32 | time: "02 Aug 2021 04:21", 33 | type: "order3", 34 | }, 35 | { 36 | title: "New order placed #XF-2356", 37 | time: "18 Apr 2021 21:51", 38 | type: "order4", 39 | }, 40 | { 41 | title: "New order placed #XF-2346", 42 | time: "03 Oct 2020 04:27", 43 | type: "order5", 44 | }, 45 | ]; 46 | 47 | const OrderTimeline = () => { 48 | return ( 49 | 50 | 51 | 52 | 53 | {timelineList.map((item, index) => ( 54 | 61 | ))} 62 | 63 | 64 | ); 65 | }; 66 | 67 | export default OrderTimeline; 68 | -------------------------------------------------------------------------------- /src/routes.js: -------------------------------------------------------------------------------- 1 | import DashboardLayout from "./layout/DashboardLayout"; 2 | import AuthLayout from "./layout/AuthLayout"; 3 | 4 | // components 5 | import Dashboard from "./pages/Dashboard"; 6 | import ErrorPage from "./pages/404"; 7 | import Login from "./pages/Login"; 8 | import Register from "./pages/Register"; 9 | import Blog from "./pages/Blog"; 10 | import Products from "./pages/Products"; 11 | import User from "./pages/User"; 12 | 13 | const PageRoutes = [ 14 | // default 15 | { 16 | path: "/", 17 | component: DashboardLayout, 18 | routes: [{ path: "/", component: Dashboard }], 19 | }, 20 | // auth 21 | { 22 | path: "/auth", 23 | component: AuthLayout, 24 | routes: [ 25 | { path: "/auth/login", component: Login }, 26 | { path: "/auth/register", component: Register }, 27 | ], 28 | }, 29 | // dash 30 | { 31 | path: "/dashboard", 32 | component: DashboardLayout, 33 | routes: [ 34 | { path: "/dashboard/app", component: Dashboard }, 35 | { path: "/dashboard/user", component: User }, 36 | { path: "/dashboard/products", component: Products }, 37 | { path: "/dashboard/blog", component: Blog }, 38 | ], 39 | }, 40 | // error 41 | { path: "*", component: ErrorPage }, 42 | ]; 43 | 44 | export default PageRoutes; 45 | 46 | /* 47 | 48 | Tried this code in the App.js but it didn't work. 49 | 50 | /// 51 | import PageRoutes from "./routes"; 52 | console.log(PageRoutes); 53 | 54 | const RouteWithSubRoutes = (route) => { 55 | return ( 56 | } 60 | /> 61 | ); 62 | }; 63 | 64 | /// 65 | 66 | const App = () => { 67 | return ( 68 | 69 | {PageRoutes.map((route, idx) => ( 70 | 71 | ))} 72 | 73 | ); 74 | }; 75 | 76 | 77 | */ 78 | -------------------------------------------------------------------------------- /src/components/Dashboard/CurrentVisits.js: -------------------------------------------------------------------------------- 1 | import ReactApexChart from "react-apexcharts"; 2 | import { styled, useTheme } from "@material-ui/styles"; 3 | import DashCard from "./DashCard"; 4 | import DashCardHeader from "./DashCardHeader"; 5 | import { Box } from "@mui/system"; 6 | 7 | const DivStyle = styled(Box)(({ theme }) => ({ 8 | paddingTop: theme.spacing(1), 9 | "& .apexcharts-legend": { 10 | borderTop: `1px solid ${theme.palette.gray.light}`, 11 | padding: `${theme.spacing(2.5)}px ${theme.spacing(1)}px`, 12 | }, 13 | "& .apexcharts-tooltip": { 14 | backgroundColor: theme.palette.common.white, 15 | color: theme.palette.common.black, 16 | border: `1px solid ${theme.palette.gray.light}`, 17 | borderRadius: 25, 18 | paddingTop: 2, 19 | }, 20 | })); 21 | 22 | const SERIES_DATA = [4344, 5435, 1443, 4443]; 23 | 24 | const CurrentVisits = () => { 25 | const theme = useTheme(); 26 | 27 | const chartOptions = { 28 | labels: ["America", "Asia", "Europe", "Africa"], 29 | stroke: { colors: [theme.palette.background.paper] }, 30 | colors: [ 31 | theme.palette.success.main, 32 | theme.palette.info.main, 33 | theme.palette.warning.light, 34 | theme.palette.error.main, 35 | ], 36 | legend: { 37 | position: "bottom", 38 | horizontalAlign: "center", 39 | }, 40 | dataLabels: { enabled: true, dropShadow: { enabled: false } }, 41 | tooltip: { 42 | fillSeriesColor: false, 43 | y: { 44 | title: { 45 | formatter: (seriesName) => `#${seriesName}`, 46 | }, 47 | }, 48 | }, 49 | }; 50 | 51 | return ( 52 | 53 | 54 | 55 | 56 | 62 | 63 | 64 | ); 65 | }; 66 | 67 | export default CurrentVisits; 68 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import { Typography, Button } from "@material-ui/core"; 2 | import { Box } from "@mui/system"; 3 | import { styled } from "@material-ui/styles"; 4 | import { Link as RouterLink } from "react-router-dom"; 5 | import image from "../images/404.svg"; 6 | import { Helmet } from "react-helmet"; 7 | 8 | // style 9 | const BoxStyle = styled(Box)(({ theme }) => ({ 10 | maxWidth: theme.breakpoints.values.sm, 11 | minHeight: `calc(100vh - ${theme.mixins.toolbar.minHeight * 2}px)`, 12 | margin: "0 auto", 13 | textAlign: "center", 14 | display: "flex", 15 | flexDirection: "column", 16 | justifyContent: "center", 17 | alignItems: "center", 18 | 19 | "& .MuiTypography-paragraph": { 20 | marginTop: 20, 21 | marginBottom: 20, 22 | }, 23 | "& img": { 24 | width: "100%", 25 | maxWidth: 400, 26 | objectFit: "cover", 27 | }, 28 | "& .MuiButton-root": { 29 | backgroundColor: theme.palette.green.darker, 30 | color: "#fff", 31 | marginTop: 40, 32 | }, 33 | 34 | [theme.breakpoints.down("sm")]: { 35 | "& .MuiTypography-h3": { fontSize: 30, fontWeight: 500 }, 36 | }, 37 | })); 38 | 39 | const ErrorPage = () => { 40 | return ( 41 | <> 42 | {/* Helmet */} 43 | 44 | 404 | MUI Dash 45 | 46 | 47 | 48 | Sorry, page not found! 49 | 50 | 51 | Sorry, we couldn’t find the page you’re looking for. Perhaps you’ve 52 | mistyped the URL? Be sure to check your spelling. 53 | 54 | 55 | 404 Error 56 | 57 | 66 | 67 | 68 | ); 69 | }; 70 | 71 | export default ErrorPage; 72 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | 28 | 32 | 33 | MUI Dash 34 | 35 | 36 | 37 |
38 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/components/User/TableToolbar.js: -------------------------------------------------------------------------------- 1 | import { 2 | IconButton, 3 | TextField, 4 | Toolbar, 5 | Tooltip, 6 | Typography, 7 | } from "@material-ui/core"; 8 | import { styled } from "@material-ui/styles"; 9 | import { RiDeleteBinFill, RiFilter3Fill } from "react-icons/ri"; 10 | 11 | const TableToolbar = ({ numSelected }) => { 12 | // style 13 | const ToolbarStyle = styled(Toolbar)(({ theme }) => ({ 14 | paddingTop: theme.spacing(2), 15 | paddingBottom: theme.spacing(2), 16 | borderRadius: "8px 8px 0 0", 17 | backgroundColor: numSelected > 0 ? theme.palette.green.light : "inherit", 18 | 19 | display: "flex", 20 | justifyContent: "space-between", 21 | alignItems: "center", 22 | 23 | // input style 24 | "& .MuiInputBase-root": { 25 | borderRadius: theme.spacing(1), 26 | }, 27 | "& label.Mui-focused": { 28 | color: theme.palette.success.main, 29 | }, 30 | "& .MuiInput-underline:after": { 31 | borderBottomColor: theme.palette.success.main, 32 | }, 33 | "& .MuiOutlinedInput-root": { 34 | "&.Mui-focused fieldset": { 35 | borderColor: theme.palette.success.main, 36 | }, 37 | }, 38 | 39 | // selectedText 40 | "& .selectedText": { 41 | fontSize: 18, 42 | fontWeight: numSelected > 0 ? 500 : 400, 43 | color: numSelected > 0 ? theme.palette.green.dark : "inherit", 44 | }, 45 | })); 46 | 47 | return ( 48 | 49 | {/* input search or selected items length */} 50 | {numSelected > 0 ? ( 51 | 56 | {numSelected} selected 57 | 58 | ) : ( 59 | 60 | )} 61 | 62 | {/* icons */} 63 | {numSelected > 0 ? ( 64 | 65 | 66 | 67 | 68 | 69 | ) : ( 70 | 71 | 72 | 73 | 74 | 75 | )} 76 | 77 | ); 78 | }; 79 | 80 | export default TableToolbar; 81 | -------------------------------------------------------------------------------- /src/api/userApi.js: -------------------------------------------------------------------------------- 1 | function createData(name, company, role, verified, status) { 2 | return { 3 | name, 4 | company, 5 | role, 6 | verified, 7 | status, 8 | }; 9 | } 10 | 11 | // helper const 12 | const [yes, no, banned, active] = ["Yes", "No", "Banned", "Active"]; 13 | const [uxd, uud, fsd, bd, pm, fed] = [ 14 | "UX Designer", 15 | "UI/UX Designer", 16 | "Full Stack Designer", 17 | "Backend Developer", 18 | "Project Manager", 19 | "Front End Developer", 20 | ]; 21 | 22 | export const userData = [ 23 | createData("Herman Reilly", "Mitchell-Predovic", pm, yes, banned), 24 | createData("Isabel Rolfson", "McKenzie-Smith", fsd, no, banned), 25 | createData("Katie Lehner", "Stehr Inc", fed, yes, active), 26 | createData("Kelly Gutmann", "Moore Group", uxd, yes, banned), 27 | createData("Lee Block", "Sipes & Padberg", fed, yes, banned), 28 | createData( 29 | "Alison Kovacek Jr.", 30 | "Bednar, Lindgren and Schmidt", 31 | uud, 32 | yes, 33 | banned 34 | ), 35 | createData("Mr. Desiree Koelpin", "Medhurst-Ziemann", pm, yes, banned), 36 | createData("Mrs. Carolyn Stiedemann", "Schuppe-Windler", pm, yes, banned), 37 | createData("Mrs. Casey Hauck", "Kuvalis LLC", bd, yes, banned), 38 | createData("Alma Bartoletti DDS", "Blick-Bernier", fsd, yes, active), 39 | createData("Archie Bechtelar", "Greenfelder-Leuschke", uud, yes, active), 40 | createData("Carol Price", "Spencer Group", uud, yes, banned), 41 | createData("Dr. Ellen Gislason", "Dickinson-Aufderhar", bd, no, banned), 42 | createData("Duane Beatty", "Blanda-Wiza", fsd, no, active), 43 | createData("Dwight Cummings V", "Baumbach", uud, yes, banned), 44 | 45 | createData("Lois Dach", "Schimmel-Swift", uxd, no, active), 46 | createData("Louis O'Reilly II", "Walsh LLC", bd, no, banned), 47 | createData("Merle Kshlerin", "Hickle, Ullrich and Mueller", uud, yes, banned), 48 | 49 | createData("Nathaniel Abernathy", "Kuhn-Boehm", uxd, no, banned), 50 | createData("Nellie Schimmel", "Haley, Paucek and Goodwin", fsd, yes, banned), 51 | createData("Wilbert McClure", "Strosin-Wisoky", fsd, yes, banned), 52 | createData("Nicole Johnson PhD", "Ward-Jacobi", fsd, no, banned), 53 | createData("Van Dibbert DVM", "Bergnaum-Schowalter", fsd, no, active), 54 | createData("Viola Muller I", "Simonis-Runolfsson", fed, yes, banned), 55 | ]; 56 | -------------------------------------------------------------------------------- /src/api/blogApi.js: -------------------------------------------------------------------------------- 1 | // list of the items/blogs 2 | export const blogList = [ 3 | { 4 | dateTime: "01 June 2021", 5 | title: 6 | "Tesla Cybertruck-inspired camper trailer for Tesla fans who can’t just wait for the truck!", 7 | path: "#", 8 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 9 | }, 10 | { 11 | dateTime: "05 November 2020", 12 | title: "Whiteboard Templates By Industry Leaders", 13 | path: "#", 14 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 15 | }, 16 | { 17 | dateTime: "01 February 2020", 18 | title: "Designify Agency Landing Page Design", 19 | path: "#", 20 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 21 | }, 22 | { 23 | dateTime: "03 February 2020", 24 | title: "✨What is Done is Done ✨", 25 | path: "#", 26 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 27 | }, 28 | { 29 | dateTime: "05 February 2020", 30 | title: "Fresh Prince", 31 | path: "#", 32 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 33 | }, 34 | { 35 | dateTime: "05 February 2020", 36 | title: "Six Socks Studio", 37 | path: "#", 38 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 39 | }, 40 | { 41 | dateTime: "05 February 2020", 42 | title: 43 | "vincenzo de cotiis’ crossing over showcases a research on contamination", 44 | path: "#", 45 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 46 | }, 47 | { 48 | dateTime: "05 February 2020", 49 | title: "Simple, Great Looking Animations in Your Project | Video Tutorial", 50 | path: "#", 51 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 52 | }, 53 | { 54 | dateTime: "05 February 2020", 55 | title: "40 Free Serif Fonts for Digital Designers", 56 | path: "#", 57 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 58 | }, 59 | { 60 | dateTime: "05 February 2020", 61 | title: "Examining the Evolution of the Typical Web Design Client", 62 | path: "#", 63 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 64 | }, 65 | { 66 | dateTime: "05 February 2020", 67 | title: "Katie Griffin loves making that homey art", 68 | path: "#", 69 | social: { comment: "76.46k", views: "90.58k", share: "77.89k" }, 70 | }, 71 | ]; 72 | -------------------------------------------------------------------------------- /src/components/User/UserTableHead.js: -------------------------------------------------------------------------------- 1 | import { 2 | Checkbox, 3 | TableCell, 4 | TableHead, 5 | TableRow, 6 | TableSortLabel, 7 | } from "@material-ui/core"; 8 | import { Box } from "@mui/system"; 9 | import { visuallyHidden } from "@mui/utils"; 10 | 11 | const headCells = [ 12 | { 13 | id: "name", 14 | label: "Name", 15 | }, 16 | { 17 | id: "company", 18 | label: "Company", 19 | }, 20 | { 21 | id: "role", 22 | label: "Role", 23 | }, 24 | { 25 | id: "verified", 26 | label: "Verified", 27 | }, 28 | { 29 | id: "status", 30 | label: "Status", 31 | }, 32 | { 33 | id: "menu", 34 | label: "", 35 | }, 36 | ]; 37 | 38 | const UserTableHead = (props) => { 39 | const { 40 | onSelectAllClick, 41 | order, 42 | orderBy, 43 | numSelected, 44 | rowCount, 45 | onRequestSort, 46 | } = props; 47 | 48 | // sort 49 | const createSortHandler = (property) => (e) => onRequestSort(e, property); 50 | 51 | return ( 52 | 53 | 54 | {/* ck box */} 55 | 56 | 0 && numSelected < rowCount} 59 | checked={rowCount > 0 && numSelected === rowCount} 60 | onChange={onSelectAllClick} 61 | inputProps={{ 62 | "aria-label": "select all users", 63 | }} 64 | /> 65 | 66 | 67 | {/* rest of the cells */} 68 | {headCells.map((cell) => ( 69 | 73 | 78 | {cell.label} 79 | 80 | {/* hidden box */} 81 | {orderBy === cell.id ? ( 82 | 83 | {order === "desc" ? "sorted descending" : "sorted ascending"} 84 | 85 | ) : null} 86 | 87 | 88 | ))} 89 | 90 | 91 | ); 92 | }; 93 | 94 | export default UserTableHead; 95 | -------------------------------------------------------------------------------- /src/components/User/UserMore.js: -------------------------------------------------------------------------------- 1 | import { useRef, useState } from "react"; 2 | import { Link as RouterLink } from "react-router-dom"; 3 | import { 4 | IconButton, 5 | ListItemIcon, 6 | ListItemText, 7 | Menu, 8 | MenuItem, 9 | } from "@material-ui/core"; 10 | import { styled } from "@material-ui/styles"; 11 | 12 | // icons 13 | import { MoreVert } from "@mui/icons-material"; 14 | import { RiDeleteBin6Line } from "react-icons/ri"; 15 | import { MdModeEdit } from "react-icons/md"; 16 | 17 | // style 18 | const MenuStyle = styled(Menu)(({ theme }) => ({ 19 | // li 20 | "& .MuiMenuItem-root": { 21 | color: theme.palette.text.secondary, 22 | }, 23 | 24 | // icons 25 | "& .MuiListItemIcon-root": { 26 | color: theme.palette.text.secondary, 27 | minWidth: 0, 28 | marginRight: theme.spacing(3), 29 | }, 30 | })); 31 | 32 | const UserMore = () => { 33 | const ref = useRef(null); 34 | const [showMenu, setShowMenu] = useState(false); 35 | 36 | return ( 37 | <> 38 | {/* Button */} 39 | setShowMenu(true)} 44 | > 45 | 46 | 47 | 48 | {/* Menu */} 49 | setShowMenu(false)} 53 | PaperProps={{ sx: { width: 200, maxWidth: "100%" } }} 54 | anchorOrigin={{ vertical: "top", horizontal: "right" }} 55 | transformOrigin={{ vertical: "top", horizontal: "right" }} 56 | > 57 | setShowMenu(false)}> 58 | 59 | 60 | 61 | 62 | 66 | 67 | 68 | setShowMenu(false)} 72 | > 73 | 74 | 75 | 76 | 77 | 81 | 82 | 83 | 84 | ); 85 | }; 86 | 87 | export default UserMore; 88 | -------------------------------------------------------------------------------- /src/components/MainHeader/SelectLanguage.js: -------------------------------------------------------------------------------- 1 | import { 2 | IconButton, 3 | styled, 4 | Menu, 5 | MenuItem, 6 | ListItemText, 7 | } from "@material-ui/core"; 8 | import { withStyles } from "@material-ui/styles"; 9 | 10 | // images 11 | import EN_Flag from "../../images/ic_flag_en.svg"; 12 | import DE_Flag from "../../images/ic_flag_de.svg"; 13 | import FR_Flag from "../../images/ic_flag_fr.svg"; 14 | 15 | // Menu styles 16 | const StyledMenu = withStyles((theme) => ({ 17 | paper: { 18 | minWidth: 175, 19 | boxShadow: `0 2px 10px -5px ${theme.palette.green.darker}`, 20 | }, 21 | }))((props) => ( 22 | 35 | )); 36 | 37 | const StyledMenuItem = withStyles((theme) => ({ 38 | root: { 39 | "&:active": { 40 | backgroundColor: theme.palette.green.light, 41 | }, 42 | "& .MuiListItemText-primary": { 43 | marginLeft: theme.spacing(2.5), 44 | fontSize: theme.spacing(2.25), 45 | }, 46 | }, 47 | }))(MenuItem); 48 | 49 | const IconButtonStyle = styled(IconButton)(({ theme }) => ({ 50 | padding: "12px 9px", 51 | "& img": { 52 | width: theme.spacing(3), 53 | }, 54 | })); 55 | 56 | // Language list 57 | const languages = [ 58 | { src: EN_Flag, alt: "English" }, 59 | { src: DE_Flag, alt: "German" }, 60 | { src: FR_Flag, alt: "French" }, 61 | ]; 62 | 63 | const LanguageSelector = (props) => { 64 | return ( 65 | <> 66 | 71 | English 72 | 73 | 74 | 81 | {languages.map((el) => ( 82 | 83 | {el.alt} 84 | 85 | 86 | 87 | ))} 88 | 89 | 90 | ); 91 | }; 92 | 93 | export default LanguageSelector; 94 | -------------------------------------------------------------------------------- /src/components/Product/DrawerContent.js: -------------------------------------------------------------------------------- 1 | import { Button, IconButton, Toolbar, Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | import { GrFormClose } from "react-icons/gr"; 5 | import { MdClearAll } from "react-icons/md"; 6 | import DrawerContentBody from "./DrawerContentBody"; 7 | 8 | // container style 9 | const ContainerStyle = styled(Box)(({ theme }) => ({ 10 | width: 300, 11 | height: "calc(100vh - 14px)", 12 | display: "grid", 13 | gap: theme.spacing(1), 14 | gridTemplateRows: `${theme.mixins.toolbar.minHeight}px 1fr ${theme.mixins.toolbar.minHeight}px`, 15 | })); 16 | 17 | // toolbar 18 | const ToolbarStyle = styled(Toolbar)(({ theme }) => ({ 19 | display: "flex", 20 | justifyContent: "space-between", 21 | alignItems: "center", 22 | borderBottom: "1px solid #eee", 23 | 24 | "& .MuiIconButton-root": { 25 | padding: theme.spacing(0.75), 26 | }, 27 | })); 28 | 29 | // content 30 | const ContentBoxStyle = styled(Box)(({ theme }) => ({ 31 | padding: "8px 20px", 32 | overflowY: "auto", 33 | 34 | // checkbox style 35 | "& .MuiCheckbox-root": { 36 | color: theme.palette.text.disabled, 37 | }, 38 | "& .Mui-checked": { 39 | color: theme.palette.success.main, 40 | }, 41 | "& .MuiIconButton-colorSecondary:hover": { 42 | backgroundColor: theme.palette.green.lighter, 43 | }, 44 | })); 45 | 46 | const DrawerContent = ({ closeDrawer }) => { 47 | return ( 48 | 49 | {/* Header */} 50 | 51 | 52 | Filters 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | {/* Main Content */} 61 | 62 | 63 | 64 | 65 | {/* Footer */} 66 | 67 | 80 | 81 | 82 | ); 83 | }; 84 | 85 | export default DrawerContent; 86 | -------------------------------------------------------------------------------- /src/pages/Dashboard.js: -------------------------------------------------------------------------------- 1 | import { Grid, Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Helmet } from "react-helmet"; 4 | import ChartCurrentSubject from "../components/Dashboard/ChartCurrentSubject"; 5 | import ChartSiteVisits from "../components/Dashboard/ChartSiteVisits"; 6 | import ConversionRate from "../components/Dashboard/ConversionRate"; 7 | import CurrentVisits from "../components/Dashboard/CurrentVisits"; 8 | import InfoCards from "../components/Dashboard/InfoCards"; 9 | import NewsUpdate from "../components/Dashboard/NewsUpdate"; 10 | import OrderTimeline from "../components/Dashboard/OrderTimeline"; 11 | import SocialTraffic from "../components/Dashboard/SocialTraffic"; 12 | import Tasks from "../components/Dashboard/Tasks"; 13 | 14 | // grid container style 15 | const GridContainerStyle = styled(Grid)(({ theme }) => ({ 16 | marginTop: theme.spacing(2), 17 | marginBottom: theme.spacing(2), 18 | })); 19 | 20 | const Dashboard = () => { 21 | return ( 22 | <> 23 | 24 | Dashboard | MUI Dash 25 | 26 | 27 | 28 | Hi, Welcome in MUI Dash. 29 | 30 | 31 | {/* Info Cards */} 32 | 33 | 34 | 35 | {/* Site visits chart */} 36 | 37 | 38 | 39 | 40 | {/* Current Visits */} 41 | 42 | 43 | 44 | 45 | {/* Conversion Rates */} 46 | 47 | 48 | 49 | 50 | {/* Current Subject */} 51 | 52 | 53 | 54 | 55 | {/* News Update */} 56 | 57 | 58 | 59 | 60 | {/* Order Timeline */} 61 | 62 | 63 | 64 | 65 | {/* Traffic by Site */} 66 | 67 | 68 | 69 | 70 | {/* Traffic by Site */} 71 | 72 | 73 | 74 | 75 | 76 | ); 77 | }; 78 | 79 | export default Dashboard; 80 | -------------------------------------------------------------------------------- /src/components/Dashboard/ChartSiteVisits.js: -------------------------------------------------------------------------------- 1 | import Chart from "react-apexcharts"; 2 | import DashCard from "./DashCard"; 3 | import DashCardHeader from "./DashCardHeader"; 4 | import DashCardBox from "./DashCardBox"; 5 | 6 | // chart data series 7 | const SERIES = [ 8 | { 9 | name: "Team A", 10 | type: "column", 11 | data: [23, 11, 22, 27, 13, 22, 37, 21, 44, 22, 30], 12 | }, 13 | { 14 | name: "Team B", 15 | type: "area", 16 | data: [44, 55, 41, 67, 22, 43, 21, 41, 56, 27, 43], 17 | }, 18 | { 19 | name: "Team C", 20 | type: "line", 21 | data: [30, 25, 36, 30, 45, 35, 64, 52, 59, 36, 39], 22 | }, 23 | ]; 24 | 25 | const ChartSiteVisits = () => { 26 | const options = { 27 | chart: { 28 | id: "basic-bar", 29 | stacked: false, 30 | toolbar: { 31 | show: false, 32 | }, 33 | }, 34 | plotOptions: { 35 | bar: { 36 | columnWidth: "15%", 37 | borderRadius: 4, 38 | }, 39 | }, 40 | stroke: { curve: "smooth", width: [0, 2, 3] }, 41 | markers: { size: 0 }, 42 | fill: { 43 | opacity: [0.85, 0.25, 1], 44 | gradient: { 45 | inverseColors: false, 46 | shade: "light", 47 | type: "vertical", 48 | opacityFrom: 0.85, 49 | opacityTo: 0.55, 50 | stops: [0, 100, 100, 100], 51 | }, 52 | }, 53 | xaxis: { 54 | type: "datetime", 55 | }, 56 | labels: [ 57 | "01/01/2003", 58 | "02/01/2003", 59 | "03/01/2003", 60 | "04/01/2003", 61 | "05/01/2003", 62 | "06/01/2003", 63 | "07/01/2003", 64 | "08/01/2003", 65 | "09/01/2003", 66 | "10/01/2003", 67 | "11/01/2003", 68 | ], 69 | tooltip: { 70 | shared: true, 71 | intersect: false, 72 | x: { show: false }, 73 | y: { 74 | formatter: (val) => 75 | val !== undefined ? `${val.toFixed(0)} visits` : val, 76 | }, 77 | style: { 78 | fontFamily: "inherit", 79 | }, 80 | }, 81 | legend: { 82 | position: "top", 83 | horizontalAlign: "right", 84 | }, 85 | }; 86 | 87 | return ( 88 | 89 | 93 | 94 | 95 | 96 | 97 | 98 | ); 99 | }; 100 | 101 | export default ChartSiteVisits; 102 | -------------------------------------------------------------------------------- /src/components/UI/IntroModal.js: -------------------------------------------------------------------------------- 1 | import { Button, Link, Modal, Typography } from "@material-ui/core"; 2 | import { Box } from "@mui/system"; 3 | 4 | const IntroModal = ({ showModal, onToggle }) => { 5 | return ( 6 | 12 | 30 | 31 | Hi there 👋{" "} 32 | 33 | 34 | 35 | Thanks for checking this site. This is a cloned dashboard from 36 | Material-UI to practice MUI. 37 | 38 | 39 | The main focus of this project was the UI. I know there are some bugs 40 | in it. If you can suggest me any way, I'll appreciate it very much. 41 | 42 | 43 | {/* 44 | PS: I'm looking for an entry level job. If you've any opportunity, 45 | please knock me. 🙏 46 | */} 47 | 48 | {/* Buttons */} 49 | 58 | 69 | 70 | 78 | 79 | 80 | 81 | ); 82 | }; 83 | 84 | export default IntroModal; 85 | -------------------------------------------------------------------------------- /src/components/Product/ProductListItem.js: -------------------------------------------------------------------------------- 1 | import { Card, Link, Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | import { Link as RouteLink } from "react-router-dom"; 5 | import ProductColorPreview from "./ProductColorPreview"; 6 | import ProductPrice from "./ProductPrice"; 7 | 8 | // card style 9 | const CardStyle = styled(Card)(({ theme }) => ({ 10 | borderRadius: theme.spacing(2), 11 | 12 | boxShadow: `rgb(145 158 171 / 24%) 0px 0px 2px 0px, rgb(145 158 171 / 24%) 0px 4px 8px -4px`, 13 | 14 | "&:hover": { 15 | boxShadow: `rgb(145 158 171 / 24%) 0px 0px 2px 0px, rgb(145 158 171 / 24%) 0px 16px 32px -4px`, 16 | }, 17 | })); 18 | 19 | const ProductListItem = (props) => { 20 | const { title, price, priceSale, productImage, status, colors } = 21 | props.product; 22 | 23 | // label style 24 | const LabelStyle = styled("label")(({ theme }) => ({ 25 | fontWeight: 600, 26 | color: "white", 27 | backgroundColor: 28 | status === "sale" ? theme.palette.error.main : theme.palette.success.main, 29 | padding: "4px 6px", 30 | borderRadius: theme.spacing(1), 31 | zIndex: 9, 32 | position: "absolute", 33 | top: theme.spacing(2), 34 | right: theme.spacing(2), 35 | textTransform: "uppercase", 36 | })); 37 | 38 | return ( 39 | 40 | {/* Image with Label */} 41 | 42 | {status && {status}} 43 | 44 | 56 | 57 | 58 | {/* bottom of the card */} 59 | 60 | 61 | 62 | {title} 63 | 64 | 65 | 66 | {/* Price & Color box */} 67 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | ); 82 | }; 83 | 84 | export default ProductListItem; 85 | -------------------------------------------------------------------------------- /src/components/Dashboard/NewsUpdate.js: -------------------------------------------------------------------------------- 1 | import { Link as RouterLink } from "react-router-dom"; 2 | //import { styled } from "@material-ui/styles"; 3 | import { Box, Button, Divider } from "@material-ui/core"; 4 | import DashCard from "./DashCard"; 5 | import DashCardHeader from "./DashCardHeader"; 6 | 7 | // icon & images 8 | import { GrFormNext } from "react-icons/gr"; 9 | import coverImg_1 from "../../images/newsList/cover_1.jpg"; 10 | import coverImg_2 from "../../images/newsList/cover_2.jpg"; 11 | import coverImg_3 from "../../images/newsList/cover_3.jpg"; 12 | import coverImg_4 from "../../images/newsList/cover_4.jpg"; 13 | import coverImg_5 from "../../images/newsList/cover_5.jpg"; 14 | import NewsUpdateItem from "./NewsUpdateItem"; 15 | 16 | // News List 17 | const loremText = `Quisquam sunt ipsa nihil ratione. Dolorum earum occaecati et sequi et eius asperiore...`; 18 | 19 | const newsList = [ 20 | { 21 | title: "Customer Optimization Architect", 22 | subtitle: loremText, 23 | photo: coverImg_1, 24 | postingTime: "about 12 hours", 25 | }, 26 | { 27 | title: "Human Creative Representative", 28 | subtitle: loremText, 29 | photo: coverImg_2, 30 | postingTime: "about 2 hours", 31 | }, 32 | { 33 | title: "Dynamic Identity Officer", 34 | subtitle: loremText, 35 | photo: coverImg_3, 36 | postingTime: "about 7 hours", 37 | }, 38 | { 39 | title: "Chief Program Planner", 40 | subtitle: loremText, 41 | photo: coverImg_4, 42 | postingTime: "about 12 hours", 43 | }, 44 | { 45 | title: "Senior Implementation Manager", 46 | subtitle: loremText, 47 | photo: coverImg_5, 48 | postingTime: "about 10 hours", 49 | }, 50 | ]; 51 | 52 | const NewsUpdate = () => { 53 | return ( 54 | 55 | 56 | 57 | {/* Main Content */} 58 | 59 | 65 | {newsList.map((news) => ( 66 | 73 | ))} 74 | 75 | 76 | {/* footer */} 77 | 78 | 79 | 86 | 95 | 96 | 97 | ); 98 | }; 99 | 100 | export default NewsUpdate; 101 | -------------------------------------------------------------------------------- /src/components/Product/ProductActionBar.js: -------------------------------------------------------------------------------- 1 | import { 2 | Button, 3 | Drawer, 4 | MenuItem, 5 | TextField, 6 | Typography, 7 | } from "@material-ui/core"; 8 | import { styled } from "@material-ui/styles"; 9 | import { Box } from "@mui/system"; 10 | import { useState } from "react"; 11 | import { BiFilter } from "react-icons/bi"; 12 | import DrawerContent from "./DrawerContent"; 13 | 14 | const ButtonStyle = styled(Button)(({ theme }) => ({ 15 | fontWeight: 500, 16 | textTransform: "capitalize", 17 | padding: `4px 12px`, 18 | borderRadius: theme.spacing(1.25), 19 | 20 | "& .text": { 21 | fontWeight: 500, 22 | }, 23 | })); 24 | 25 | const TextFieldStyle = styled(TextField)(({ theme }) => ({ 26 | // select 27 | 28 | "& .MuiOutlinedInput-input": { 29 | paddingTop: 6, 30 | paddingBottom: 6, 31 | paddingLeft: 10, 32 | color: theme.palette.text.secondary, 33 | fontWeight: 400, 34 | }, 35 | "& .MuiMenu-paper": { 36 | marginTop: "50px !important", 37 | }, 38 | 39 | "& .MuiOutlinedInput-notchedOutline": { 40 | border: `0`, 41 | borderRadius: theme.spacing(0), 42 | }, 43 | 44 | // menu item 45 | "& .MuiMenuItem-root": { 46 | color: "pink", 47 | }, 48 | 49 | "& .MuiSelect-select:focus": { 50 | backgroundColor: "inherit", 51 | }, 52 | })); 53 | 54 | const ProductActionBar = () => { 55 | const [showDrawer, setShowDrawer] = useState(false); 56 | const toggleDrawer = () => setShowDrawer(!showDrawer); 57 | 58 | return ( 59 | 70 | {/* click to open the drawer */} 71 | } onClick={toggleDrawer}> 72 | Filters 73 | 74 | 75 | {/* Drawer */} 76 | 82 | 83 | 84 | 85 | {/* Sorter */} 86 | 87 | 88 | Sort by: 89 | 90 | 91 | 98 | Featured 99 | Newest 100 | Price: High-Low 101 | Price: Low-High 102 | 103 | 104 | 105 | ); 106 | }; 107 | 108 | export default ProductActionBar; 109 | -------------------------------------------------------------------------------- /src/pages/Login.js: -------------------------------------------------------------------------------- 1 | import { Typography, Link, Container } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | import { Helmet } from "react-helmet"; 5 | import { Link as RouterLink } from "react-router-dom"; 6 | import AuthButtonGroup from "../components/AuthPages/ButtonGroup"; 7 | import FormLogin from "../components/AuthPages/FormLogin"; 8 | import LeftPanel from "../components/AuthPages/LeftPanel"; 9 | import SectionDivider from "../components/AuthPages/SectionDivider"; 10 | 11 | // img 12 | import LoginPhoto from "../images/auth/login.png"; 13 | 14 | // styles 15 | const ContainerBoxStyle = styled(Box)(({ theme }) => ({ 16 | minHeight: `calc(100vh - ${theme.mixins.toolbar.minHeight * 2}px)`, 17 | display: "grid", 18 | gap: theme.spacing(3), 19 | gridTemplateColumns: `350px 1fr`, 20 | 21 | [theme.breakpoints.down("sm")]: { 22 | gridTemplateColumns: `1fr`, 23 | }, 24 | })); 25 | 26 | const RightPanelStyle = styled(Box)(({ theme }) => ({ 27 | display: "flex", 28 | flexDirection: "column", 29 | 30 | "& .account_switch": { 31 | textAlign: "right", 32 | paddingRight: theme.spacing(3), 33 | marginBottom: theme.spacing(8), 34 | "& .MuiLink-underlineNone ": { 35 | color: theme.palette.green.darker, 36 | fontWeight: 500, 37 | }, 38 | [theme.breakpoints.down("sm")]: { 39 | paddingRight: theme.spacing(1.5), 40 | }, 41 | }, 42 | 43 | "& .form_Container": { 44 | flex: 1, 45 | display: "flex", 46 | flexDirection: "column", 47 | justifyContent: "center", 48 | 49 | "& .MuiTypography-h4": { 50 | fontSize: 25, 51 | fontWeight: 500, 52 | }, 53 | "& .MuiTypography-paragraph": { 54 | margin: "8px 0 20px 0", 55 | }, 56 | }, 57 | })); 58 | 59 | const Login = () => { 60 | return ( 61 | <> 62 | {/* Helmet */} 63 | 64 | Login | MUI Dash 65 | 66 | 67 | 68 | 73 | 74 | 75 | 76 | Don't have an account?{" "} 77 | 78 | Get started 79 | 80 | 81 | 82 | 83 | Sign in to MUI Dash 84 | 85 | Enter your details below. 86 | 87 | 88 | {/* Buttons */} 89 | 90 | 91 | {/* Section Divider */} 92 | 93 | 94 | {/* The Actual Form 👇 */} 95 | 96 | 97 | 98 | 99 | 100 | ); 101 | }; 102 | 103 | export default Login; 104 | -------------------------------------------------------------------------------- /src/components/Dashboard/InfoCard.js: -------------------------------------------------------------------------------- 1 | import { Box, styled, Typography } from "@material-ui/core"; 2 | 3 | const InfoCard = ({ colorId, icon, amount, title }) => { 4 | const CardStyle = styled(Box)(({ theme }) => ({ 5 | paddingTop: theme.spacing(6), 6 | paddingBottom: theme.spacing(6), 7 | borderRadius: theme.spacing(1.5), 8 | textAlign: "center", 9 | display: "flex", 10 | flexDirection: "column", 11 | alignItems: "center", 12 | backgroundColor: 13 | colorId === "green" 14 | ? theme.palette.green.light 15 | : colorId === "blue" 16 | ? theme.palette.blue.light 17 | : colorId === "yellow" 18 | ? theme.palette.yellow.light 19 | : colorId === "maroon" 20 | ? theme.palette.maroon.light 21 | : "salmon", 22 | [theme.breakpoints.down("sm")]: { 23 | paddingTop: theme.spacing(2.5), 24 | paddingBottom: theme.spacing(2.5), 25 | }, 26 | })); 27 | 28 | const IconStyle = styled(Box)(({ theme }) => ({ 29 | display: "grid", 30 | placeItems: "center", 31 | width: 62, 32 | height: 62, 33 | borderRadius: "50%", 34 | fontSize: theme.spacing(3), 35 | color: 36 | colorId === "green" 37 | ? theme.palette.green.main 38 | : colorId === "blue" 39 | ? theme.palette.blue.main 40 | : colorId === "yellow" 41 | ? theme.palette.yellow.main 42 | : colorId === "maroon" 43 | ? theme.palette.maroon.main 44 | : "salmon", 45 | background: 46 | colorId === "green" 47 | ? `linear-gradient(135deg, transparent 0%, rgba(0, 123, 85, 0.24) 100%)` 48 | : colorId === "blue" 49 | ? `linear-gradient(135deg, transparent 0%, rgba(12, 83, 183, 0.24) 100%)` 50 | : colorId === "yellow" 51 | ? `linear-gradient(135deg, transparent 0%, rgba(183, 129, 3, 0.24) 100%)` 52 | : colorId === "maroon" 53 | ? `linear-gradient(135deg, transparent 0%, rgba(183, 33, 54, 0.24) 100%)` 54 | : "salmon", 55 | })); 56 | 57 | const AmountStyle = styled(Typography)(({ theme }) => ({ 58 | marginTop: theme.spacing(3), 59 | marginBottom: theme.spacing(0.5), 60 | fontSize: theme.spacing(3.5), 61 | color: 62 | colorId === "green" 63 | ? theme.palette.green.main 64 | : colorId === "blue" 65 | ? theme.palette.blue.main 66 | : colorId === "yellow" 67 | ? theme.palette.yellow.main 68 | : colorId === "maroon" 69 | ? theme.palette.maroon.main 70 | : "salmon", 71 | })); 72 | 73 | const TitleStyle = styled(Typography)(({ theme }) => ({ 74 | margin: 0, 75 | opacity: 0.75, 76 | color: 77 | colorId === "green" 78 | ? theme.palette.green.dark 79 | : colorId === "blue" 80 | ? theme.palette.blue.dark 81 | : colorId === "yellow" 82 | ? theme.palette.yellow.dark 83 | : colorId === "maroon" 84 | ? theme.palette.maroon.dark 85 | : "salmon", 86 | })); 87 | 88 | return ( 89 | 90 | {icon} 91 | 92 | 93 | {amount} 94 | 95 | 96 | 97 | {title} 98 | 99 | 100 | ); 101 | }; 102 | 103 | export default InfoCard; 104 | -------------------------------------------------------------------------------- /src/components/Blog/BlogFilters.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { InputAdornment, MenuItem, TextField } from "@material-ui/core"; 3 | import { styled } from "@material-ui/styles"; 4 | import { Autocomplete } from "@mui/material"; 5 | import { Box } from "@mui/system"; 6 | import { FiSearch } from "react-icons/fi"; 7 | 8 | // blogs 9 | import { blogList } from "../../api/blogApi"; 10 | 11 | // style 12 | const BoxStyle = styled(Box)(({ theme }) => ({ 13 | // root 14 | display: "flex", 15 | justifyContent: "space-between", 16 | alignItems: "center", 17 | marginTop: theme.spacing(3), 18 | marginBottom: theme.spacing(2), 19 | 20 | // pop up indicator, down caret icon 21 | "& .MuiAutocomplete-popupIndicator": { 22 | display: "none", 23 | }, 24 | 25 | // textfield 26 | "& .searchField": { 27 | "& .MuiInputBase-root": { 28 | paddingTop: 1, 29 | paddingBottom: 1, 30 | paddingLeft: 10, 31 | }, 32 | "& .MuiAutocomplete-hasPopupIcon": { 33 | paddingRight: 30, 34 | }, 35 | "& .MuiOutlinedInput-notchedOutline": { 36 | border: `1px solid ${theme.palette.text.secondary}`, 37 | borderRadius: theme.spacing(1), 38 | }, 39 | }, 40 | 41 | // select 42 | "& .selectFilter": { 43 | "& .MuiOutlinedInput-input": { 44 | paddingTop: 10, 45 | paddingBottom: 10, 46 | paddingLeft: 12, 47 | }, 48 | "& .MuiMenu-paper": { 49 | marginTop: "50px !important", 50 | }, 51 | 52 | "& .MuiOutlinedInput-notchedOutline": { 53 | border: `1px solid ${theme.palette.text.secondary}`, 54 | borderRadius: theme.spacing(1), 55 | }, 56 | 57 | // menu item 58 | "& .MuiMenuItem-root": { 59 | color: "pink", 60 | }, 61 | }, 62 | })); 63 | 64 | // filter 65 | const filterItems = [ 66 | { id: "el1", type: "Latest" }, 67 | { id: "el2", type: "Popular" }, 68 | { id: "el3", type: "Oldest" }, 69 | ]; 70 | 71 | const BlogFilters = () => { 72 | const [filterType, setFilterType] = useState("Latest"); 73 | const handleFilterTypeChange = (e) => setFilterType(e.target.value); 74 | 75 | return ( 76 | 77 | {/* auto complete */} 78 | item.title} 82 | style={{ width: 220 }} 83 | renderInput={(params) => ( 84 | 93 | 94 | 95 | ), 96 | }} 97 | /> 98 | )} 99 | /> 100 | 101 | {/* select with text field */} 102 | 110 | {filterItems.map((el) => ( 111 | 112 | {el.type} 113 | 114 | ))} 115 | 116 | 117 | ); 118 | }; 119 | 120 | export default BlogFilters; 121 | -------------------------------------------------------------------------------- /src/layout/MainHeader.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | import { AppBar, Box, IconButton, styled, Toolbar } from "@material-ui/core"; 4 | 5 | import { drawerWidth } from "./DashboardLayout"; 6 | 7 | // icons 8 | import { RiMenu3Line } from "react-icons/ri"; 9 | import { BiSearch } from "react-icons/bi"; 10 | 11 | // components 12 | import LanguageSelector from "../components/MainHeader/SelectLanguage"; 13 | import Notifications from "../components/MainHeader/Notifications"; 14 | import UserMenu from "../components/MainHeader/UserMenu"; 15 | 16 | const AppBarStyle = styled(AppBar)(({ theme }) => ({ 17 | boxShadow: "none", 18 | backdropFilter: "blur(6px)", 19 | backgroundColor: "rgba(255, 255, 255, 0.72)", 20 | color: "#333333", 21 | [theme.breakpoints.up("sm")]: { 22 | width: `calc(100% - ${drawerWidth}px)`, 23 | flexShrink: 0, 24 | }, 25 | })); 26 | 27 | const ToolbarStyle = styled(Toolbar)(({ theme }) => ({ 28 | display: "flex", 29 | justifyContent: "space-between", 30 | alignContent: "flex-start", 31 | alignItems: "center", 32 | })); 33 | 34 | const ContainerStyle = styled(Box)(({ theme }) => ({ 35 | display: "grid", 36 | gap: theme.spacing(0.5), 37 | gridAutoFlow: "column", 38 | })); 39 | 40 | const ToggleButtonStyle = styled(IconButton)(({ theme }) => ({ 41 | [theme.breakpoints.up("sm")]: { 42 | display: "none", 43 | }, 44 | })); 45 | 46 | const MainHeader = (props) => { 47 | const [showLang, setShowLang] = useState(null); 48 | const [showNotification, setShowNotification] = useState(null); 49 | const [showUserMenu, setShowUserMenu] = useState(null); 50 | 51 | // open and close lang menu 52 | const handleOpenLang = (e) => setShowLang(e.currentTarget); 53 | const handleCloseLang = () => setShowLang(null); 54 | 55 | // notifications 56 | const handleOpenNotification = (e) => setShowNotification(e.currentTarget); 57 | const handleCloseNotification = () => setShowNotification(null); 58 | 59 | // User Menu 60 | const handleOpenUserMenu = (e) => setShowUserMenu(e.currentTarget); 61 | const handleCloseUserMenu = () => setShowUserMenu(null); 62 | 63 | return ( 64 | 65 | 66 | {/* Left side's items */} 67 | 68 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | {/* Right side's items */} 83 | 84 | {/* Language selector */} 85 | 90 | 91 | {/* Notification */} 92 | 97 | 98 | {/* User Avatar */} 99 | 104 | 105 | 106 | 107 | ); 108 | }; 109 | 110 | export default MainHeader; 111 | -------------------------------------------------------------------------------- /src/api/productApi.js: -------------------------------------------------------------------------------- 1 | export const products = [ 2 | { 3 | id: "p1", 4 | title: `Nike Air Force 1 NDESTRUKT`, 5 | price: 93.229, 6 | priceSale: "", 7 | status: "", 8 | colors: ["#00AB55", "#000000"], 9 | productImage: `https://raw.githubusercontent.com/minimal-ui-kit/material-kit-react/465e1219502ff9d091b1c922cc30f25a2119a681/public/static/mock-images/products/product_1.jpg`, 10 | }, 11 | { 12 | id: "p2", 13 | title: `Nike Space Hippie 04`, 14 | price: 85.59, 15 | priceSale: "", 16 | status: "", 17 | colors: ["#94D82D", "#FFC107", "#000000", "#FFFFFF"], 18 | productImage: `https://raw.githubusercontent.com/minimal-ui-kit/material-kit-react/465e1219502ff9d091b1c922cc30f25a2119a681/public/static/mock-images/products/product_2.jpg`, 19 | }, 20 | { 21 | id: "p3", 22 | title: `Nike Air Zoom Pegasus 37 A.I.R. Chaz Bear`, 23 | price: 37.18, 24 | priceSale: 27.784, 25 | status: "new", 26 | colors: ["#FF4842", "#1890FF", "#94D82D", "#FFC107"], 27 | productImage: `https://raw.githubusercontent.com/minimal-ui-kit/material-kit-react/465e1219502ff9d091b1c922cc30f25a2119a681/public/static/mock-images/products/product_3.jpg`, 28 | }, 29 | { 30 | id: "p4", 31 | title: `Nike Blazer Low 77 Vintage`, 32 | price: 85.04, 33 | priceSale: "", 34 | status: "new", 35 | colors: ["#FFFFFF", "#FFC0CB", "#FF4842", "#1890FF"], 36 | productImage: `https://raw.githubusercontent.com/minimal-ui-kit/material-kit-react/465e1219502ff9d091b1c922cc30f25a2119a681/public/static/mock-images/products/product_4.jpg`, 37 | }, 38 | { 39 | id: "p5", 40 | title: `Nike ZoomX SuperRep Surge`, 41 | price: 40.16, 42 | priceSale: "", 43 | status: "", 44 | colors: ["#00AB55", "#FF4842", "#1890FF"], 45 | productImage: `https://raw.githubusercontent.com/minimal-ui-kit/material-kit-react/465e1219502ff9d091b1c922cc30f25a2119a681/public/static/mock-images/products/product_5.jpg`, 46 | }, 47 | { 48 | id: "p6", 49 | title: `Zoom Freak 2`, 50 | price: 94.87, 51 | priceSale: 28.6, 52 | status: "new", 53 | colors: ["#FF4842"], 54 | productImage: `https://raw.githubusercontent.com/minimal-ui-kit/material-kit-react/465e1219502ff9d091b1c922cc30f25a2119a681/public/static/mock-images/products/product_6.jpg`, 55 | }, 56 | { 57 | id: "p7", 58 | title: `Nike Air Max Zephyr`, 59 | price: 84.54, 60 | priceSale: "", 61 | status: "new", 62 | colors: ["#94D82D", "#00AB55", "#000000"], 63 | productImage: `https://raw.githubusercontent.com/minimal-ui-kit/material-kit-react/465e1219502ff9d091b1c922cc30f25a2119a681/public/static/mock-images/products/product_7.jpg`, 64 | }, 65 | { 66 | id: "p8", 67 | title: `Jordan Delta`, 68 | price: 54.34, 69 | priceSale: "", 70 | status: "", 71 | colors: ["#FFC0CB", "#FF4842"], 72 | productImage: `https://raw.githubusercontent.com/minimal-ui-kit/material-kit-react/465e1219502ff9d091b1c922cc30f25a2119a681/public/static/mock-images/products/product_8.jpg`, 73 | }, 74 | { 75 | id: "p9", 76 | title: `Air Jordan XXXV PF`, 77 | price: 46.1, 78 | priceSale: 24.24, 79 | status: "sale", 80 | colors: ["#000000", "#FFFFFF", "#FFC0CB"], 81 | productImage: `https://raw.githubusercontent.com/minimal-ui-kit/material-kit-react/465e1219502ff9d091b1c922cc30f25a2119a681/public/static/mock-images/products/product_9.jpg`, 82 | }, 83 | { 84 | id: "p10", 85 | title: `Nike Waffle Racer Crater`, 86 | price: 21.94, 87 | priceSale: "", 88 | status: "", 89 | colors: ["#1890FF", "#94D82D", "#FFC107"], 90 | productImage: `https://raw.githubusercontent.com/minimal-ui-kit/material-kit-react/465e1219502ff9d091b1c922cc30f25a2119a681/public/static/mock-images/products/product_10.jpg`, 91 | }, 92 | ]; 93 | -------------------------------------------------------------------------------- /src/images/404.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 11 | 14 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/pages/Register.js: -------------------------------------------------------------------------------- 1 | import { Typography, Link, Container } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | import { Helmet } from "react-helmet"; 5 | import { Link as RouterLink } from "react-router-dom"; 6 | import AuthButtonGroup from "../components/AuthPages/ButtonGroup"; 7 | import FormRegister from "../components/AuthPages/FormRegister"; 8 | import LeftPanel from "../components/AuthPages/LeftPanel"; 9 | import SectionDivider from "../components/AuthPages/SectionDivider"; 10 | 11 | // img 12 | import RegisterPhoto from "../images/auth/register.png"; 13 | 14 | // styles 15 | const ContainerBoxStyle = styled(Box)(({ theme }) => ({ 16 | minHeight: `calc(100vh - ${theme.mixins.toolbar.minHeight * 2}px)`, 17 | display: "grid", 18 | gap: theme.spacing(3), 19 | gridTemplateColumns: `350px 1fr`, 20 | 21 | [theme.breakpoints.down("sm")]: { 22 | gridTemplateColumns: `1fr`, 23 | }, 24 | })); 25 | 26 | const RightPanelStyle = styled(Box)(({ theme }) => ({ 27 | display: "flex", 28 | flexDirection: "column", 29 | 30 | "& .account_switch": { 31 | textAlign: "right", 32 | paddingRight: theme.spacing(3), 33 | marginBottom: theme.spacing(8), 34 | "& .MuiLink-underlineNone ": { 35 | color: theme.palette.green.darker, 36 | fontWeight: 500, 37 | }, 38 | [theme.breakpoints.down("sm")]: { 39 | paddingRight: theme.spacing(1.5), 40 | }, 41 | }, 42 | 43 | "& .form_Container": { 44 | flex: 1, 45 | display: "flex", 46 | flexDirection: "column", 47 | justifyContent: "center", 48 | 49 | "& .MuiTypography-h4": { 50 | fontSize: 25, 51 | fontWeight: 500, 52 | }, 53 | "& .MuiTypography-paragraph": { 54 | margin: "8px 0 20px 0", 55 | }, 56 | }, 57 | 58 | "& .terms": { 59 | display: "block", 60 | marginTop: "24px !important", 61 | fontSize: 12, 62 | textAlign: "justify", 63 | 64 | "& a": { 65 | textDecorationColor: theme.palette.success.light, 66 | "&:hover": { 67 | textDecorationColor: theme.palette.common.black, 68 | }, 69 | }, 70 | }, 71 | })); 72 | 73 | const Register = () => { 74 | const preventDefault = (e) => e.preventDefault(); 75 | 76 | return ( 77 | <> 78 | {/* Helmet */} 79 | 80 | Register | MUI Dash 81 | 82 | 83 | 84 | 89 | 90 | 91 | 92 | Already have an account?{" "} 93 | 94 | Login 95 | 96 | 97 | 98 | 99 | Get started absolutely free. 100 | 101 | Free forever. No credit card needed. 102 | 103 | 104 | {/* Buttons */} 105 | 106 | 107 | {/* Section Divider */} 108 | 109 | 110 | {/* The Actual Form 👇 */} 111 | 112 | 113 | {/* Terms */} 114 | 115 | By registering, I agree to MUI Dash{" "} 116 | 122 | Terms of Service 123 | {" "} 124 | and{" "} 125 | 131 | Privacy Policy 132 | 133 | . 134 | 135 | 136 | 137 | 138 | 139 | ); 140 | }; 141 | 142 | export default Register; 143 | -------------------------------------------------------------------------------- /src/components/MainHeader/UserMenu.js: -------------------------------------------------------------------------------- 1 | // icons 2 | import { 3 | Avatar, 4 | Box, 5 | Divider, 6 | IconButton, 7 | Link, 8 | Menu, 9 | MenuItem, 10 | Typography, 11 | } from "@material-ui/core"; 12 | import { makeStyles, styled, withStyles } from "@material-ui/styles"; 13 | 14 | // icons & images 15 | import userAvatar from "../../images/avatar_default.jpg"; 16 | import { RiHome4Fill, RiUserFill, RiSettings3Fill } from "react-icons/ri"; 17 | 18 | // styles 19 | const useStyles = makeStyles((theme) => ({ 20 | grayMain: { 21 | color: theme.palette.gray.main, 22 | }, 23 | grayDark: { 24 | color: theme.palette.gray.dark, 25 | }, 26 | listHeader: { 27 | color: theme.palette.gray.main, 28 | margin: "8px 0", 29 | paddingLeft: theme.spacing(2), 30 | letterSpacing: 1, 31 | fontSize: theme.spacing(2), 32 | fontWeight: 600, 33 | }, 34 | })); 35 | 36 | const StyledMenu = withStyles((theme) => ({ 37 | paper: { 38 | maxWidth: 225, 39 | width: "90%", 40 | boxShadow: `0 2px 10px -5px ${theme.palette.green.darker}`, 41 | }, 42 | }))((props) => ( 43 | 56 | )); 57 | 58 | const BoxStyle = styled(Box)(({ theme }) => ({ 59 | padding: "10px 16px", 60 | })); 61 | 62 | const AvatarButtonStyle = styled(IconButton)(({ theme }) => ({ 63 | padding: "2px 6px", 64 | "& .MuiAvatar-root": { 65 | width: theme.spacing(4), 66 | height: theme.spacing(4), 67 | }, 68 | })); 69 | 70 | const LinkStyle = styled(Link)(({ theme }) => ({ 71 | display: "block", 72 | textAlign: "center", 73 | padding: theme.spacing(1), 74 | color: theme.palette.common.black, 75 | fontSize: theme.spacing(2.25), 76 | fontWeight: 500, 77 | border: "1px solid #333", 78 | borderRadius: theme.spacing(0.75), 79 | transition: "background 0.25s ease-in", 80 | "&:hover": { 81 | backgroundColor: theme.palette.gray.lighter, 82 | underline: "none", 83 | }, 84 | })); 85 | 86 | const MenuItemStyle = styled(MenuItem)(({ theme }) => ({ 87 | padding: 0, 88 | "& a": { 89 | width: "100%", 90 | padding: "8px 20px", 91 | display: "flex", 92 | alignItems: "center", 93 | fontSize: 18, 94 | color: theme.palette.common.black, 95 | textDecoration: "none", 96 | "& svg": { 97 | marginRight: theme.spacing(1.5), 98 | fontSize: theme.spacing(2.5), 99 | }, 100 | }, 101 | })); 102 | 103 | // List of links 104 | const links = [ 105 | { id: "l1", path: "/home", title: "Home", icon: }, 106 | { id: "l2", path: "/profile", title: "Profile", icon: }, 107 | { id: "l3", path: "/settings", title: "Settings", icon: }, 108 | ]; 109 | 110 | const UserMenu = (props) => { 111 | const classes = useStyles(); 112 | 113 | return ( 114 | <> 115 | 120 | 121 | JD 122 | 123 | 124 | 125 | 132 | {/* Header */} 133 | 134 | 135 | Jaydon Frankie 136 | 137 | 142 | demo@minimal.cc 143 | 144 | 145 | 146 | 147 | 148 | {/* list of links */} 149 | {links.map((el) => ( 150 | 151 | 152 | {el.icon} 153 | {el.title} 154 | 155 | 156 | ))} 157 | 158 | {/* Footer */} 159 | 160 | 161 | Logout 162 | 163 | 164 | 165 | 166 | ); 167 | }; 168 | 169 | export default UserMenu; 170 | -------------------------------------------------------------------------------- /src/components/AuthPages/FormRegister.js: -------------------------------------------------------------------------------- 1 | import { Button, IconButton, InputAdornment } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { TextField } from "@mui/material"; 4 | import { Box } from "@mui/system"; 5 | import { useState } from "react"; 6 | import { useForm } from "react-hook-form"; 7 | import { RiEyeFill, RiEyeOffFill } from "react-icons/ri"; 8 | 9 | // style 10 | const FormStyle = styled("form")(({ theme }) => ({ 11 | // root style 12 | marginTop: theme.spacing(2), 13 | display: "grid", 14 | gap: theme.spacing(3), 15 | 16 | // input style 17 | "& label.Mui-focused": { 18 | color: theme.palette.success.main, 19 | }, 20 | "& .MuiInput-underline:after": { 21 | borderBottomColor: theme.palette.success.main, 22 | }, 23 | "& .MuiOutlinedInput-root": { 24 | "&.Mui-focused fieldset": { 25 | borderColor: theme.palette.success.main, 26 | }, 27 | }, 28 | 29 | // error 30 | "& .Mui-error.MuiOutlinedInput-root": { 31 | "&.Mui-focused fieldset": { 32 | borderColor: theme.palette.error.light, 33 | }, 34 | }, 35 | "& label.Mui-error.Mui-focused": { 36 | color: theme.palette.error.light, 37 | }, 38 | 39 | // Button style 40 | "& .MuiButton-contained": { 41 | backgroundColor: theme.palette.success.main, 42 | color: theme.palette.common.white, 43 | fontWeight: 600, 44 | textTransform: "capitalize", 45 | padding: theme.spacing(1.25), 46 | boxShadow: `rgb(0 171 85 / 24%) 0px 8px 16px 0px`, 47 | "&:hover": { 48 | backgroundColor: theme.palette.success.dark, 49 | boxShadow: "none", 50 | }, 51 | }, 52 | })); 53 | 54 | const FormRegister = () => { 55 | const [showPassword, setShowPassord] = useState(false); 56 | const handleTogglePassword = () => setShowPassord(!showPassword); 57 | 58 | // hook form 59 | const { 60 | register, 61 | handleSubmit, 62 | formState: { errors }, 63 | } = useForm({ 64 | defaultValues: { 65 | firstName: "", 66 | lastName: "", 67 | email: "", 68 | password: "", 69 | }, 70 | }); 71 | 72 | // submit 73 | const onSubmit = (data) => { 74 | console.table(data); 75 | alert("userData: " + JSON.stringify(data)); 76 | }; 77 | 78 | return ( 79 | 80 | {/* Names box */} 81 | 88 | 97 | 98 | 107 | 108 | 109 | {/* email */} 110 | 119 | 120 | {/* password */} 121 | 128 | 129 | {showPassword ? : } 130 | 131 | 132 | ), 133 | }} 134 | label="Password" 135 | {...register("password", { 136 | required: true, 137 | minLength: 5, 138 | maxLength: 15, 139 | })} 140 | error={errors.password ? true : false} 141 | helperText={ 142 | errors.password && "Enter a valid password (5-15 characters)" 143 | } 144 | /> 145 | 146 | {/* submit */} 147 | 150 | 151 | ); 152 | }; 153 | 154 | export default FormRegister; 155 | -------------------------------------------------------------------------------- /src/components/Product/DrawerContentBody.js: -------------------------------------------------------------------------------- 1 | import { 2 | Button, 3 | Checkbox, 4 | FormControl, 5 | FormControlLabel, 6 | FormGroup, 7 | Radio, 8 | RadioGroup, 9 | } from "@material-ui/core"; 10 | import { styled } from "@material-ui/styles"; 11 | import { Rating } from "@mui/material"; 12 | import DrawerContentCard from "./DrawerContentCard"; 13 | import { RiCheckboxBlankCircleFill, RiCheckLine } from "react-icons/ri"; 14 | import { Box } from "@mui/system"; 15 | 16 | // style 17 | const ButtonStyle = styled(Button)(({ theme }) => ({ 18 | justifyContent: "flex-start", 19 | alignItems: "center", 20 | 21 | "& .upText": { 22 | marginLeft: theme.spacing(1), 23 | marginTop: theme.spacing(0.25), 24 | textTransform: "capitalize", 25 | }, 26 | 27 | "&:hover": { 28 | backgroundColor: theme.palette.green.lighter, 29 | opacity: 0.5, 30 | }, 31 | })); 32 | 33 | // price radio 34 | const PRICE_SORT = [ 35 | { val: "below25", title: "Below $25" }, 36 | { val: "25to75", title: "Between $25-$75" }, 37 | { val: "above75", title: "Above $75" }, 38 | ]; 39 | 40 | // colors 41 | const COLORS_TO_PICK = [ 42 | "#00AB55", 43 | "#000000", 44 | "#FFFFFF", 45 | "#FFC0CB", 46 | "#FF4842", 47 | "#1890FF", 48 | "#94D82D", 49 | "#FFC107", 50 | ]; 51 | 52 | const DrawerContentBody = () => { 53 | return ( 54 | <> 55 | {/* Gender */} 56 | 57 | 58 | {["Men", "Women", "Kids"].map((el, idx) => ( 59 | } 62 | label={el} 63 | /> 64 | ))} 65 | 66 | 67 | 68 | {/* Category */} 69 | 70 | 71 | 76 | {["All", "Shoes", "Apparel", "Accessories"].map((el, idx) => ( 77 | } 81 | label={el} 82 | /> 83 | ))} 84 | 85 | 86 | 87 | 88 | {/* Colors later */} 89 | 90 | 97 | {COLORS_TO_PICK.map((el, idx) => ( 98 | 112 | } 115 | checkedIcon={ 116 | 120 | } 121 | /> 122 | 123 | ))} 124 | 125 | 126 | 127 | {/* Price */} 128 | 129 | 130 | 135 | {PRICE_SORT.map((el, idx) => ( 136 | } 140 | label={el.title} 141 | /> 142 | ))} 143 | 144 | 145 | 146 | 147 | {/* Ratings */} 148 | 149 | {[4, 3, 2, 1].map((el) => ( 150 | 151 | 152 | & up 153 | 154 | ))} 155 | 156 | 157 | ); 158 | }; 159 | 160 | export default DrawerContentBody; 161 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MUI Dash 2 | 3 | **Hi there!** 4 | 5 | I cloned [this dashboard](https://minimal-kit-react.vercel.app/dashboard/app) to practice my skills in Material UI with Reactjs. I learnt a lot from version 4 to 5. I used almost all the common components in this project. 6 | 7 | **Pages** 8 | 9 | 1. Dashboard 10 | 2. User 11 | 3. Product 12 | 4. Blog 13 | 5. Login 14 | 6. Register 15 | 7. 404 16 | 17 | ## Styling 18 | 19 | For styling I mainly used `styled` function from `@material-ui/styles`. 20 | 21 | I used the `sx` property when it was available in some certain components. 22 | 23 | ## Help Center 24 | 25 | There's a big problem in the routing. I used `"react-router-dom": "^5.2.0"`. I couldn't nest the **Login** and **Register** component in the **AuthLayout** component. I tried the methods from version 6 but it didn't work. 26 | 27 | I tried another way which can be found in the **routes.js** file. It didn't work as well. 28 | 29 | If you can suggest me any way, I'll appreciate it very much. 30 | 31 | ## Are you hiring? 32 | 33 | I'm looking for an entry level job. If you've any opportunity, please let [me](mailto:tutulnahid@gmail.com) know. 🙏 34 | 35 | ## Support 36 | 37 | If you're inspired, don't be shy to give it a ⭐ 38 | 39 | --- 40 | 41 | ## Getting Started with Create React App 42 | 43 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 44 | 45 | ## Available Scripts 46 | 47 | In the project directory, you can run: 48 | 49 | ### `npm start` 50 | 51 | Runs the app in the development mode.\ 52 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 53 | 54 | The page will reload if you make edits.\ 55 | You will also see any lint errors in the console. 56 | 57 | ### `npm test` 58 | 59 | Launches the test runner in the interactive watch mode.\ 60 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 61 | 62 | ### `npm run build` 63 | 64 | Builds the app for production to the `build` folder.\ 65 | It correctly bundles React in production mode and optimizes the build for the best performance. 66 | 67 | The build is minified and the filenames include the hashes.\ 68 | Your app is ready to be deployed! 69 | 70 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 71 | 72 | ### `npm run eject` 73 | 74 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 75 | 76 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 77 | 78 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 79 | 80 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 81 | 82 | ## Learn More 83 | 84 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 85 | 86 | To learn React, check out the [React documentation](https://reactjs.org/). 87 | 88 | ### Code Splitting 89 | 90 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 91 | 92 | ### Analyzing the Bundle Size 93 | 94 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 95 | 96 | ### Making a Progressive Web App 97 | 98 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 99 | 100 | ### Advanced Configuration 101 | 102 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 103 | 104 | ### Deployment 105 | 106 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 107 | 108 | ### `npm run build` fails to minify 109 | 110 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 111 | -------------------------------------------------------------------------------- /src/components/AuthPages/FormLogin.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { useForm } from "react-hook-form"; 3 | import { 4 | Button, 5 | Checkbox, 6 | FormControlLabel, 7 | IconButton, 8 | InputAdornment, 9 | Link, 10 | } from "@material-ui/core"; 11 | import { styled } from "@material-ui/styles"; 12 | import { TextField } from "@mui/material"; 13 | import { Box } from "@mui/system"; 14 | import { RiEyeFill, RiEyeOffFill } from "react-icons/ri"; 15 | 16 | // style 17 | const FormStyle = styled("form")(({ theme }) => ({ 18 | // root style 19 | marginTop: theme.spacing(2), 20 | display: "grid", 21 | gap: theme.spacing(3), 22 | 23 | // input style 24 | "& label.Mui-focused": { 25 | color: theme.palette.success.main, 26 | }, 27 | "& .MuiInput-underline:after": { 28 | borderBottomColor: theme.palette.success.main, 29 | }, 30 | "& .MuiOutlinedInput-root": { 31 | "&.Mui-focused fieldset": { 32 | borderColor: theme.palette.success.main, 33 | }, 34 | }, 35 | 36 | // error 37 | "& .Mui-error.MuiOutlinedInput-root": { 38 | "&.Mui-focused fieldset": { 39 | borderColor: theme.palette.error.light, 40 | }, 41 | }, 42 | "& label.Mui-error.Mui-focused": { 43 | color: theme.palette.error.light, 44 | }, 45 | 46 | // checkbox style 47 | "& .MuiCheckbox-root": { 48 | color: theme.palette.success.light, 49 | }, 50 | "& .Mui-checked": { 51 | color: theme.palette.success.main, 52 | }, 53 | 54 | // forgot link style 55 | "& a": { 56 | color: theme.palette.success.main, 57 | fontWeight: 500, 58 | "&:hover": { 59 | color: theme.palette.success.light, 60 | }, 61 | }, 62 | 63 | // button style 64 | "& .MuiButton-contained": { 65 | backgroundColor: theme.palette.success.main, 66 | color: theme.palette.common.white, 67 | fontWeight: 600, 68 | textTransform: "capitalize", 69 | padding: theme.spacing(1.25), 70 | boxShadow: `rgb(0 171 85 / 24%) 0px 8px 16px 0px`, 71 | "&:hover": { 72 | backgroundColor: theme.palette.success.dark, 73 | boxShadow: "none", 74 | }, 75 | }, 76 | })); 77 | 78 | const FormLogin = () => { 79 | const [showPassword, setShowPassord] = useState(false); 80 | const [remember, setRemember] = useState(true); 81 | 82 | const handleTogglePassword = () => setShowPassord(!showPassword); 83 | const handleToggleRemember = () => setRemember(!remember); 84 | 85 | // hook form 86 | const { 87 | register, 88 | handleSubmit, 89 | formState: { errors }, 90 | } = useForm({ 91 | defaultValues: { 92 | email: "", 93 | password: "", 94 | rememberUser: true, 95 | }, 96 | }); 97 | 98 | // prevent Default 99 | const preventDefault = (e) => e.preventDefault(); 100 | 101 | // form submit 102 | const onSubmit = (data) => { 103 | console.table(data); 104 | alert(JSON.stringify(data)); 105 | }; 106 | 107 | // for reset 108 | // couldn't make it work 109 | 110 | return ( 111 | 112 | {/* Email */} 113 | 122 | 123 | {/* Password */} 124 | 131 | 132 | {showPassword ? : } 133 | 134 | 135 | ), 136 | }} 137 | label="Password" 138 | error={errors.password ? true : false} 139 | helperText={ 140 | errors.password && "Enter a valid password (5-15 characters)" 141 | } 142 | {...register("password", { 143 | required: true, 144 | minLength: 5, 145 | maxLength: 15, 146 | })} 147 | /> 148 | 149 | 156 | {/* Checkbox */} 157 | 164 | } 165 | label="Remember me" 166 | {...register("rememberUser")} 167 | /> 168 | 169 | 170 | Forgot password? 171 | 172 | 173 | 174 | 177 | 178 | ); 179 | }; 180 | 181 | export default FormLogin; 182 | -------------------------------------------------------------------------------- /src/layout/SideDrawer.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import { 3 | Hidden, 4 | styled, 5 | Toolbar, 6 | Drawer, 7 | List, 8 | Typography, 9 | Avatar, 10 | Box, 11 | } from "@material-ui/core"; 12 | 13 | // icons & images 14 | import userAvatar from "../images/avatar_default.jpg"; 15 | import getMoreAvatar from "../images/illustration_avatar.png"; 16 | import { ImPieChart } from "react-icons/im"; 17 | import { FaUserFriends, FaUserPlus } from "react-icons/fa"; 18 | import { GiHazardSign } from "react-icons/gi"; 19 | import { 20 | RiShoppingBag3Fill, 21 | RiClipboardFill, 22 | RiLoginCircleFill, 23 | } from "react-icons/ri"; 24 | 25 | import { drawerWidth } from "./DashboardLayout"; 26 | import CustomListItem from "../components/Drawer/CustomListItem"; 27 | 28 | const NavDrawerStyle = styled("nav")(({ theme }) => ({ 29 | [theme.breakpoints.up("sm")]: { 30 | width: drawerWidth, 31 | flexShrink: 0, 32 | }, 33 | })); 34 | 35 | const LogoStyle = styled(Typography)(({ theme }) => ({ 36 | color: theme.palette.green.darker, 37 | margin: 0, 38 | })); 39 | 40 | const UserCardStyle = styled(Link)(({ theme }) => ({ 41 | display: "flex", 42 | alignItems: "center", 43 | color: "inherit", 44 | backgroundColor: theme.palette.gray.light, 45 | margin: "12px", 46 | padding: "14px 12px", 47 | borderRadius: theme.spacing(1.5), 48 | textDecoration: "none", 49 | "& .MuiTypography-root": { 50 | marginLeft: theme.spacing(1.5), 51 | }, 52 | })); 53 | 54 | const ListStyle = styled(List)(({ theme }) => ({ 55 | marginTop: theme.spacing(2), 56 | })); 57 | 58 | const GetMoreStyle = styled(Box)(({ theme }) => ({ 59 | backgroundColor: theme.palette.gray.lighter, 60 | margin: "40px 12px 16px", 61 | padding: "60px 12px 14px 12px", 62 | borderRadius: theme.spacing(1.5), 63 | textAlign: "center", 64 | position: "relative", 65 | 66 | "& img": { 67 | position: "absolute", 68 | top: 0, 69 | left: "50%", 70 | width: theme.spacing(12.5), 71 | transform: "translate(-40%, -40%)", 72 | transition: "all 0.3s ease-in", 73 | }, 74 | "& h5": { 75 | margin: "10px 0", 76 | }, 77 | "& a": { 78 | textDecoration: "none", 79 | fontWeight: 500, 80 | color: theme.palette.common.white, 81 | backgroundColor: theme.palette.green.darker, 82 | display: "block", 83 | padding: "6px", 84 | borderRadius: "inherit", 85 | transition: "background 0.3s ease-in", 86 | boxShadow: "0px 5px 5px white", 87 | "&:hover": { 88 | backgroundColor: theme.palette.green.dark, 89 | }, 90 | }, 91 | 92 | "&:hover": { 93 | "& img": { 94 | transform: "translate(-40%, -50%)", 95 | }, 96 | }, 97 | })); 98 | 99 | // links for the side nav 100 | const links = [ 101 | { 102 | id: "L0", 103 | path: "/dashboard", 104 | icon: , 105 | title: "Dashboard", 106 | }, 107 | { id: "L1", path: "/user", icon: , title: "User" }, 108 | { 109 | id: "L2", 110 | path: "/product", 111 | icon: , 112 | title: "Product", 113 | }, 114 | { id: "L3", path: "/blog", icon: , title: "Blog" }, 115 | { id: "L4", path: "/login", icon: , title: "Login" }, 116 | { id: "L5", path: "/register", icon: , title: "Register" }, 117 | { id: "L6", path: "/404", icon: , title: "Not Found" }, 118 | ]; 119 | 120 | const SideDrawer = (props) => { 121 | const drawerContent = ( 122 | <> 123 | {/* Logo */} 124 | 125 | 126 | MUI Dash 127 | 128 | 129 | 130 | {/* User Card */} 131 | 132 | 133 | 134 | 135 | Jaydon Frankie 136 | 137 | 138 | 139 | {/* List of links */} 140 | 141 | {links.map((el) => ( 142 | 149 | ))} 150 | 151 | 152 | {/* get more card */} 153 | 154 | avatar 155 | 156 | 157 | Get more? 158 | 159 | 160 | 161 | From only $69 162 | 163 | 164 | 169 | Upgrade To Pro 170 | 171 | 172 | 173 | ); 174 | 175 | return ( 176 | 177 | {/* Hidden 01 for sm size */} 178 | 179 | 188 | {/* Drawer Component */} 189 | {drawerContent} 190 | 191 | 192 | 193 | {/* Hidden 02 for big size*/} 194 | 195 | 196 | {drawerContent} 197 | 198 | 199 | 200 | ); 201 | }; 202 | 203 | export default SideDrawer; 204 | -------------------------------------------------------------------------------- /src/components/User/UserTable.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { userData } from "../../api/userApi"; 3 | import { 4 | TableContainer, 5 | Table, 6 | TableBody, 7 | TableRow, 8 | TableCell, 9 | Checkbox, 10 | TablePagination, 11 | } from "@material-ui/core"; 12 | import { styled } from "@material-ui/styles"; 13 | import TableToolbar from "./TableToolbar"; 14 | import UserTableHead from "./UserTableHead"; 15 | import UserMore from "./UserMore"; 16 | 17 | // style 18 | const TableStyle = styled(Table)(({ theme }) => ({ 19 | // border: "1px solid", 20 | minWidth: 500, 21 | overflowX: "auto", 22 | 23 | // status style 24 | "& .statusText": { 25 | padding: "2px 4px", 26 | borderRadius: theme.spacing(0.75), 27 | color: theme.palette.common.white, 28 | }, 29 | "& .activeText": { 30 | backgroundColor: theme.palette.green.darker, 31 | }, 32 | "& .bannedText": { 33 | backgroundColor: theme.palette.error.light, 34 | }, 35 | 36 | // selected tableRow desing 37 | "& .MuiTableRow-root.Mui-selected": { 38 | backgroundColor: theme.palette.green.lighter, 39 | }, 40 | 41 | // checkbox style 42 | "& .MuiCheckbox-root": { 43 | color: theme.palette.text.disabled, 44 | }, 45 | "& .Mui-checked": { 46 | color: theme.palette.success.main, 47 | }, 48 | "& .MuiIconButton-colorPrimary:hover": { 49 | backgroundColor: theme.palette.green.lighter, 50 | }, 51 | })); 52 | 53 | //////////////////////////////////////////////// 54 | const descendingComparator = (a, b, orderBy) => { 55 | if (b[orderBy] < a[orderBy]) return -1; 56 | if (b[orderBy] > a[orderBy]) return 1; 57 | return 0; 58 | }; 59 | 60 | const getComparator = (order, orderBy) => { 61 | return order === "desc" 62 | ? (a, b) => descendingComparator(a, b, orderBy) 63 | : (a, b) => -descendingComparator(a, b, orderBy); 64 | }; 65 | 66 | const sortableArr = (arr, comparator) => { 67 | const stabilizedThis = arr.map((el, idx) => [el, idx]); 68 | stabilizedThis.sort((a, b) => { 69 | const order = comparator(a[0], b[0]); 70 | if (order !== 0) { 71 | return order; 72 | } 73 | return a[1] - b[1]; 74 | }); 75 | 76 | return stabilizedThis.map((el) => el[0]); 77 | }; 78 | 79 | const UserTable = () => { 80 | // states 81 | const [order, setOrder] = useState("asc"); 82 | const [orderBy, setOrderBy] = useState("calories"); 83 | const [selectedItems, setSelectedItems] = useState([]); 84 | const [page, setPage] = useState(0); 85 | const [rowsPerPage, setRowsPerPage] = useState(5); 86 | 87 | //console.log(selectedItems); 88 | 89 | ////// functions /////////////////////////////// 90 | // you click on the row, it takes the name as property, check the prop & sort 91 | const handleRequestSort = (e, property) => { 92 | const isAsc = orderBy === property && order === "asc"; 93 | setOrder(isAsc ? "desc" : "asc"); 94 | setOrderBy(property); 95 | }; 96 | 97 | // click the ckbox on top & select all the rows 98 | const handleSelectAllClick = (e) => { 99 | if (e.target.checked) { 100 | const newSelected = userData.map((n) => n.name); 101 | setSelectedItems(newSelected); 102 | return; 103 | } 104 | setSelectedItems([]); 105 | }; 106 | 107 | // click each item to select 108 | const handleClick = (e, name) => { 109 | const selectedItemsIndex = selectedItems.indexOf(name); 110 | let newSelected = []; 111 | 112 | // if not in the arr, add 113 | if (selectedItemsIndex === -1) 114 | newSelected = newSelected.concat(selectedItems, name); 115 | else if (selectedItemsIndex === 0) 116 | newSelected = newSelected.concat(selectedItems.slice(1)); 117 | else if (selectedItemsIndex === selectedItems.length - 1) 118 | newSelected = newSelected.concat(selectedItems.slice(0, -1)); 119 | else if (selectedItemsIndex > 0) 120 | newSelected = newSelected.concat( 121 | selectedItems.slice(0, selectedItemsIndex), 122 | selectedItems.slice(selectedItemsIndex + 1) 123 | ); 124 | 125 | setSelectedItems(newSelected); 126 | }; 127 | 128 | // set page 129 | const handleChangePage = (e, newPage) => setPage(newPage); 130 | 131 | // change row per page 132 | const handleChangeRowsPerPage = (e) => { 133 | setRowsPerPage(e.target.value, 10); 134 | setPage(0); 135 | }; 136 | 137 | // find if there's any empty rows || fill it up later 138 | const emptyRows = 139 | page > 0 ? Math.max(0, (1 + page) * rowsPerPage - userData.length) : 0; 140 | 141 | // active/ banned 142 | const StatusText = ({ text }) => { 143 | if (text === "Active") { 144 | return {text}; 145 | } else if (text === "Banned") { 146 | return {text}; 147 | } else { 148 | return { text }; 149 | } 150 | }; 151 | 152 | return ( 153 | <> 154 | {/* Toolbar */} 155 | 156 | 157 | {/* Table */} 158 | 159 | 160 | {/* Table Head */} 161 | 169 | 170 | {/* Table Body */} 171 | 172 | {sortableArr(userData, getComparator(order, orderBy)) 173 | .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) 174 | .map((user, idx) => { 175 | const isItemSelected = selectedItems.indexOf(user.name) !== -1; 176 | const labelId = `enhanced-table-checkbox-${idx}`; 177 | 178 | return ( 179 | 187 | 188 | handleClick(e, user.name)} 193 | /> 194 | 195 | 196 | 202 | {user.name} 203 | 204 | {user.company} 205 | {user.role} 206 | {user.verified} 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | ); 215 | })} 216 | 217 | {/* empty rows can be added below */} 218 | {emptyRows > 0 && ( 219 | 220 | 221 | 222 | )} 223 | 224 | 225 | 226 | 227 | {/* Table Pagination */} 228 | 237 | 238 | ); 239 | }; 240 | 241 | export default UserTable; 242 | -------------------------------------------------------------------------------- /src/components/Blog/Blogs.js: -------------------------------------------------------------------------------- 1 | import { Avatar, Grid, Link, Typography } from "@material-ui/core"; 2 | import { styled } from "@material-ui/styles"; 3 | import { Box } from "@mui/system"; 4 | import BlogSocialInfo from "./BlogSocialInfo"; 5 | 6 | // blog 7 | import { blogList } from "../../api/blogApi"; 8 | 9 | // styles 10 | const GridContainerStyle = styled(Grid)(({ theme }) => ({ 11 | // border: "1px solid", 12 | marginTop: theme.spacing(4), 13 | marginBottom: theme.spacing(2), 14 | })); 15 | 16 | const GridItemStyle = styled(Grid)(({ theme }) => ({ 17 | "& .boxContainer": { 18 | // border: "1px solid #eee", 19 | borderRadius: theme.spacing(1.5), 20 | minHeight: 350, 21 | margin: 0, 22 | padding: theme.spacing(3), 23 | position: "relative", 24 | transition: "all 0.3s ease-in-out", 25 | 26 | display: "grid", 27 | gridTemplateRows: `80px 1fr`, 28 | 29 | "&::before": { 30 | content: `""`, 31 | display: "block", 32 | width: "100%", 33 | height: "100%", 34 | position: "absolute", 35 | top: 0, 36 | left: 0, 37 | backgroundColor: "rgba(0,0,0,0.7)", 38 | borderRadius: "inherit", 39 | }, 40 | 41 | "&:hover": { 42 | transition: "all 0.3s ease-in-out", 43 | transform: `translateY(-5px)`, 44 | boxShadow: theme.shadows[8], 45 | }, 46 | 47 | // textContent 48 | "& .textContainer": { 49 | color: theme.palette.common.white, 50 | zIndex: 100, 51 | display: "grid", 52 | gap: 12, 53 | alignContent: "space-between", 54 | }, 55 | 56 | // link 57 | "& a": { 58 | color: "inherit", 59 | display: "block", 60 | marginTop: 8, 61 | }, 62 | }, 63 | })); 64 | 65 | const NewBoxStyle = styled(Box)(({ theme }) => ({ 66 | border: `1px solid ${theme.palette.gray.light}`, 67 | borderRadius: theme.spacing(1.5), 68 | minHeight: 350, 69 | margin: 0, 70 | position: "relative", 71 | transition: "all 0.3s ease-in-out", 72 | boxShadow: `rgb(145 158 171 / 24%) 0px 0px 2px 0px, rgb(145 158 171 / 24%) 0px 16px 32px -4px`, 73 | 74 | display: "grid", 75 | gridTemplateRows: `200px auto`, 76 | 77 | "&:hover": { 78 | transition: "all 0.3s ease-in-out", 79 | boxShadow: `rgb(145 158 171 / 24%) 0px 0px 2px 0px, rgb(145 158 171 / 24%) 0px 4px 8px -2px`, 80 | }, 81 | 82 | "& .imgContainer": { 83 | position: "relative", 84 | "&::before": { 85 | content: `""`, 86 | display: "block", 87 | width: "100%", 88 | height: "100%", 89 | position: "absolute", 90 | top: 0, 91 | left: 0, 92 | backgroundColor: "rgba(0,0,0,0.45)", 93 | borderRadius: "inherit", 94 | }, 95 | }, 96 | 97 | "& .textContainer": { 98 | padding: `0 ${theme.spacing(3)}px ${theme.spacing(3)}px`, 99 | 100 | display: "grid", 101 | gap: theme.spacing(2), 102 | 103 | "& .MuiAvatar-root": { 104 | backgroundColor: theme.palette.common.white, 105 | padding: 10, 106 | width: 50, 107 | height: 50, 108 | transform: `translateY(-50%)`, 109 | 110 | "& img": { 111 | borderRadius: "50%", 112 | width: 40, 113 | height: 40, 114 | }, 115 | }, 116 | 117 | "& .dateTime": { 118 | marginTop: "-15px", 119 | color: theme.palette.text.disabled, 120 | }, 121 | 122 | "& .linkTitle": { 123 | "& a": { 124 | fontSize: 20, 125 | color: "inherit", 126 | display: "block", 127 | }, 128 | }, 129 | }, 130 | })); 131 | 132 | // blog items 133 | const firstBlogItem = blogList[0]; 134 | const secondAndThirdItem = blogList.slice(1, 3); 135 | const restOfTheArr = blogList.slice(3, blogList.length); 136 | 137 | const Blogs = () => { 138 | return ( 139 | 140 | {/* First Item of the blog */} 141 | 142 | 148 | 149 | 150 | 151 | 152 | 153 | {firstBlogItem.dateTime} 154 | 155 | 156 | 157 | 158 | {firstBlogItem.title} 159 | 160 | 161 | 162 | 163 | {/* Blog Social Info */} 164 | 169 | 170 | 171 | 172 | 173 | {/* Second and Third Items */} 174 | {secondAndThirdItem.map((el, idx) => ( 175 | 176 | 184 | 185 | 186 | 187 | 188 | {el.dateTime} 189 | 190 | 191 | 192 | {el.title} 193 | 194 | 195 | 196 | 197 | {/* Blog Social Info */} 198 | 203 | 204 | 205 | 206 | ))} 207 | {/* end of second & third */} 208 | 209 | {/* Rest of the Array data */} 210 | {restOfTheArr.map((el, idx) => ( 211 | 212 | 213 | 222 | 223 | 224 | 230 | 235 | 236 | 237 | {el.dateTime} 238 | 239 | 240 | 241 | 242 | {el.title} 243 | 244 | 245 | 246 | 247 | {/* Blog Social Info */} 248 | 254 | 255 | 256 | 257 | ))} 258 | {/* end of rest of the array data */} 259 | 260 | ); 261 | }; 262 | 263 | export default Blogs; 264 | -------------------------------------------------------------------------------- /src/components/MainHeader/Notifications.js: -------------------------------------------------------------------------------- 1 | import { 2 | Badge, 3 | Box, 4 | Divider, 5 | IconButton, 6 | Link, 7 | Menu, 8 | MenuItem, 9 | Typography, 10 | } from "@material-ui/core"; 11 | import { makeStyles, styled, withStyles } from "@material-ui/styles"; 12 | 13 | // icons 14 | import { HiBell, HiClock } from "react-icons/hi"; 15 | import { FaUser, FaTruck } from "react-icons/fa"; 16 | import { BsFillChatDotsFill } from "react-icons/bs"; 17 | import { IoMailOpenSharp } from "react-icons/io5"; 18 | import { FiBox } from "react-icons/fi"; 19 | 20 | // styles 21 | const useStyles = makeStyles((theme) => ({ 22 | grayMain: { 23 | color: theme.palette.gray.main, 24 | }, 25 | grayDark: { 26 | color: theme.palette.gray.dark, 27 | }, 28 | listHeader: { 29 | color: theme.palette.gray.main, 30 | margin: "8px 0", 31 | paddingLeft: theme.spacing(2), 32 | letterSpacing: 1, 33 | fontSize: theme.spacing(2), 34 | fontWeight: 600, 35 | }, 36 | })); 37 | 38 | const StyledMenu = withStyles((theme) => ({ 39 | paper: { 40 | minWidth: 250, 41 | maxWidth: 400, 42 | width: "90%", 43 | boxShadow: `0 2px 10px -5px ${theme.palette.green.darker}`, 44 | }, 45 | }))((props) => ( 46 | 59 | )); 60 | 61 | const BadgeStyle = styled(Badge)(({ theme }) => ({ 62 | "& .MuiBadge-badge": { 63 | backgroundColor: theme.palette.red.main, 64 | color: theme.palette.common.white, 65 | top: "-3px", 66 | fontSize: theme.spacing(1.75), 67 | }, 68 | })); 69 | 70 | const BoxStyle = styled(Box)(({ theme }) => ({ 71 | padding: "10px 16px", 72 | })); 73 | 74 | const LinkStyle = styled(Link)(({ theme }) => ({ 75 | display: "block", 76 | textAlign: "center", 77 | padding: theme.spacing(1), 78 | color: theme.palette.green.dark, 79 | fontSize: theme.spacing(2), 80 | fontWeight: 500, 81 | borderRadius: theme.spacing(0.75), 82 | transition: "background 0.25s ease-in", 83 | "&:hover": { 84 | backgroundColor: theme.palette.green.light, 85 | underline: "none", 86 | }, 87 | })); 88 | 89 | const MenuItemUnseenStyle = styled(MenuItem)(({ theme }) => ({ 90 | backgroundColor: theme.palette.gray.lighter, 91 | padding: "16px 12px 16px 8px", 92 | display: "flex", 93 | alignItems: "center", 94 | whiteSpace: "break-spaces", 95 | "&:hover": { 96 | backgroundColor: theme.palette.gray.light, 97 | }, 98 | })); 99 | 100 | const MenuItemSeenStyle = styled(MenuItem)(() => ({ 101 | padding: "16px 12px 16px 8px", 102 | display: "flex", 103 | alignItems: "center", 104 | whiteSpace: "break-spaces", 105 | })); 106 | 107 | const MenuItemIconButtonStyle = styled(IconButton)(({ theme }) => ({ 108 | marginRight: theme.spacing(2), 109 | backgroundColor: theme.palette.gray.lighter, 110 | color: `#${Math.random().toString(16).substr(-6)}`, 111 | })); 112 | 113 | const MenuItemTimeStampStyle = styled(Typography)(({ theme }) => ({ 114 | display: "flex", 115 | alignItems: "center", 116 | fontSize: theme.spacing(1.85), 117 | color: theme.palette.gray.main, 118 | margin: 0, 119 | marginTop: theme.spacing(0.5), 120 | "& span": { 121 | marginLeft: theme.spacing(1), 122 | }, 123 | })); 124 | 125 | // List of notification 126 | const notificationList = [ 127 | { 128 | id: "n1", 129 | status: "unseen", 130 | avatar: , 131 | mainText: "Your order is placed", 132 | subText: "waiting for shipping", 133 | time: "about 12 hours", 134 | }, 135 | { 136 | id: "n2", 137 | status: "seen", 138 | avatar: , 139 | mainText: "You have new message", 140 | subText: "5 unread messages", 141 | time: "1 day", 142 | }, 143 | { 144 | id: "n3", 145 | status: "unseen", 146 | avatar: , 147 | mainText: "Miss Veronica Walter", 148 | subText: "answered to your comment on the minimal", 149 | time: "about 4 hours", 150 | }, 151 | { 152 | id: "n4", 153 | status: "seen", 154 | avatar: , 155 | mainText: "You have new mail", 156 | subText: "sent from guido padberg", 157 | time: "2 days", 158 | }, 159 | { 160 | id: "n5", 161 | status: "seen", 162 | avatar: , 163 | mainText: "Delivery processing", 164 | subText: "your order is being shipped", 165 | time: "3 days", 166 | }, 167 | ]; 168 | 169 | const seenNotifications = notificationList.filter((el) => el.status === "seen"); 170 | const unSeenNotifications = notificationList.filter( 171 | (el) => el.status === "unseen" 172 | ); 173 | const totalUnseenNotifications = unSeenNotifications.length; 174 | 175 | const Notifications = (props) => { 176 | const classes = useStyles(); 177 | 178 | return ( 179 | <> 180 | 185 | 186 | 187 | 188 | 189 | 190 | 197 | {/* Header */} 198 | 199 | 200 | Notifications 201 | 202 | 207 | You have {totalUnseenNotifications} unread messages 208 | 209 | 210 | 211 | 212 | 213 | {/* Unseen Notifications */} 214 | 219 | NEW 220 | 221 | 222 | {unSeenNotifications.map((el) => ( 223 | 224 | {el.avatar} 225 | 226 | 227 | 228 | {el.mainText}{" "} 229 | {el.subText} 230 | 231 | 232 | 233 | 234 | {el.time} 235 | 236 | 237 | 238 | ))} 239 | 240 | {/* Seen Notifications */} 241 | 246 | BEFORE THAT 247 | 248 | 249 | {seenNotifications.map((el) => ( 250 | 251 | {el.avatar} 252 | 253 | 254 | 255 | {el.mainText}{" "} 256 | {el.subText} 257 | 258 | 259 | 260 | 261 | {el.time} 262 | 263 | 264 | 265 | ))} 266 | 267 | 268 | 269 | {/* Footer */} 270 | 271 | 272 | View All 273 | 274 | 275 | 276 | 277 | ); 278 | }; 279 | 280 | export default Notifications; 281 | --------------------------------------------------------------------------------