├── .gitignore
├── LICENSE.md
├── README.md
├── package-lock.json
├── package.json
├── public
└── index.html
├── src
├── App.js
├── components
│ ├── chart
│ │ ├── Chart.jsx
│ │ └── chart.scss
│ ├── datatable
│ │ ├── Datatable.jsx
│ │ └── datatable.scss
│ ├── featured
│ │ ├── Featured.jsx
│ │ └── featured.scss
│ ├── navbar
│ │ ├── Navbar.jsx
│ │ └── navbar.scss
│ ├── sidebar
│ │ ├── Sidebar.jsx
│ │ └── sidebar.scss
│ ├── table
│ │ ├── Table.jsx
│ │ └── table.scss
│ └── widget
│ │ ├── Widget.jsx
│ │ └── widget.scss
├── context
│ ├── darkModeContext.js
│ └── darkModeReducer.js
├── datatablesource.js
├── formSource.js
├── index.js
├── pages
│ ├── home
│ │ ├── Home.jsx
│ │ └── home.scss
│ ├── list
│ │ ├── List.jsx
│ │ └── list.scss
│ ├── login
│ │ ├── Login.jsx
│ │ └── login.scss
│ ├── new
│ │ ├── New.jsx
│ │ └── new.scss
│ └── single
│ │ ├── Single.jsx
│ │ └── single.scss
└── style
│ └── dark.scss
└── yarn.lock
/.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 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Zykar Solutions
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Material Admin Dashboard — Template
2 |
3 | React Admin is a React template
4 |
5 | Built with [React](https://facebook.github.io/react/), [Material-UI](https://material-ui.com), [React Router](https://reacttraining.com/react-router/).
6 | **No jQuery and Bootstrap!**
7 |
8 | **This version uses React 16.14.0, React Router v5, MaterialUI v4, built with React Hooks and React Context (No Redux)**
9 |
10 |
11 | 
12 |
13 | ## Full Version
14 |
15 | React Admin is a React template built with Material-UI
16 |
17 | ## Features
18 |
19 | - [X] React (**18.2.0**)
20 | - [X] React Hooks
21 | - [X] React Context
22 | - [X] **No jQuery and Bootstrap!**
23 | - [X] Mobile friendly layout (responsive)
24 | - [X] Create-react-app under the hood
25 | - [X] React Router v5
26 | - [X] Material-UI v4
27 | - [X] Modular Architecture
28 | - [X] CSS-in-JS styles
29 | - [X] Webpack build
30 | - [X] Stylish & clean
31 | - [ ] Authentication
32 |
33 | ## Pages
34 |
35 | We have implemented some basic pages, so you can see our template in action.
36 |
37 | - [X] Dashboard
38 | - [ ] Typography
39 | - [X] Tables
40 | - [ ] Notifications
41 | - [X] Charts
42 | - [X] Icons
43 | - [ ] Maps
44 | - [ ] Login
45 | - [ ] Error
46 |
47 | ## Quick Start
48 |
49 | #### 1. Get the latest version
50 |
51 | You can start by cloning the latest version of React Dashboard on your
52 | local machine by running:
53 |
54 | ```shell
55 | $ git clone https://github.com/zykarsolutions/React-Material-UI-Admin.git MyApp
56 |
57 | $ cd MyApp
58 | ```
59 |
60 | #### 2. Run `yarn install`
61 | Install Yarn (npm install --global yarn).
62 |
63 | This will install both run-time project dependencies and developer tools listed
64 | in [package.json](package.json) file.
65 |
66 | #### 3. Run `yarn start`
67 |
68 | Runs the app in the development mode.
69 |
70 | Open http://localhost:3000 to view it in the browser. Whenever you modify any of the source files inside the `/src` folder,
71 | the module bundler ([Webpack](http://webpack.github.io/)) will recompile the
72 | app on the fly and refresh all the connected browsers.
73 |
74 | #### 4. Run `yarn build`
75 |
76 | Builds the app for production to the build folder.
77 | It correctly bundles React in production mode and optimizes the build for the best performance.
78 |
79 | The build is minified and the filenames include the hashes.
80 | Your app is ready to be deployed!
81 |
82 |
83 | ## Premium themes
84 |
85 | Looking for custome theme development? Check out more [web app templates at zykarsolutions.com](https://zykarsolutions.com/services/design-development/).
86 |
87 | ## License
88 |
89 | [MIT](https://github.com/zykarsolutions/React-Material-UI-Admin/blob/main/LICENSE.md).
90 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "admin",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@emotion/react": "^11.11.4",
7 | "@emotion/styled": "^11.11.5",
8 | "@mui/icons-material": "^5.16.1",
9 | "@mui/material": "^5.16.1",
10 | "@mui/x-data-grid": "^7.10.0",
11 | "@testing-library/jest-dom": "^6.4.6",
12 | "@testing-library/react": "^16.0.0",
13 | "@testing-library/user-event": "^14.5.2",
14 | "react": "^18.3.1",
15 | "react-circular-progressbar": "^2.1.0",
16 | "react-dom": "^18.3.1",
17 | "react-router-dom": "^6.24.1",
18 | "react-scripts": "^5.0.1",
19 | "recharts": "^2.12.7",
20 | "sass": "^1.77.8",
21 | "web-vitals": "^4.2.1"
22 | },
23 | "scripts": {
24 | "start": "react-scripts start",
25 | "build": "react-scripts build",
26 | "test": "react-scripts test",
27 | "eject": "react-scripts eject"
28 | },
29 | "eslintConfig": {
30 | "extends": [
31 | "react-app",
32 | "react-app/jest"
33 | ]
34 | },
35 | "browserslist": {
36 | "production": [
37 | ">0.2%",
38 | "not dead",
39 | "not op_mini all"
40 | ],
41 | "development": [
42 | "last 1 chrome version",
43 | "last 1 firefox version",
44 | "last 1 safari version"
45 | ]
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
17 |
18 |
19 |
28 | Zykar Admin App
29 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import Home from "./pages/home/Home";
2 | import Login from "./pages/login/Login";
3 | import List from "./pages/list/List";
4 | import Single from "./pages/single/Single";
5 | import New from "./pages/new/New";
6 | import { productInputs, userInputs } from "./formSource";
7 | import "./style/dark.scss";
8 | import { useContext} from "react";
9 | import { DarkModeContext} from "./context/darkModeContext";
10 |
11 | import {
12 | BrowserRouter,
13 | Routes,
14 | Route,
15 | } from "react-router-dom";
16 |
17 |
18 | function App() {
19 |
20 | const {darkMode} = useContext(DarkModeContext)
21 |
22 | return (
23 |
24 |
25 |
26 |
27 | } />
28 | }/>
29 |
30 | }/>
31 | }/>
32 | }/>
33 |
34 |
35 | }/>
36 | }/>
37 | }/>
38 |
39 |
40 |
41 |
42 |
43 | );
44 | }
45 |
46 | export default App;
47 |
--------------------------------------------------------------------------------
/src/components/chart/Chart.jsx:
--------------------------------------------------------------------------------
1 | import "./chart.scss"
2 | import { AreaChart, Area, XAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
3 |
4 |
5 | const data = [
6 | { name: "January", Total: 1100},
7 | { name: "February", Total: 2100},
8 | { name: "March", Total: 820},
9 | { name: "April", Total: 1620},
10 | { name: "May", Total: 820},
11 | { name: "June", Total: 1720},
12 | ];
13 |
14 | const Chart = ({aspect , title}) => {
15 | return (
16 |
17 |
{title}
18 |
19 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | )
35 | }
36 |
37 | export default Chart
38 |
--------------------------------------------------------------------------------
/src/components/chart/chart.scss:
--------------------------------------------------------------------------------
1 | .chart{
2 | flex: 4;
3 | -webkit-box-shadow: 2px 4px 10px 1px rgba(0,0,0, 0.47);
4 | box-shadow: 2px 4px 10px 1px rgba(201, 201 , 201 , 0.47);
5 | padding: 10px;
6 | color: gray;
7 |
8 | .title{
9 | margin-bottom: 20px;
10 | }
11 |
12 | .chartGrid{
13 | stroke: rgb(288, 225, 225);
14 | }
15 | }
--------------------------------------------------------------------------------
/src/components/datatable/Datatable.jsx:
--------------------------------------------------------------------------------
1 | import "./datatable.scss";
2 | import { DataGrid } from "@mui/x-data-grid";
3 | import { userColumns, userRows } from "../../datatablesource";
4 | import { Link } from "react-router-dom";
5 | import { useState } from "react";
6 |
7 | const Datatable = () => {
8 | const [data, setData] = useState(userRows);
9 |
10 | const handleDelete = (id) => {
11 | setData(data.filter((item) => item.id !== id));
12 | };
13 |
14 | const actionColumn = [
15 | {
16 | field: "action",
17 | headerName: "Action",
18 | width: 200,
19 | renderCell: (params) => {
20 | return (
21 |
22 |
23 |
View
24 |
25 |
handleDelete(params.row.id)}
28 | >
29 | Delete
30 |
31 |
32 | );
33 | },
34 | },
35 | ];
36 | return (
37 |
38 |
39 | Add New User
40 |
41 | Add New
42 |
43 |
44 |
52 |
53 | );
54 | };
55 |
56 | export default Datatable;
--------------------------------------------------------------------------------
/src/components/datatable/datatable.scss:
--------------------------------------------------------------------------------
1 | .datatable{
2 | height: 600px;
3 | padding: 20px;
4 |
5 | .datatableTitle{
6 | width: 100%;
7 | font-size: 24px;
8 | color: gray;
9 | margin-bottom: 10px;
10 | display: flex;
11 | align-items: center;
12 | justify-content: space-between;
13 |
14 | .link{
15 | text-decoration: none;
16 | color: green;
17 | font-size: 16px;
18 | font-weight: 400;
19 | border: 1px solid green;
20 | padding: 5px;
21 | border-radius: 5px;
22 | cursor: pointer;
23 |
24 | }
25 | }
26 |
27 | .cellWithImg{
28 | display: flex;
29 | align-items: center;
30 |
31 | .cellImg{
32 | width: 32px;
33 | height: 32px;
34 | border-radius: 50%;
35 | object-fit: cover;
36 | margin-right: 20px;
37 | }
38 | }
39 |
40 | .cellWithStatus{
41 | padding: 5px;
42 | border-radius: 5px;
43 |
44 | &.active {
45 | background-color: rgba(0, 128, 0, 0.05);
46 | color: green;
47 | }
48 |
49 | &.pending {
50 | background-color: rgba(255, 217, 0, 0.05);
51 | color: goldenrod;
52 | }
53 |
54 | &.passive {
55 | background-color: rgba(0, 128, 0, 0.05);
56 | color: crimson;
57 | }
58 | }
59 |
60 | .cellAction{
61 | display: flex;
62 | align-items: center;
63 | gap: 15px;
64 |
65 | .viewButton{
66 | padding: 2px 5px;
67 | border-radius: 5px;
68 | color: darkblue;
69 | border: 1px dotted rgba(0, 0, 139, 0.596);
70 | cursor: pointer;
71 | }
72 |
73 | .deleteButton{
74 | padding: 2px 5px;
75 | border-radius: 5px;
76 | color: crimson;
77 | border: 1px dotted rgba(220, 20, 60, 0.6);
78 | cursor: pointer;
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/src/components/featured/Featured.jsx:
--------------------------------------------------------------------------------
1 | import "./featured.scss"
2 | import { CircularProgressbar} from "react-circular-progressbar";
3 | import "react-circular-progressbar/dist/styles.css";
4 | import { KeyboardArrowUpOutlined, MoreVertOutlined } from "@mui/icons-material";
5 | import { KeyboardArrowDown } from "@mui/icons-material";
6 |
7 |
8 | const Featured = () => {
9 | return (
10 |
11 |
12 |
Total Revenue
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Total Sales made today
20 |
ZMK 450
21 |
Previous transcations processing. Last Payments may not be included.
22 |
23 |
30 |
37 |
38 |
Last Month
39 |
43 |
44 |
45 |
46 |
47 | )
48 | }
49 |
50 | export default Featured
51 |
--------------------------------------------------------------------------------
/src/components/featured/featured.scss:
--------------------------------------------------------------------------------
1 | .featured{
2 | flex: 2;
3 | -webkit-box-shadow: 2px 4px 10px 1px rgba(0,0,0, 0.47);
4 | box-shadow: 2px 4px 10px 1px rgba(201, 201 , 201 , 0.47);
5 | padding: 10px;
6 |
7 | .top{
8 | display: flex;
9 | align-items: center;
10 | justify-content: space-between;
11 | color: gray;
12 | }
13 |
14 | .title{
15 | font-size: 16px;
16 | font-weight: 500;
17 | }
18 |
19 | .bottom{
20 | padding: 20px;
21 | display: flex;
22 | flex-direction: column;
23 | align-items: center;
24 | justify-content: center;
25 | gap: 15px;
26 |
27 | .featuredChart{
28 | width: 100px;
29 | height: 100px;
30 | }
31 |
32 | .title{
33 | font-weight: 500;
34 | color: gray;
35 | }
36 |
37 | .amount{
38 | font-size: 300;
39 | }
40 |
41 | .desc{
42 | font-weight: 300;
43 | font-size: 12px;
44 | color: gray;
45 | text-align: center;
46 | }
47 |
48 | .summary{
49 | width: 100%;
50 | display: flex;
51 | align-items: center;
52 | justify-content: space-between;
53 |
54 | .item{
55 | text-align: center;
56 |
57 | .itemTitle{
58 | font-size: 14px;
59 | color: gray;
60 | }
61 |
62 | .itemResult{
63 | display: flex;
64 | align-items: center;
65 | margin-top: 10px;
66 | font-size: 14px;
67 |
68 | &.positive{
69 | color: green;
70 | }
71 |
72 | &.negative{
73 | color: red;
74 | }
75 | }
76 | }
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/src/components/navbar/Navbar.jsx:
--------------------------------------------------------------------------------
1 | import "./navbar.scss"
2 | import SearchOutlinedIcon from "@mui/icons-material/SearchOutlined";
3 | import LanguageOutlinedIcon from "@mui/icons-material/LanguageOutlined";
4 | import DarkModeOutlined from "@mui/icons-material/DarkModeOutlined";
5 | import FullScreenExitOutlinedIcon from "@mui/icons-material/FullscreenExitOutlined"
6 | import NotificationsNoneOutlined from "@mui/icons-material/NotificationsNoneOutlined";
7 | import ChatBubbleOutlinedIcon from "@mui/icons-material/ChatBubbleOutlineOutlined";
8 | import ListOutLinedIcon from "@mui/icons-material/ListOutlined";
9 | import { useContext} from "react";
10 | import { DarkModeContext} from "../../context/darkModeContext";
11 |
12 | const Navbar = () => {
13 |
14 | const {dispatch} = useContext(DarkModeContext)
15 |
16 | return (
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | English
27 |
28 |
29 | dispatch({type:"TOGGLE"})}/>
30 |
31 |
32 |
33 |
34 |
38 |
42 |
43 |
44 |
45 |
46 |

47 |
48 |
49 |
50 |
51 | )
52 | }
53 |
54 | export default Navbar
55 |
--------------------------------------------------------------------------------
/src/components/navbar/navbar.scss:
--------------------------------------------------------------------------------
1 | .navbar{
2 | height: 50px;
3 | border-bottom: 0.5px solid rgb(231, 228 , 228);
4 | display: flex;
5 | align-items: center;
6 | font-size: 14px;
7 | color: #555;
8 |
9 | .wrapper{
10 | width: 100%;
11 | padding: 20px;
12 | display: flex;
13 | align-items: center;
14 | justify-content: space-between;
15 |
16 | .search {
17 | display: flex;
18 | align-items: center;
19 | border: 0.5px solid lightgray;
20 | padding: 3px;
21 |
22 | input {
23 | border: none;
24 | outline: none;
25 | background-color: transparent;
26 |
27 | }
28 | }
29 |
30 | .items{
31 | display: flex;
32 | align-items: center;
33 |
34 | .item{
35 | display: flex;
36 | align-items: center;
37 | margin-right: 20px;
38 | position: relative;
39 |
40 | .icon{
41 | font-size: 20px;
42 | }
43 |
44 | .avatar{
45 | width: 30px;
46 | height: 30px;
47 | border-radius: 50%;
48 | }
49 |
50 | .counter{
51 | width: 15px;
52 | height: 15px;
53 | background-color: #00d748;
54 | border-radius: 50%;
55 | color: white;
56 | display: flex;
57 | align-items: center;
58 | justify-content: center;
59 | font-size: 10px;
60 | font-weight: bold;
61 | position: absolute;
62 | top: -5px;
63 | right: -5px;
64 | }
65 | }
66 | }
67 | }
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/src/components/sidebar/Sidebar.jsx:
--------------------------------------------------------------------------------
1 | import "./sidebar.scss"
2 | import DashboardIcon from '@mui/icons-material/Dashboard';
3 | import PersonOutlineOutlinedIcon from '@mui/icons-material/PersonOutlineOutlined';
4 | import StoreIcon from '@mui/icons-material/Store';
5 | import CreditCardIcon from '@mui/icons-material/CreditCard';
6 | import LocalShippingIcon from '@mui/icons-material/LocalShipping';
7 | import AnalyticsIcon from '@mui/icons-material/Analytics';
8 | import NotificationsNoneOutlinedIcon from '@mui/icons-material/NotificationsNoneOutlined';
9 | import SettingsSystemDaydreamOutlinedIcon from '@mui/icons-material/SettingsSystemDaydreamOutlined';
10 | import PsychologyOutlinedIcon from '@mui/icons-material/PsychologyOutlined';
11 | import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined';
12 | import AccountCircleOutlinedIcon from '@mui/icons-material/AccountCircleOutlined';
13 | import InputOutlinedIcon from '@mui/icons-material/InputOutlined';
14 | import {Link} from "react-router-dom";
15 | import { useContext} from "react";
16 | import { DarkModeContext} from "../../context/darkModeContext";
17 |
18 | const Sidebar = () => {
19 |
20 | const {dispatch} = useContext(DarkModeContext)
21 |
22 | return (
23 |
24 |
25 |
26 |
27 | Zykar Admin
28 |
29 |
30 |
31 |
32 |
33 | MAIN
34 | -
35 |
36 | Dashboard
37 |
38 | LISTS
39 |
40 | -
41 |
42 | Users
43 |
44 |
45 |
46 | -
47 |
48 | Products
49 |
50 |
51 | -
52 |
53 | Orders
54 |
55 | -
56 |
57 | Delivery
58 |
59 | USEFUL LINKS
60 | -
61 |
62 | Stats
63 |
64 | -
65 |
66 | Notifications
67 |
68 | SERVICE
69 | -
70 |
71 | System Health
72 |
73 | -
74 |
75 | Logs
76 |
77 | -
78 |
79 | Settings
80 |
81 | USER
82 | -
83 |
84 | Profile
85 |
86 | -
87 |
88 | Logout
89 |
90 |
91 |
92 |
93 |
94 |
dispatch({ type : "LIGHT"})}>
96 |
97 |
98 |
dispatch({ type : "DARK"})}>
100 |
101 |
102 |
103 |
104 | )
105 | }
106 |
107 | export default Sidebar
108 |
--------------------------------------------------------------------------------
/src/components/sidebar/sidebar.scss:
--------------------------------------------------------------------------------
1 | .sidebar{
2 | flex: 1;
3 | border-right: 0.5px solid rgb(230,227,227);
4 | min-height: 100vh;
5 | background-color: white;
6 |
7 | .top{
8 | height: 50px;
9 | display: flex;
10 | align-items: center;
11 | justify-content: center;
12 |
13 |
14 | .logo{
15 | font-size: 20px;
16 | font-weight: bold;
17 | color: #ff3d57;
18 | }
19 |
20 | }
21 |
22 | hr{
23 | height: 0;
24 | border: 0.5px solid rgb(230,227,227);
25 | }
26 |
27 | .center{
28 | padding-left: 10px;
29 |
30 | ul{
31 | list-style: none;
32 | margin: 0;
33 | padding: 0;
34 |
35 | .title{
36 | font-size: 10px;
37 | font-weight: bold;
38 | color: #999;
39 | margin-top: 15px;
40 | margin-bottom: 5px;
41 | }
42 |
43 | li {
44 | display: flex;
45 | align-items: center;
46 | padding: 5px;
47 | cursor: pointer;
48 |
49 | &:hover{
50 | background-color: #ece8ff;
51 | }
52 |
53 | .icon{
54 | font-size: 18px;
55 | color: #ffca00;
56 | // color: #7451f8;
57 | }
58 |
59 | span{
60 | font-size: 13px;
61 | font-weight: bold;
62 | color: #888;
63 | margin-left: 10px;
64 | }
65 | }
66 | }
67 | }
68 |
69 | .bottom{
70 | display: flex;
71 | margin: 10px;
72 |
73 |
74 | .colorOption{
75 | width: 20px;
76 | height: 20px;
77 | border-radius: 5px;
78 | border: 1px solid #7451f8;
79 | cursor: pointer;
80 | margin: 5px;
81 |
82 | &:nth-child(1){
83 | background-color: whitesmoke;
84 | }
85 | &:nth-child(2){
86 | background-color: #333;
87 | }
88 | }
89 | }
90 |
91 | }
--------------------------------------------------------------------------------
/src/components/table/Table.jsx:
--------------------------------------------------------------------------------
1 | import "./table.scss"
2 | import Table from '@mui/material/Table';
3 | import TableBody from '@mui/material/TableBody';
4 | import TableCell from '@mui/material/TableCell';
5 | import TableContainer from '@mui/material/TableContainer';
6 | import TableHead from '@mui/material/TableHead';
7 | import TableRow from '@mui/material/TableRow';
8 | import Paper from '@mui/material/Paper';
9 |
10 | // Made by Moses Mwila
11 | // for Zykar Solutions Limited
12 |
13 | const List = () => {
14 |
15 | const rows = [
16 | {
17 | id: 11443155,
18 | product: "Accer Nitro 5",
19 | img: "https://m.media-amazon.com/images/I/81bc8mA3nKL._AC_UY327_FMwebp_QL65_.jpg",
20 | customer: "Arlyn Mwila",
21 | date: "1 March",
22 | amount: 987,
23 | method: "Cash On Delivery",
24 | status: "Approved",
25 | },
26 | {
27 | id: 2235235,
28 | product: "Playstation 5",
29 | img: "https://m.media-amazon.com/images/I/81bc8mA3nKL._AC_UY327_FMwebp_QL65_.jpg",
30 | customer: "Jamal Banda",
31 | date: "1 April",
32 | amount: 2057,
33 | method: "Mobile Money",
34 | status: "Pending",
35 | },
36 | {
37 | id: 11443155,
38 | product: "Denim Jeans 5",
39 | img: "https://m.media-amazon.com/images/I/81bc8mA3nKL._AC_UY327_FMwebp_QL65_.jpg",
40 | customer: "Monse Tembo",
41 | date: "1 May",
42 | amount: 687,
43 | method: "Cash On Delivery",
44 | status: "Approved",
45 | },
46 | {
47 | id: 2235235,
48 | product: "Apple Iphone 14",
49 | img: "https://m.media-amazon.com/images/I/81bc8mA3nKL._AC_UY327_FMwebp_QL65_.jpg",
50 | customer: "Arlyn Mwila",
51 | date: "1 June",
52 | amount: 1757,
53 | method: "Online Payment",
54 | status: "Approved",
55 | },
56 | {
57 | id: 2235235,
58 | product: "Apple Iphone 14 Pro",
59 | img: "https://images.pexels.com/photos/428338/pexels-photo-428338.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
60 | customer: "Oscar Bwalya",
61 | date: "1 June",
62 | amount: 7757,
63 | method: "Online Payment",
64 | status: "Approved",
65 | },
66 | ];
67 |
68 |
69 | return (
70 |
71 |
72 |
73 |
74 | Tracking ID
75 | Product
76 | Customer
77 | Date
78 | Amount
79 | Payment Method
80 | Status
81 |
82 |
83 |
84 | {rows.map((row) => (
85 |
87 | {row.id}
88 |
89 |
90 |

91 | {row.product}
92 |
93 |
94 | {row.customer}
95 | {row.date}
96 | {row.amount}
97 | {row.method}
98 |
99 | {row.status}
100 |
101 |
102 | ))}
103 |
104 |
105 |
106 | )
107 | }
108 |
109 | export default List
110 |
--------------------------------------------------------------------------------
/src/components/table/table.scss:
--------------------------------------------------------------------------------
1 | .table{
2 | .cellWrapper{
3 | display: flex;
4 | align-items: center;
5 |
6 | .image{
7 | width: 32px;
8 | height: 32px;
9 | border-radius: 50%;
10 | margin-right: 10px;
11 | object-fit: cover;
12 | }
13 | }
14 |
15 | .status{
16 | padding: 5px;
17 | border-radius: 5px;
18 |
19 | &.Approved{
20 | color: green;
21 | background-color: rgba(0, 128, 0, 0.151);
22 | }
23 | &.Pending {
24 | color: goldenrod;
25 | background-color: rgba(189, 189, 3, 0.103);
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/components/widget/Widget.jsx:
--------------------------------------------------------------------------------
1 | import "./widget.scss";
2 | import KeyboardArrowUp from "@mui/icons-material/KeyboardArrowUp";
3 | import PersonOutlineOutlined from "@mui/icons-material/PersonOutlineOutlined";
4 | import AccountBalanceWalletOutLinedIcon from "@mui/icons-material/AccountBalanceOutlined";
5 | import ShoppingCartOutlinedIcon from "@mui/icons-material/ShoppingCartOutlined";
6 | import MonetizationOnOutlined from "@mui/icons-material/MonetizationOnOutlined";
7 |
8 | const Widget = ({ type }) => {
9 | let data;
10 |
11 | // Temporary
12 | const amount = 100;
13 | const diff = 20;
14 |
15 |
16 | switch (type) {
17 | case "user":
18 | data = {
19 | title: "USERS",
20 | isMoney: false,
21 | link: "See all users",
22 | icon: (
23 |
30 | ),
31 | };
32 | break;
33 | case "order":
34 | data = {
35 | title: "ORDERS",
36 | isMoney: false,
37 | link: "View all orders",
38 | icon: (
39 |
45 | ),
46 | };
47 | break;
48 | case "earning":
49 | data = {
50 | title: "EARNINGS",
51 | isMoney: true,
52 | link: "View net earnings",
53 | icon: (
54 |
60 | ),
61 | };
62 | break;
63 | case "balance":
64 | data = {
65 | title: "BALANCE",
66 | isMoney: true,
67 | link: "See details",
68 | icon: (
69 |
75 | ),
76 | };
77 | break;
78 | default:
79 | break;
80 | }
81 |
82 | return (
83 |
84 |
85 | {data.title}
86 | {data.isMoney && "ZMK"} {amount}
87 | {data.link}
88 |
89 |
90 |
91 |
92 | {diff} %
93 |
94 | {data.icon}
95 |
96 |
97 |
98 | );
99 |
100 | }
101 |
102 | export default Widget
103 |
--------------------------------------------------------------------------------
/src/components/widget/widget.scss:
--------------------------------------------------------------------------------
1 | .widget{
2 | display: flex;
3 | justify-content: space-between;
4 | flex: 1;
5 | padding: 10px;
6 | -webkit-box-shadow: 2px 4px 10px 1px rgba(0,0,0, 0.47);
7 | box-shadow: 2px 4px 10px 1px rgba(201, 201, 201, 0.47);
8 | height: 100px;
9 |
10 | .left, .right{
11 | display: flex;
12 | flex-direction: column;
13 | justify-content: space-between;
14 |
15 | .title{
16 | font-weight: bold;
17 | font-size: 14px;
18 | color: rgb(135, 123, 123);
19 | }
20 |
21 | .counter{
22 | font-size: 28px;
23 | font-weight: 300;
24 | }
25 |
26 | .link{
27 | width: max-content;
28 | font-size: 12px;
29 | border-bottom: 1px solid gray;
30 | }
31 |
32 | .percentage{
33 | display: flex;
34 | align-items: center;
35 | font-size: 14px;
36 |
37 | &.positive{
38 | color: green;
39 | }
40 | &.negative{
41 | color: red;
42 | }
43 | }
44 |
45 | .icon{
46 | font-size: 18px;
47 | padding: 5px;
48 | border-radius: 5px;
49 | align-self: flex-end;
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/src/context/darkModeContext.js:
--------------------------------------------------------------------------------
1 | import { createContext, useReducer } from "react";
2 | import DarkModeReducer from "./darkModeReducer";
3 |
4 | const INITIAL_STATE = {
5 | darkMode: false,
6 | }
7 |
8 |
9 | export const DarkModeContext = createContext(INITIAL_STATE)
10 |
11 | export const DarkModeContextProvider = ({children}) => {
12 | const [state, dispatch] = useReducer(DarkModeReducer, INITIAL_STATE);
13 |
14 | return (
15 |
16 | {children}
17 |
18 | )
19 | }
--------------------------------------------------------------------------------
/src/context/darkModeReducer.js:
--------------------------------------------------------------------------------
1 | const DarkModeReducer = (state, action) => {
2 | switch (action.type) {
3 | case "LIGHT": {
4 | return{
5 | darkMode: false,
6 | };
7 | }
8 | case "DARK": {
9 | return {
10 | darkMode: true,
11 | };
12 | }
13 | case "TOGGLE": {
14 | return {
15 | darkMode: !state.darkMode,
16 | };
17 | }
18 | default:
19 | return state;
20 | }
21 |
22 | };
23 |
24 | export default DarkModeReducer;
--------------------------------------------------------------------------------
/src/datatablesource.js:
--------------------------------------------------------------------------------
1 | export const userColumns = [
2 | { field: "id", headerName: "ID", width: 70 },
3 | {
4 | field: "user",
5 | headerName: "User",
6 | width: 230,
7 | renderCell: (params) => {
8 | return (
9 |
10 |

11 | {params.row.username}
12 |
13 | );
14 | },
15 | },
16 | {
17 | field: "email",
18 | headerName: "Email",
19 | width: 230,
20 | },
21 |
22 | {
23 | field: "age",
24 | headerName: "Age",
25 | width: 100,
26 | },
27 | {
28 | field: "status",
29 | headerName: "Status",
30 | width: 160,
31 | renderCell: (params) => {
32 | return (
33 |
34 | {params.row.status}
35 |
36 | );
37 | },
38 | },
39 | ];
40 |
41 | //temporary data
42 | export const userRows = [
43 | {
44 | id: 1,
45 | username: "Snow",
46 | img: "https://images.pexels.com/photos/1820770/pexels-photo-1820770.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
47 | status: "active",
48 | email: "1snow@gmail.com",
49 | age: 35,
50 | },
51 | {
52 | id: 2,
53 | username: "Jamie Lannister",
54 | img: "https://images.pexels.com/photos/1820770/pexels-photo-1820770.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
55 | email: "2snow@gmail.com",
56 | status: "passive",
57 | age: 42,
58 | },
59 | {
60 | id: 3,
61 | username: "Lannister",
62 | img: "https://images.pexels.com/photos/1820770/pexels-photo-1820770.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
63 | email: "3snow@gmail.com",
64 | status: "pending",
65 | age: 45,
66 | },
67 | {
68 | id: 4,
69 | username: "Stark",
70 | img: "https://images.pexels.com/photos/1820770/pexels-photo-1820770.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
71 | email: "4snow@gmail.com",
72 | status: "active",
73 | age: 16,
74 | },
75 | {
76 | id: 5,
77 | username: "Targaryen",
78 | img: "https://images.pexels.com/photos/1820770/pexels-photo-1820770.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
79 | email: "5snow@gmail.com",
80 | status: "passive",
81 | age: 22,
82 | },
83 | {
84 | id: 6,
85 | username: "Melisandre",
86 | img: "https://images.pexels.com/photos/1820770/pexels-photo-1820770.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
87 | email: "6snow@gmail.com",
88 | status: "active",
89 | age: 15,
90 | },
91 | {
92 | id: 7,
93 | username: "Clifford",
94 | img: "https://images.pexels.com/photos/1820770/pexels-photo-1820770.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
95 | email: "7snow@gmail.com",
96 | status: "passive",
97 | age: 44,
98 | },
99 | {
100 | id: 8,
101 | username: "Frances",
102 | img: "https://images.pexels.com/photos/1820770/pexels-photo-1820770.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
103 | email: "8snow@gmail.com",
104 | status: "active",
105 | age: 36,
106 | },
107 | {
108 | id: 9,
109 | username: "Roxie",
110 | img: "https://images.pexels.com/photos/1820770/pexels-photo-1820770.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
111 | email: "snow@gmail.com",
112 | status: "pending",
113 | age: 65,
114 | },
115 | {
116 | id: 10,
117 | username: "Roxie",
118 | img: "https://images.pexels.com/photos/1820770/pexels-photo-1820770.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
119 | email: "snow@gmail.com",
120 | status: "active",
121 | age: 65,
122 | },
123 | ];
--------------------------------------------------------------------------------
/src/formSource.js:
--------------------------------------------------------------------------------
1 | export const userInputs = [
2 | {
3 | id: 1,
4 | label: "Username",
5 | type: "text",
6 | placeholder: "john_doe",
7 | },
8 | {
9 | id: 2,
10 | label: "Name and surname",
11 | type: "text",
12 | placeholder: "John Doe",
13 | },
14 | {
15 | id: 3,
16 | label: "Email",
17 | type: "mail",
18 | placeholder: "john_doe@gmail.com",
19 | },
20 | {
21 | id: 4,
22 | label: "Phone",
23 | type: "text",
24 | placeholder: "+1 234 567 89",
25 | },
26 | {
27 | id: 5,
28 | label: "Password",
29 | type: "password",
30 | },
31 | {
32 | id: 6,
33 | label: "Address",
34 | type: "text",
35 | placeholder: "Elton St. 216 NewYork",
36 | },
37 | {
38 | id: 7,
39 | label: "Country",
40 | type: "text",
41 | placeholder: "USA",
42 | },
43 | ];
44 |
45 | export const productInputs = [
46 | {
47 | id: 1,
48 | label: "Title",
49 | type: "text",
50 | placeholder: "Apple Macbook Pro",
51 | },
52 | {
53 | id: 2,
54 | label: "Description",
55 | type: "text",
56 | placeholder: "Description",
57 | },
58 | {
59 | id: 3,
60 | label: "Category",
61 | type: "text",
62 | placeholder: "Computers",
63 | },
64 | {
65 | id: 4,
66 | label: "Price",
67 | type: "text",
68 | placeholder: "100",
69 | },
70 | {
71 | id: 5,
72 | label: "Stock",
73 | type: "text",
74 | placeholder: "in stock",
75 | },
76 | ];
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import App from './App';
4 | import { DarkModeContextProvider } from './context/darkModeContext';
5 |
6 | const root = ReactDOM.createRoot(document.getElementById('root'));
7 | root.render(
8 |
9 |
10 |
11 |
12 |
13 | );
14 |
15 | // If you want to start measuring performance in your app, pass a function
16 | // to log results (for example: reportWebVitals(console.log))
17 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
18 | // reportWebVitals();
--------------------------------------------------------------------------------
/src/pages/home/Home.jsx:
--------------------------------------------------------------------------------
1 | import Navbar from "../../components/navbar/Navbar"
2 | import Sidebar from "../../components/sidebar/Sidebar"
3 | import Widget from "../../components/widget/Widget"
4 | import Featured from "../../components/featured/Featured"
5 | import Chart from "../../components/chart/Chart"
6 | import Table from "../../components/table/Table"
7 | import "./home.scss"
8 |
9 |
10 | const Home = () => {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
Latest Transactions
28 |
29 |
30 |
31 |
32 | )
33 | }
34 |
35 | export default Home
--------------------------------------------------------------------------------
/src/pages/home/home.scss:
--------------------------------------------------------------------------------
1 | .home{
2 | display: flex;
3 |
4 | .homeContainer{
5 | flex: 6;
6 |
7 | .widgets , .charts{
8 | display: flex;
9 | padding: 20px;
10 | gap: 20px;
11 | }
12 |
13 | .charts{
14 | padding: 5px 20px;
15 | }
16 |
17 | .listContainer{
18 | -webkit-box-shadow: 2px 4px 10px 1px rgba(0,0,0, 0.47);
19 | box-shadow: 2px 4px 10px 1px rgba(201, 201 , 201 , 0.47);
20 | padding: 10px;
21 | margin: 20px;
22 | }
23 |
24 | .listTitle{
25 | font-weight: 500;
26 | color: gray;
27 | margin-bottom: 25px;
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/pages/list/List.jsx:
--------------------------------------------------------------------------------
1 | import "./list.scss"
2 | import Sidebar from "../../components/sidebar/Sidebar"
3 | import Navbar from "../../components/navbar/Navbar"
4 | import Datatable from "../../components/datatable/Datatable"
5 |
6 | const List = () => {
7 | return (
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | )
16 | }
17 |
18 | export default List
19 |
--------------------------------------------------------------------------------
/src/pages/list/list.scss:
--------------------------------------------------------------------------------
1 | .list{
2 | display: flex;
3 | width: 100%;
4 |
5 | .listContainer{
6 | flex: 6;
7 | }
8 | }
--------------------------------------------------------------------------------
/src/pages/login/Login.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const Login = () => {
4 | return (
5 | Login Page
6 | )
7 | }
8 |
9 | export default Login
10 |
--------------------------------------------------------------------------------
/src/pages/login/login.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zykarsolutions/React-Material-UI-Admin/43b2d29078ae2754034918287ff8c21dc6ce44d1/src/pages/login/login.scss
--------------------------------------------------------------------------------
/src/pages/new/New.jsx:
--------------------------------------------------------------------------------
1 | import "./new.scss";
2 | import Sidebar from "../../components/sidebar/Sidebar";
3 | import Navbar from "../../components/navbar/Navbar";
4 | import { DriveFolderUploadOutlined } from "@mui/icons-material";
5 | import { useState } from "react";
6 |
7 | const New = ({inputs, title}) => {
8 | const [file, setFile] = useState("");
9 |
10 |
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
{title}
19 |
20 |
21 |
22 |

24 |
25 |
47 |
48 |
49 |
50 | )
51 | }
52 |
53 | export default New
--------------------------------------------------------------------------------
/src/pages/new/new.scss:
--------------------------------------------------------------------------------
1 | .new{
2 | display: flex;
3 | width: 100%;
4 |
5 | .newContainer{
6 | flex: 6;
7 |
8 | .top, .bottom {
9 | -webkit-box-shadow: 2px 4px 10 px 1px rgba(0, 0, 0, 0.47);
10 | box-shadow: 2px 4px 10px 1px rgba(201, 201, 201, 0.47);
11 | padding : 10px;
12 | margin: 20px;
13 | display: flex;
14 |
15 | h1{
16 | color: lightgray;
17 | font-size: 20px;
18 | }
19 |
20 | .left{
21 | flex:1;
22 | text-align: center;
23 |
24 | img{
25 | width: 100px;
26 | height: 100px;
27 | border-radius: 50%;
28 | object-fit: contain;
29 | }
30 | }
31 |
32 | .right{
33 | flex: 2;
34 |
35 | form{
36 | display: flex;
37 | flex-wrap: wrap;
38 | gap: 25px;
39 | justify-content: space-around;
40 |
41 | .formInput{
42 | width: 40%;
43 |
44 | label{
45 | display: flex;
46 | align-items: center;
47 | gap: 10px;
48 |
49 | .icon{
50 | cursor: pointer;
51 | }
52 | }
53 |
54 | input{
55 | width:100%;
56 | padding: 5px;
57 | border: none;
58 | border-bottom: 1px solid gray;
59 | }
60 | }
61 |
62 | button{
63 | width: 150px;
64 | padding: 10px;
65 | border: none;
66 | background-color: teal;
67 | color: white;
68 | font-weight: bold;
69 | cursor: pointer;
70 | margin-top: 10px;
71 | }
72 | }
73 | }
74 | }
75 | }
76 | }
--------------------------------------------------------------------------------
/src/pages/single/Single.jsx:
--------------------------------------------------------------------------------
1 | import "./single.scss";
2 | import Sidebar from "../../components/sidebar/Sidebar";
3 | import Navbar from "../../components/navbar/Navbar";
4 | import Chart from "../../components/chart/Chart" ;
5 | import List from "../../components/table/Table";
6 |
7 | const Single = () => {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Edit
16 |
Information
17 |
18 |

20 |
21 |
Jane Doe
22 |
23 | Phone :
24 | +260 XXX XXX XXX
25 |
26 |
27 | Address :
28 | 256 Liberty House, Place Avenue , Zambia
29 |
30 |
31 | Country :
32 | Zambia
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
Last Transactions
43 |
44 |
45 |
46 |
47 | )
48 | }
49 |
50 | export default Single
51 |
--------------------------------------------------------------------------------
/src/pages/single/single.scss:
--------------------------------------------------------------------------------
1 | .single{
2 | display: flex;
3 | width: 100%;
4 |
5 | .singleContainer{
6 | flex: 6;
7 |
8 | .top{
9 | padding: 20px;
10 | display: flex;
11 | gap: 20px;
12 |
13 | .left{
14 | flex: 1;
15 | -webkit-box-shadow: 2px 4px 10px 1px rgba(0,0,0, 0.47);
16 | box-shadow: 2px 4px 10px 1px rgba(201, 201 , 201 , 0.47);
17 | padding: 20px;
18 | position: relative;
19 |
20 | .editButton{
21 | position: absolute;
22 | top: 0;
23 | right: 0;
24 | padding: 5px;
25 | font-size: 12px;
26 | color: #7451f8;
27 | background-color: #7551f818;
28 | cursor: pointer;
29 | border-radius: 0px 0px 0px 5px;
30 | }
31 |
32 |
33 | .item{
34 | display: flex;
35 | gap: 20px ;
36 | }
37 | .itemImg{
38 | width: 100px;
39 | height: 100px;
40 | border-radius: 50%;
41 | object-fit: cover;
42 | }
43 |
44 | .details{
45 | .itemTitle{
46 | margin-bottom: 10px;
47 | color: #555;
48 | }
49 |
50 | .detailItem{
51 | margin-bottom: 10px;
52 | font-size: 14px;
53 |
54 | .itemKey{
55 | font-weight: bold;
56 | color: gray;
57 | margin-right: 5px;
58 | }
59 |
60 | .itemValue{
61 | font-weight: 300;
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
68 | .right {
69 | flex: 2;
70 | }
71 | }
72 |
73 | .bottom{
74 | -webkit-box-shadow: 2px 4px 10px 1px rgba(0,0,0, 0.47);
75 | box-shadow: 2px 4px 10px 1px rgba(201, 201 , 201 , 0.47);
76 | padding: 20px;
77 | margin: 10px 20px;
78 | }
79 |
80 | .title{
81 | font-size: 20px;
82 | color: lightgray;
83 | margin-bottom: 20px;
84 | }
85 | }
86 |
87 |
--------------------------------------------------------------------------------
/src/style/dark.scss:
--------------------------------------------------------------------------------
1 | .dark{
2 | background-color: #111;
3 | color: rgb(156, 156, 156);
4 |
5 | .chartGrid {
6 | stroke: rgba(228, 288, 228, 0.219);
7 | }
8 |
9 | .table{
10 | background-color: #111;
11 |
12 | .tableCell{
13 | color:gray;
14 | }
15 | }
16 |
17 | .navbar{
18 | color: #999;
19 | border-color: #333;
20 |
21 | .search{
22 | border-color: gray;
23 | }
24 | }
25 |
26 | .sidebar{
27 | background-color: #111;
28 | border-color: #333;
29 |
30 | .top{
31 | .logo{
32 | color: #999;
33 | }
34 | }
35 |
36 | hr {
37 | border-color: #333;
38 | }
39 |
40 | ul{
41 | li{
42 | &:hover{
43 | background-color: #333;
44 | }
45 |
46 | .icon{
47 | color: #999;
48 | }
49 | }
50 | }
51 | }
52 |
53 | .datatable{
54 | .datagrid{
55 | color: gray;
56 | border: none;
57 |
58 | .viewButton,
59 | .deleteButton ,
60 | .cellWithStatus {
61 | color: gray;
62 | border: none;
63 | }
64 | }
65 | }
66 | input{
67 | background-color: transparent;
68 | }
69 | }
--------------------------------------------------------------------------------