├── 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 | }>
37 | New User
38 |
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 |
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 |
67 |
68 |
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 |
72 |
73 |
74 |
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 | }
71 | style={{
72 | padding: "10px 0",
73 | fontWeight: 500,
74 | textTransform: "capitalize",
75 | }}
76 | onClick={closeDrawer}
77 | >
78 | Clear All
79 |
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 | }
92 | >
93 | View All
94 |
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 |
99 |
100 |
101 |
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 |
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 |
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 |
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 |
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 |
276 | >
277 | );
278 | };
279 |
280 | export default Notifications;
281 |
--------------------------------------------------------------------------------