├── .gitignore
├── .prettierrc
├── LICENSE.txt
├── README.md
├── changelog.md
├── package.json
├── public
├── favicon.ico
├── index.html
└── manifest.json
├── src
├── components
│ ├── App.js
│ ├── Header
│ │ ├── Header.js
│ │ ├── HeaderView.js
│ │ ├── package.json
│ │ └── styles.js
│ ├── Layout
│ │ ├── Layout.js
│ │ ├── package.json
│ │ └── styles.js
│ ├── Notification
│ │ ├── Notification.js
│ │ ├── package.json
│ │ └── styles.js
│ ├── PageTitle
│ │ ├── PageTitle.js
│ │ ├── package.json
│ │ └── styles.js
│ ├── Sidebar
│ │ ├── Sidebar.js
│ │ ├── SidebarView.js
│ │ ├── components
│ │ │ ├── Dot.js
│ │ │ └── SidebarLink
│ │ │ │ ├── SidebarLink.js
│ │ │ │ └── styles.js
│ │ ├── package.json
│ │ └── styles.js
│ ├── UserAvatar
│ │ ├── UserAvatar.js
│ │ ├── package.json
│ │ └── styles.js
│ ├── Widget
│ │ ├── Widget.js
│ │ ├── WidgetView.js
│ │ ├── package.json
│ │ └── styles.js
│ └── Wrappers
│ │ ├── Wrappers.js
│ │ └── package.json
├── context
│ ├── LayoutContext.js
│ └── UserContext.js
├── images
│ └── google.svg
├── index.js
├── pages
│ ├── charts
│ │ ├── Charts.js
│ │ ├── components
│ │ │ ├── ApexHeatmap.js
│ │ │ └── ApexLineChart.js
│ │ └── package.json
│ ├── dashboard
│ │ ├── Dashboard.js
│ │ ├── components
│ │ │ ├── BigStat
│ │ │ │ ├── BigStat.js
│ │ │ │ └── styles.js
│ │ │ └── Table
│ │ │ │ └── Table.js
│ │ ├── mock.js
│ │ ├── package.json
│ │ └── styles.js
│ ├── error
│ │ ├── Error.js
│ │ ├── logo.svg
│ │ ├── package.json
│ │ └── styles.js
│ ├── icons
│ │ ├── Icons.js
│ │ ├── package.json
│ │ └── styles.js
│ ├── login
│ │ ├── Login.js
│ │ ├── logo.svg
│ │ ├── package.json
│ │ └── styles.js
│ ├── maps
│ │ ├── Maps.js
│ │ ├── package.json
│ │ └── styles.js
│ ├── notifications
│ │ ├── Notifications.js
│ │ ├── NotificationsContainer.js
│ │ ├── NotificationsView.js
│ │ ├── package.json
│ │ └── styles.js
│ ├── tables
│ │ ├── Tables.js
│ │ └── package.json
│ └── typography
│ │ ├── Typography.js
│ │ ├── package.json
│ │ └── styles.js
├── serviceWorker.js
└── themes
│ ├── default.js
│ └── index.js
└── 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 | .idea/
8 |
9 | # testing
10 | /coverage
11 |
12 | # production
13 | /build
14 |
15 | # misc
16 | .DS_Store
17 | .env.local
18 | .env.development.local
19 | .env.test.local
20 | .env.production.local
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 2,
3 | "singleQuote": false,
4 | "semi": true,
5 | "trailingComma": "all"
6 | }
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2019 Flatlogic LLC.
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
13 | all 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
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Material Admin — Material-UI Dashboard Template
2 |
3 | Built with [React](https://facebook.github.io/react/), [Material-UI](https://material-ui.com), [React Router](https://reacttraining.com/react-router/).
4 | **No jQuery and Bootstrap!**
5 |
6 | **This version uses React 16.8.6, React Router v5, MaterialUI v4, built with React Hooks and React Context (No Redux)**
7 |
8 | [Demo](https://flatlogic.com/admin-dashboards/react-material-admin/demo). Use any credentials to log in.
9 |
10 | [](https://flatlogic.com/admin-dashboards/react-material-admin/demo)
11 |
12 | ## Full Version
13 |
14 | This is a limited version of [**Full React Material Admin**](https://flatlogic.com/templates/react-material-admin-full/demo) with more components, pages and theme support.
15 |
16 | ## Features
17 |
18 | - React (**16.8.6**)
19 | - React Hooks
20 | - React Context
21 | - **No jQuery and Bootstrap!**
22 | - Mobile friendly layout (responsive)
23 | - Create-react-app under the hood
24 | - React Router v5
25 | - Material-UI v4
26 | - Modular Architecture
27 | - CSS-in-JS styles
28 | - Webpack build
29 | - Stylish, clean, responsive layout
30 | - Authentication
31 |
32 | ## Pages
33 |
34 | We have implemented some basic pages, so you can see our template in action.
35 |
36 | - Dashboard
37 | - Typography
38 | - Tables
39 | - Notifications
40 | - Charts
41 | - Icons
42 | - Maps
43 | - Login
44 | - Error
45 |
46 | ## Quick Start
47 |
48 | #### 1. Get the latest version
49 |
50 | You can start by cloning the latest version of React Dashboard on your
51 | local machine by running:
52 |
53 | ```shell
54 | $ git clone https://github.com/flatlogic/react-material-admin.git MyApp
55 | $ cd MyApp
56 | ```
57 |
58 | #### 2. Run `yarn install`
59 |
60 | This will install both run-time project dependencies and developer tools listed
61 | in [package.json](package.json) file.
62 |
63 | #### 3. Run `yarn start`
64 |
65 | Runs the app in the development mode.
66 |
67 | Open http://localhost:3000 to view it in the browser. Whenever you modify any of the source files inside the `/src` folder,
68 | the module bundler ([Webpack](http://webpack.github.io/)) will recompile the
69 | app on the fly and refresh all the connected browsers.
70 |
71 | #### 4. Run `yarn build`
72 |
73 | Builds the app for production to the build folder.
74 | It correctly bundles React in production mode and optimizes the build for the best performance.
75 |
76 | The build is minified and the filenames include the hashes.
77 | Your app is ready to be deployed!
78 |
79 | ## Support
80 |
81 | For any additional information please refer to [Flatlogic homepage](https://flatlogic.com).
82 |
83 | ## How can I support developers?
84 |
85 | - Star our GitHub repo :star:
86 | - [Tweet about it](https://twitter.com/intent/tweet?text=Amazing%20dashboard%20built%20with%20NodeJS,%20React%20and%20Bootstrap!&url=https://github.com/flatlogic/react-material-template&via=flatlogic).
87 | - Create pull requests, submit bugs, suggest new features or documentation updates :wrench:
88 | - Follow [@flatlogic on Twitter](https://twitter.com/flatlogic).
89 | - Subscribe to Flatlogic newsletter at [flatlogic.com](https://flatlogic.com/)
90 | - Like our page on [Facebook](https://www.facebook.com/flatlogic/) :thumbsup:
91 |
92 | ## More from Flatlogic
93 |
94 | - [React Native Starter](https://github.com/flatlogic/react-native-starter) - 🚀 A powerful react native starter template that bootstraps development of your mobile application
95 | - [Sing App](https://github.com/flatlogic/sing-app) - 💥 Free and open-source admin dashboard template built with Bootstrap 4
96 | - [Awesome Bootstrap Checkboxes & Radios](https://github.com/flatlogic/awesome-bootstrap-checkbox) - ✅ Pure css way to make inputs look prettier
97 | - [React Dashboard](https://github.com/flatlogic/react-dashboard) - 🔥 React Dashboard - isomorphic admin dashboard template with GraphQL
98 | - [Light Blue Dashboard](https://github.com/flatlogic/light-blue-dashboard) - 💦 Free and open-source admin dashboard template built with Bootstrap
99 |
100 | ## Premium themes
101 |
102 | Looking for premium themes and templates? Check out more [admin dashboard templates at flatlogic.com](https://flatlogic.com/admin-dashboards).
103 |
104 | ## License
105 |
106 | [MIT](https://github.com/flatlogic/react-material-dashboard/blob/master/LICENSE.txt).
107 |
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | # [1.2.3]
4 |
5 | ### Updated
6 | - Fixed security vulnerabilities in dependencies
7 |
8 | # [1.2.2]
9 |
10 | ### Updated
11 | - Packages updated
12 |
13 | # [1.2.1]
14 |
15 | ### Updated
16 | - Packages updated
17 |
18 | ### Fixed
19 | - Sign up name type of input
20 | - Dot component size prop
21 | - Performance errors
22 |
23 | # [1.2.0]
24 |
25 | ### Updated
26 | - Packages update
27 | - Link to Full version
28 |
29 | ### Fixed
30 | - User login state improvements
31 |
32 | ## [1.1.0]
33 |
34 | ### New Feactures
35 |
36 | - React v16.8.6
37 | - React Router v5
38 | - new React Hooks
39 | - Material UI v4.3
40 |
41 | Bug fixes
42 |
43 | ## [1.0.0]
44 |
45 | Initial version of the project
46 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-material-admin",
3 | "version": "1.1.0",
4 | "private": true,
5 | "resolutions": {
6 | "websocket-extensions": "^0.1.4",
7 | "node-forge": "^0.10.0",
8 | "node-fetch": "^2.6.1"
9 | },
10 | "dependencies": {
11 | "@material-ui/core": "^4.11.0",
12 | "@material-ui/icons": "^4.2.1",
13 | "@material-ui/styles": "^4.10.0",
14 | "apexcharts": "^3.20.0",
15 | "classnames": "^2.2.6",
16 | "font-awesome": "^4.7.0",
17 | "mui-datatables": "^3.4.1",
18 | "react": "^16.13.1",
19 | "react-apexcharts": "^1.3.7",
20 | "react-dom": "^16.13.1",
21 | "react-google-maps": "^9.4.5",
22 | "react-router-dom": "^5.2.0",
23 | "react-scripts": "3.4.3",
24 | "react-syntax-highlighter": "^13.5.3",
25 | "react-toastify": "^6.0.8",
26 | "recharts": "^1.6.2",
27 | "tinycolor2": "^1.4.1"
28 | },
29 | "scripts": {
30 | "start": "react-scripts start",
31 | "build": "react-scripts build",
32 | "test": "react-scripts test",
33 | "eject": "react-scripts eject"
34 | },
35 | "eslintConfig": {
36 | "extends": "react-app"
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 | "devDependencies": {
51 | "@babel/helper-call-delegate": "^7.11.4",
52 | "prettier": "^2.1.1"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srsedev/react-material-admin/7e257e3e020dcf77d5d3543cb5a7fa93cf4f02d6/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
15 |
16 |
25 | React Material Admin
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React Material Admin",
3 | "name": "React Material Admin is a React Template built with Material-UI",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#536DFE",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { HashRouter, Route, Switch, Redirect } from "react-router-dom";
3 |
4 | // components
5 | import Layout from "./Layout";
6 |
7 | // pages
8 | import Error from "../pages/error";
9 | import Login from "../pages/login";
10 |
11 | // context
12 | import { useUserState } from "../context/UserContext";
13 |
14 | export default function App() {
15 | // global
16 | var { isAuthenticated } = useUserState();
17 |
18 | return (
19 |
20 |
21 | } />
22 | }
26 | />
27 |
28 |
29 |
30 |
31 |
32 | );
33 |
34 | // #######################################################################
35 |
36 | function PrivateRoute({ component, ...rest }) {
37 | return (
38 |
41 | isAuthenticated ? (
42 | React.createElement(component, props)
43 | ) : (
44 |
52 | )
53 | }
54 | />
55 | );
56 | }
57 |
58 | function PublicRoute({ component, ...rest }) {
59 | return (
60 |
63 | isAuthenticated ? (
64 |
69 | ) : (
70 | React.createElement(component, props)
71 | )
72 | }
73 | />
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/components/Header/Header.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | AppBar,
4 | Toolbar,
5 | IconButton,
6 | InputBase,
7 | Menu,
8 | MenuItem,
9 | Fab,
10 | Link
11 | } from "@material-ui/core";
12 | import {
13 | Menu as MenuIcon,
14 | MailOutline as MailIcon,
15 | NotificationsNone as NotificationsIcon,
16 | Person as AccountIcon,
17 | Search as SearchIcon,
18 | Send as SendIcon,
19 | ArrowBack as ArrowBackIcon,
20 | } from "@material-ui/icons";
21 | import classNames from "classnames";
22 |
23 | // styles
24 | import useStyles from "./styles";
25 |
26 | // components
27 | import { Badge, Typography, Button } from "../Wrappers/Wrappers";
28 | import Notification from "../Notification/Notification";
29 | import UserAvatar from "../UserAvatar/UserAvatar";
30 |
31 | // context
32 | import {
33 | useLayoutState,
34 | useLayoutDispatch,
35 | toggleSidebar,
36 | } from "../../context/LayoutContext";
37 | import { useUserDispatch, signOut } from "../../context/UserContext";
38 |
39 | const messages = [
40 | {
41 | id: 0,
42 | variant: "warning",
43 | name: "Jane Hew",
44 | message: "Hey! How is it going?",
45 | time: "9:32",
46 | },
47 | {
48 | id: 1,
49 | variant: "success",
50 | name: "Lloyd Brown",
51 | message: "Check out my new Dashboard",
52 | time: "9:18",
53 | },
54 | {
55 | id: 2,
56 | variant: "primary",
57 | name: "Mark Winstein",
58 | message: "I want rearrange the appointment",
59 | time: "9:15",
60 | },
61 | {
62 | id: 3,
63 | variant: "secondary",
64 | name: "Liana Dutti",
65 | message: "Good news from sale department",
66 | time: "9:09",
67 | },
68 | ];
69 |
70 | const notifications = [
71 | { id: 0, color: "warning", message: "Check out this awesome ticket" },
72 | {
73 | id: 1,
74 | color: "success",
75 | type: "info",
76 | message: "What is the best way to get ...",
77 | },
78 | {
79 | id: 2,
80 | color: "secondary",
81 | type: "notification",
82 | message: "This is just a simple notification",
83 | },
84 | {
85 | id: 3,
86 | color: "primary",
87 | type: "e-commerce",
88 | message: "12 new orders has arrived today",
89 | },
90 | ];
91 |
92 | export default function Header(props) {
93 | var classes = useStyles();
94 |
95 | // global
96 | var layoutState = useLayoutState();
97 | var layoutDispatch = useLayoutDispatch();
98 | var userDispatch = useUserDispatch();
99 |
100 | // local
101 | var [mailMenu, setMailMenu] = useState(null);
102 | var [isMailsUnread, setIsMailsUnread] = useState(true);
103 | var [notificationsMenu, setNotificationsMenu] = useState(null);
104 | var [isNotificationsUnread, setIsNotificationsUnread] = useState(true);
105 | var [profileMenu, setProfileMenu] = useState(null);
106 | var [isSearchOpen, setSearchOpen] = useState(false);
107 |
108 | return (
109 |
110 |
111 | toggleSidebar(layoutDispatch)}
114 | className={classNames(
115 | classes.headerMenuButton,
116 | classes.headerMenuButtonCollapse,
117 | )}
118 | >
119 | {layoutState.isSidebarOpened ? (
120 |
128 | ) : (
129 |
137 | )}
138 |
139 |
140 | React Material Admin
141 |
142 |
143 |
144 |
149 |
setSearchOpen(!isSearchOpen)}
154 | >
155 |
156 |
157 |
164 |
165 | {
170 | setNotificationsMenu(e.currentTarget);
171 | setIsNotificationsUnread(false);
172 | }}
173 | className={classes.headerMenuButton}
174 | >
175 |
179 |
180 |
181 |
182 | {
187 | setMailMenu(e.currentTarget);
188 | setIsMailsUnread(false);
189 | }}
190 | className={classes.headerMenuButton}
191 | >
192 |
196 |
197 |
198 |
199 | setProfileMenu(e.currentTarget)}
205 | >
206 |
207 |
208 |
263 |
281 |
337 |
338 |
339 | );
340 | }
341 |
--------------------------------------------------------------------------------
/src/components/Header/HeaderView.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | AppBar,
4 | Toolbar,
5 | IconButton,
6 | InputBase,
7 | Menu,
8 | MenuItem,
9 | Fab,
10 | withStyles
11 | } from "@material-ui/core";
12 | import {
13 | Menu as MenuIcon,
14 | MailOutline as MailIcon,
15 | NotificationsNone as NotificationsIcon,
16 | Person as AccountIcon,
17 | Search as SearchIcon,
18 | Send as SendIcon,
19 | ArrowBack as ArrowBackIcon
20 | } from "@material-ui/icons";
21 | import { fade } from "@material-ui/core/styles/colorManipulator";
22 | import classNames from "classnames";
23 |
24 | import { Badge, Typography } from "../Wrappers";
25 | import Notification from "../Notification";
26 | import UserAvatar from "../UserAvatar";
27 |
28 | const messages = [
29 | {
30 | id: 0,
31 | variant: "warning",
32 | name: "Jane Hew",
33 | message: "Hey! How is it going?",
34 | time: "9:32"
35 | },
36 | {
37 | id: 1,
38 | variant: "success",
39 | name: "Lloyd Brown",
40 | message: "Check out my new Dashboard",
41 | time: "9:18"
42 | },
43 | {
44 | id: 2,
45 | variant: "primary",
46 | name: "Mark Winstein",
47 | message: "I want rearrange the appointment",
48 | time: "9:15"
49 | },
50 | {
51 | id: 3,
52 | variant: "secondary",
53 | name: "Liana Dutti",
54 | message: "Good news from sale department",
55 | time: "9:09"
56 | }
57 | ];
58 |
59 | const notifications = [
60 | { id: 0, color: "warning", message: "Check out this awesome ticket" },
61 | {
62 | id: 1,
63 | color: "success",
64 | type: "info",
65 | message: "What is the best way to get ..."
66 | },
67 | {
68 | id: 2,
69 | color: "secondary",
70 | type: "notification",
71 | message: "This is just a simple notification"
72 | },
73 | {
74 | id: 3,
75 | color: "primary",
76 | type: "e-commerce",
77 | message: "12 new orders has arrived today"
78 | }
79 | ];
80 |
81 | const Header = ({ classes, isSidebarOpened, toggleSidebar, ...props }) => (
82 |
83 |
84 |
92 | {isSidebarOpened ? (
93 |
98 | ) : (
99 |
104 | )}
105 |
106 | React Material Admin
107 |
108 |
113 |
119 |
120 |
121 |
128 |
129 |
136 |
142 |
143 |
144 |
145 |
152 |
156 |
157 |
158 |
159 |
166 |
167 |
168 |
221 |
239 |
295 |
296 |
297 | );
298 |
299 | const styles = theme => ({
300 | logotype: {
301 | color: "white",
302 | marginLeft: theme.spacing.unit * 2.5,
303 | marginRight: theme.spacing.unit * 2.5,
304 | fontWeight: 500,
305 | fontSize: 18,
306 | whiteSpace: "nowrap",
307 | [theme.breakpoints.down("xs")]: {
308 | display: "none"
309 | }
310 | },
311 | appBar: {
312 | width: "100vw",
313 | zIndex: theme.zIndex.drawer + 1,
314 | transition: theme.transitions.create(["margin"], {
315 | easing: theme.transitions.easing.sharp,
316 | duration: theme.transitions.duration.leavingScreen
317 | })
318 | },
319 | toolbar: {
320 | paddingLeft: theme.spacing.unit * 2,
321 | paddingRight: theme.spacing.unit * 2
322 | },
323 | hide: {
324 | display: "none"
325 | },
326 | grow: {
327 | flexGrow: 1
328 | },
329 | search: {
330 | position: "relative",
331 | borderRadius: 25,
332 | paddingLeft: theme.spacing.unit * 2.5,
333 | width: 36,
334 | backgroundColor: fade(theme.palette.common.black, 0),
335 | transition: theme.transitions.create(["background-color", "width"]),
336 | "&:hover": {
337 | cursor: "pointer",
338 | backgroundColor: fade(theme.palette.common.black, 0.08)
339 | }
340 | },
341 | searchFocused: {
342 | backgroundColor: fade(theme.palette.common.black, 0.08),
343 | width: "100%",
344 | [theme.breakpoints.up("md")]: {
345 | width: 250
346 | }
347 | },
348 | searchIcon: {
349 | width: 36,
350 | right: 0,
351 | height: "100%",
352 | position: "absolute",
353 | display: "flex",
354 | alignItems: "center",
355 | justifyContent: "center",
356 | transition: theme.transitions.create("right"),
357 | "&:hover": {
358 | cursor: "pointer"
359 | }
360 | },
361 | searchIconOpened: {
362 | right: theme.spacing.unit * 1.25
363 | },
364 | inputRoot: {
365 | color: "inherit",
366 | width: "100%"
367 | },
368 | inputInput: {
369 | height: 36,
370 | padding: 0,
371 | paddingRight: 36 + theme.spacing.unit * 1.25,
372 | width: "100%"
373 | },
374 | messageContent: {
375 | display: "flex",
376 | flexDirection: "column"
377 | },
378 | headerMenu: {
379 | marginTop: theme.spacing.unit * 7
380 | },
381 | headerMenuList: {
382 | display: "flex",
383 | flexDirection: "column"
384 | },
385 | headerMenuItem: {
386 | "&:hover, &:focus": {
387 | backgroundColor: theme.palette.primary.main,
388 | color: "white"
389 | }
390 | },
391 | headerMenuButton: {
392 | marginLeft: theme.spacing.unit * 2,
393 | padding: theme.spacing.unit / 2
394 | },
395 | headerMenuButtonCollapse: {
396 | marginRight: theme.spacing.unit * 2
397 | },
398 | headerIcon: {
399 | fontSize: 28,
400 | color: "rgba(255, 255, 255, 0.35)"
401 | },
402 | headerIconCollapse: {
403 | color: "white"
404 | },
405 | profileMenu: {
406 | minWidth: 265
407 | },
408 | profileMenuUser: {
409 | display: "flex",
410 | flexDirection: "column",
411 | padding: theme.spacing.unit * 2
412 | },
413 | profileMenuItem: {
414 | color: theme.palette.text.hint
415 | },
416 | profileMenuIcon: {
417 | marginRight: theme.spacing.unit * 2,
418 | color: theme.palette.text.hint
419 | },
420 | profileMenuLink: {
421 | fontSize: 16,
422 | textDecoration: "none",
423 | "&:hover": {
424 | cursor: "pointer"
425 | }
426 | },
427 | messageNotification: {
428 | height: "auto",
429 | display: "flex",
430 | alignItems: "center",
431 | "&:hover, &:focus": {
432 | backgroundColor: theme.palette.background.light
433 | }
434 | },
435 | messageNotificationSide: {
436 | display: "flex",
437 | flexDirection: "column",
438 | alignItems: "center",
439 | marginRight: theme.spacing.unit * 2
440 | },
441 | messageNotificationBodySide: {
442 | alignItems: "flex-start",
443 | marginRight: 0
444 | },
445 | sendMessageButton: {
446 | margin: theme.spacing.unit * 4,
447 | marginTop: theme.spacing.unit * 2,
448 | marginBottom: theme.spacing.unit * 2,
449 | textTransform: "none"
450 | },
451 | sendButtonIcon: {
452 | marginLeft: theme.spacing.unit * 2
453 | }
454 | });
455 |
456 | export default withStyles(styles)(Header);
457 |
--------------------------------------------------------------------------------
/src/components/Header/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Header",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "Header.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/Header/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 | import { fade } from "@material-ui/core/styles/colorManipulator";
3 |
4 | export default makeStyles(theme => ({
5 | logotype: {
6 | color: "white",
7 | marginLeft: theme.spacing(2.5),
8 | marginRight: theme.spacing(2.5),
9 | fontWeight: 500,
10 | fontSize: 18,
11 | whiteSpace: "nowrap",
12 | [theme.breakpoints.down("xs")]: {
13 | display: "none",
14 | },
15 | },
16 | appBar: {
17 | width: "100vw",
18 | zIndex: theme.zIndex.drawer + 1,
19 | transition: theme.transitions.create(["margin"], {
20 | easing: theme.transitions.easing.sharp,
21 | duration: theme.transitions.duration.leavingScreen,
22 | }),
23 | },
24 | toolbar: {
25 | paddingLeft: theme.spacing(2),
26 | paddingRight: theme.spacing(2),
27 | },
28 | hide: {
29 | display: "none",
30 | },
31 | grow: {
32 | flexGrow: 1,
33 | },
34 | search: {
35 | position: "relative",
36 | borderRadius: 25,
37 | paddingLeft: theme.spacing(2.5),
38 | width: 36,
39 | backgroundColor: fade(theme.palette.common.black, 0),
40 | transition: theme.transitions.create(["background-color", "width"]),
41 | "&:hover": {
42 | cursor: "pointer",
43 | backgroundColor: fade(theme.palette.common.black, 0.08),
44 | },
45 | },
46 | searchFocused: {
47 | backgroundColor: fade(theme.palette.common.black, 0.08),
48 | width: "100%",
49 | [theme.breakpoints.up("md")]: {
50 | width: 250,
51 | },
52 | },
53 | searchIcon: {
54 | width: 36,
55 | right: 0,
56 | height: "100%",
57 | position: "absolute",
58 | display: "flex",
59 | alignItems: "center",
60 | justifyContent: "center",
61 | transition: theme.transitions.create("right"),
62 | "&:hover": {
63 | cursor: "pointer",
64 | },
65 | },
66 | searchIconOpened: {
67 | right: theme.spacing(1.25),
68 | },
69 | inputRoot: {
70 | color: "inherit",
71 | width: "100%",
72 | },
73 | inputInput: {
74 | height: 36,
75 | padding: 0,
76 | paddingRight: 36 + theme.spacing(1.25),
77 | width: "100%",
78 | },
79 | messageContent: {
80 | display: "flex",
81 | flexDirection: "column",
82 | },
83 | headerMenu: {
84 | marginTop: theme.spacing(7),
85 | },
86 | headerMenuList: {
87 | display: "flex",
88 | flexDirection: "column",
89 | },
90 | headerMenuItem: {
91 | "&:hover, &:focus": {
92 | backgroundColor: theme.palette.primary.main,
93 | color: "white",
94 | },
95 | },
96 | headerMenuButton: {
97 | marginLeft: theme.spacing(2),
98 | padding: theme.spacing(0.5),
99 | },
100 | headerMenuButtonCollapse: {
101 | marginRight: theme.spacing(2),
102 | },
103 | headerIcon: {
104 | fontSize: 28,
105 | color: "rgba(255, 255, 255, 0.35)",
106 | },
107 | headerIconCollapse: {
108 | color: "white",
109 | },
110 | profileMenu: {
111 | minWidth: 265,
112 | },
113 | profileMenuUser: {
114 | display: "flex",
115 | flexDirection: "column",
116 | padding: theme.spacing(2),
117 | },
118 | profileMenuItem: {
119 | color: theme.palette.text.hint,
120 | },
121 | profileMenuIcon: {
122 | marginRight: theme.spacing(2),
123 | color: theme.palette.text.hint,
124 | },
125 | profileMenuLink: {
126 | fontSize: 16,
127 | textDecoration: "none",
128 | "&:hover": {
129 | cursor: "pointer",
130 | },
131 | },
132 | messageNotification: {
133 | height: "auto",
134 | display: "flex",
135 | alignItems: "center",
136 | "&:hover, &:focus": {
137 | backgroundColor: theme.palette.background.light,
138 | },
139 | },
140 | messageNotificationSide: {
141 | display: "flex",
142 | flexDirection: "column",
143 | alignItems: "center",
144 | marginRight: theme.spacing(2),
145 | },
146 | messageNotificationBodySide: {
147 | alignItems: "flex-start",
148 | marginRight: 0,
149 | },
150 | sendMessageButton: {
151 | margin: theme.spacing(4),
152 | marginTop: theme.spacing(2),
153 | marginBottom: theme.spacing(2),
154 | textTransform: "none",
155 | },
156 | sendButtonIcon: {
157 | marginLeft: theme.spacing(2),
158 | },
159 | }));
160 |
--------------------------------------------------------------------------------
/src/components/Layout/Layout.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | Route,
4 | Switch,
5 | Redirect,
6 | withRouter,
7 | } from "react-router-dom";
8 | import classnames from "classnames";
9 |
10 | // styles
11 | import useStyles from "./styles";
12 |
13 | // components
14 | import Header from "../Header";
15 | import Sidebar from "../Sidebar";
16 |
17 | // pages
18 | import Dashboard from "../../pages/dashboard";
19 | import Typography from "../../pages/typography";
20 | import Notifications from "../../pages/notifications";
21 | import Maps from "../../pages/maps";
22 | import Tables from "../../pages/tables";
23 | import Icons from "../../pages/icons";
24 | import Charts from "../../pages/charts";
25 |
26 | // context
27 | import { useLayoutState } from "../../context/LayoutContext";
28 |
29 | function Layout(props) {
30 | var classes = useStyles();
31 |
32 | // global
33 | var layoutState = useLayoutState();
34 |
35 | return (
36 |
37 | <>
38 |
39 |
40 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | }
55 | />
56 |
57 |
58 |
59 |
60 |
61 | >
62 |
63 | );
64 | }
65 |
66 | export default withRouter(Layout);
67 |
--------------------------------------------------------------------------------
/src/components/Layout/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Layout",
3 | "version": "1.0.0",
4 | "private": true,
5 | "main": "Layout.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/Layout/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | root: {
5 | display: "flex",
6 | maxWidth: "100vw",
7 | overflowX: "hidden",
8 | },
9 | content: {
10 | flexGrow: 1,
11 | padding: theme.spacing(3),
12 | width: `calc(100vw - 240px)`,
13 | minHeight: "100vh",
14 | },
15 | contentShift: {
16 | width: `calc(100vw - ${240 + theme.spacing(6)}px)`,
17 | transition: theme.transitions.create(["width", "margin"], {
18 | easing: theme.transitions.easing.sharp,
19 | duration: theme.transitions.duration.enteringScreen,
20 | }),
21 | },
22 | fakeToolbar: {
23 | ...theme.mixins.toolbar,
24 | },
25 | }));
26 |
--------------------------------------------------------------------------------
/src/components/Notification/Notification.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Button } from "@material-ui/core";
3 | import {
4 | NotificationsNone as NotificationsIcon,
5 | ThumbUp as ThumbUpIcon,
6 | ShoppingCart as ShoppingCartIcon,
7 | LocalOffer as TicketIcon,
8 | BusinessCenter as DeliveredIcon,
9 | SmsFailed as FeedbackIcon,
10 | DiscFull as DiscIcon,
11 | Email as MessageIcon,
12 | Report as ReportIcon,
13 | Error as DefenceIcon,
14 | AccountBox as CustomerIcon,
15 | Done as ShippedIcon,
16 | Publish as UploadIcon,
17 | } from "@material-ui/icons";
18 | import { useTheme } from "@material-ui/styles";
19 | import classnames from "classnames";
20 | import tinycolor from "tinycolor2";
21 |
22 | // styles
23 | import useStyles from "./styles";
24 |
25 | // components
26 | import { Typography } from "../Wrappers";
27 |
28 | const typesIcons = {
29 | "e-commerce": ,
30 | notification: ,
31 | offer: ,
32 | info: ,
33 | message: ,
34 | feedback: ,
35 | customer: ,
36 | shipped: ,
37 | delivered: ,
38 | defence: ,
39 | report: ,
40 | upload: ,
41 | disc: ,
42 | };
43 |
44 | export default function Notification({ variant, ...props }) {
45 | var classes = useStyles();
46 | var theme = useTheme();
47 |
48 | const icon = getIconByType(props.type);
49 | const iconWithStyles = React.cloneElement(icon, {
50 | classes: {
51 | root: classes.notificationIcon,
52 | },
53 | style: {
54 | color:
55 | variant !== "contained" &&
56 | theme.palette[props.color] &&
57 | theme.palette[props.color].main,
58 | },
59 | });
60 |
61 | return (
62 |
74 |
88 | {iconWithStyles}
89 |
90 |
91 |
98 | {props.message}
99 |
100 | {props.extraButton && props.extraButtonClick && (
101 |
108 | )}
109 |
110 |
111 | );
112 | }
113 |
114 | // ####################################################################
115 | function getIconByType(type = "offer") {
116 | return typesIcons[type];
117 | }
118 |
--------------------------------------------------------------------------------
/src/components/Notification/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Notification",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "Notification.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/Notification/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | notificationContainer: {
5 | display: "flex",
6 | alignItems: "center",
7 | },
8 | notificationContained: {
9 | borderRadius: 45,
10 | height: 45,
11 | boxShadow: theme.customShadows.widgetDark,
12 | },
13 | notificationContainedShadowless: {
14 | boxShadow: "none",
15 | },
16 | notificationIconContainer: {
17 | minWidth: 45,
18 | height: 45,
19 | borderRadius: 45,
20 | display: "flex",
21 | alignItems: "center",
22 | justifyContent: "center",
23 | fontSize: 24,
24 | },
25 | notificationIconContainerContained: {
26 | fontSize: 18,
27 | color: "#FFFFFF80",
28 | },
29 | notificationIconContainerRounded: {
30 | marginRight: theme.spacing(2),
31 | },
32 | containedTypography: {
33 | color: "white",
34 | },
35 | messageContainer: {
36 | display: "flex",
37 | alignItems: "center",
38 | justifyContent: "space-between",
39 | flexGrow: 1,
40 | },
41 | extraButton: {
42 | color: "white",
43 | "&:hover, &:focus": {
44 | background: "transparent",
45 | },
46 | },
47 | }));
48 |
--------------------------------------------------------------------------------
/src/components/PageTitle/PageTitle.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Button } from "@material-ui/core";
3 |
4 | // styles
5 | import useStyles from "./styles";
6 |
7 | // components
8 | import { Typography } from "../Wrappers";
9 |
10 | export default function PageTitle(props) {
11 | var classes = useStyles();
12 |
13 | return (
14 |
15 |
16 | {props.title}
17 |
18 | {props.button && (
19 |
27 | )}
28 |
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/src/components/PageTitle/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "PageTitle",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "PageTitle.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/PageTitle/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | pageTitleContainer: {
5 | display: "flex",
6 | justifyContent: "space-between",
7 | marginBottom: theme.spacing(4),
8 | marginTop: theme.spacing(5),
9 | },
10 | typo: {
11 | color: theme.palette.text.hint,
12 | },
13 | button: {
14 | boxShadow: theme.customShadows.widget,
15 | textTransform: "none",
16 | "&:active": {
17 | boxShadow: theme.customShadows.widgetWide,
18 | },
19 | },
20 | }));
21 |
--------------------------------------------------------------------------------
/src/components/Sidebar/Sidebar.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Drawer, IconButton, List } from "@material-ui/core";
3 | import {
4 | Home as HomeIcon,
5 | NotificationsNone as NotificationsIcon,
6 | FormatSize as TypographyIcon,
7 | FilterNone as UIElementsIcon,
8 | BorderAll as TableIcon,
9 | QuestionAnswer as SupportIcon,
10 | LibraryBooks as LibraryIcon,
11 | HelpOutline as FAQIcon,
12 | ArrowBack as ArrowBackIcon,
13 | } from "@material-ui/icons";
14 | import { useTheme } from "@material-ui/styles";
15 | import { withRouter } from "react-router-dom";
16 | import classNames from "classnames";
17 |
18 | // styles
19 | import useStyles from "./styles";
20 |
21 | // components
22 | import SidebarLink from "./components/SidebarLink/SidebarLink";
23 | import Dot from "./components/Dot";
24 |
25 | // context
26 | import {
27 | useLayoutState,
28 | useLayoutDispatch,
29 | toggleSidebar,
30 | } from "../../context/LayoutContext";
31 |
32 | const structure = [
33 | { id: 0, label: "Dashboard", link: "/app/dashboard", icon: },
34 | {
35 | id: 1,
36 | label: "Typography",
37 | link: "/app/typography",
38 | icon: ,
39 | },
40 | { id: 2, label: "Tables", link: "/app/tables", icon: },
41 | {
42 | id: 3,
43 | label: "Notifications",
44 | link: "/app/notifications",
45 | icon: ,
46 | },
47 | {
48 | id: 4,
49 | label: "UI Elements",
50 | link: "/app/ui",
51 | icon: ,
52 | children: [
53 | { label: "Icons", link: "/app/ui/icons" },
54 | { label: "Charts", link: "/app/ui/charts" },
55 | { label: "Maps", link: "/app/ui/maps" },
56 | ],
57 | },
58 | { id: 5, type: "divider" },
59 | { id: 6, type: "title", label: "HELP" },
60 | { id: 7, label: "Library", link: "", icon: },
61 | { id: 8, label: "Support", link: "", icon: },
62 | { id: 9, label: "FAQ", link: "", icon: },
63 | { id: 10, type: "divider" },
64 | { id: 11, type: "title", label: "PROJECTS" },
65 | {
66 | id: 12,
67 | label: "My recent",
68 | link: "",
69 | icon: ,
70 | },
71 | {
72 | id: 13,
73 | label: "Starred",
74 | link: "",
75 | icon: ,
76 | },
77 | {
78 | id: 14,
79 | label: "Background",
80 | link: "",
81 | icon: ,
82 | },
83 | ];
84 |
85 | function Sidebar({ location }) {
86 | var classes = useStyles();
87 | var theme = useTheme();
88 |
89 | // global
90 | var { isSidebarOpened } = useLayoutState();
91 | var layoutDispatch = useLayoutDispatch();
92 |
93 | // local
94 | var [isPermanent, setPermanent] = useState(true);
95 |
96 | useEffect(function() {
97 | window.addEventListener("resize", handleWindowWidthChange);
98 | handleWindowWidthChange();
99 | return function cleanup() {
100 | window.removeEventListener("resize", handleWindowWidthChange);
101 | };
102 | });
103 |
104 | return (
105 |
119 |
120 |
121 |
toggleSidebar(layoutDispatch)}>
122 |
127 |
128 |
129 |
130 | {structure.map(link => (
131 |
137 | ))}
138 |
139 |
140 | );
141 |
142 | // ##################################################################
143 | function handleWindowWidthChange() {
144 | var windowWidth = window.innerWidth;
145 | var breakpointWidth = theme.breakpoints.values.md;
146 | var isSmallScreen = windowWidth < breakpointWidth;
147 |
148 | if (isSmallScreen && isPermanent) {
149 | setPermanent(false);
150 | } else if (!isSmallScreen && !isPermanent) {
151 | setPermanent(true);
152 | }
153 | }
154 | }
155 |
156 | export default withRouter(Sidebar);
157 |
--------------------------------------------------------------------------------
/src/components/Sidebar/SidebarView.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Drawer,
4 | IconButton,
5 | List,
6 | withStyles } from "@material-ui/core";
7 | import {
8 | Home as HomeIcon,
9 | NotificationsNone as NotificationsIcon,
10 | FormatSize as TypographyIcon,
11 | FilterNone as UIElementsIcon,
12 | BorderAll as TableIcon,
13 | QuestionAnswer as SupportIcon,
14 | LibraryBooks as LibraryIcon,
15 | HelpOutline as FAQIcon,
16 | ArrowBack as ArrowBackIcon,
17 | } from "@material-ui/icons";
18 | import classNames from 'classnames';
19 |
20 | import SidebarLink from './components/SidebarLink/SidebarLinkContainer';
21 | import Dot from './components/Dot';
22 |
23 | const structure = [
24 | { id: 0, label: 'Dashboard', link: '/app/dashboard', icon: },
25 | { id: 1, label: 'Typography', link: '/app/typography', icon: },
26 | { id: 2, label: 'Tables', link: '/app/tables', icon: },
27 | { id: 3, label: 'Notifications', link: '/app/notifications', icon: },
28 | {
29 | id: 4,
30 | label: 'UI Elements',
31 | link: '/app/ui',
32 | icon: ,
33 | children: [
34 | { label: 'Icons', link: '/app/ui/icons' },
35 | { label: 'Charts', link: '/app/ui/charts' },
36 | { label: 'Maps', link: '/app/ui/maps' },
37 | ],
38 | },
39 | { id: 5, type: 'divider' },
40 | { id: 6, type: 'title', label: 'HELP' },
41 | { id: 7, label: 'Library', link: '', icon: },
42 | { id: 8, label: 'Support', link: '', icon: },
43 | { id: 9, label: 'FAQ', link: '', icon: },
44 | { id: 10, type: 'divider' },
45 | { id: 11, type: 'title', label: 'PROJECTS' },
46 | { id: 12, label: 'My recent', link: '', icon: },
47 | { id: 13, label: 'Starred', link: '', icon: },
48 | { id: 14, label: 'Background', link: '', icon: },
49 | ];
50 |
51 | const SidebarView = ({ classes, theme, toggleSidebar, isSidebarOpened, isPermanent, location }) => {
52 | return (
53 |
67 |
74 |
75 | {structure.map(link => )}
76 |
77 |
78 | );
79 | }
80 |
81 | const drawerWidth = 240;
82 |
83 | const styles = theme => ({
84 | menuButton: {
85 | marginLeft: 12,
86 | marginRight: 36,
87 | },
88 | hide: {
89 | display: 'none',
90 | },
91 | drawer: {
92 | width: drawerWidth,
93 | flexShrink: 0,
94 | whiteSpace: 'nowrap',
95 | top: theme.spacing.unit * 8,
96 | [theme.breakpoints.down("sm")]: {
97 | top: 0,
98 | }
99 | },
100 | drawerOpen: {
101 | width: drawerWidth,
102 | transition: theme.transitions.create('width', {
103 | easing: theme.transitions.easing.sharp,
104 | duration: theme.transitions.duration.enteringScreen,
105 | }),
106 | },
107 | drawerClose: {
108 | transition: theme.transitions.create('width', {
109 | easing: theme.transitions.easing.sharp,
110 | duration: theme.transitions.duration.leavingScreen,
111 | }),
112 | overflowX: 'hidden',
113 | width: theme.spacing.unit * 7 + 40,
114 | [theme.breakpoints.down("sm")]: {
115 | width: drawerWidth,
116 | }
117 | },
118 | toolbar: {
119 | ...theme.mixins.toolbar,
120 | [theme.breakpoints.down("sm")]: {
121 | display: 'none',
122 | }
123 | },
124 | content: {
125 | flexGrow: 1,
126 | padding: theme.spacing.unit * 3,
127 | },
128 | mobileBackButton: {
129 | marginTop: theme.spacing.unit * .5,
130 | marginLeft: theme.spacing.unit * 3,
131 | [theme.breakpoints.only("sm")]: {
132 | marginTop: theme.spacing.unit * .625,
133 | },
134 | [theme.breakpoints.up("md")]: {
135 | display: 'none',
136 | }
137 | }
138 | });
139 |
140 | export default withStyles(styles, { withTheme: true })(SidebarView);
141 |
--------------------------------------------------------------------------------
/src/components/Sidebar/components/Dot.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { makeStyles, useTheme } from "@material-ui/styles";
3 | import classnames from "classnames";
4 |
5 | // styles
6 | var useStyles = makeStyles(theme => ({
7 | dotBase: {
8 | width: 8,
9 | height: 8,
10 | backgroundColor: theme.palette.text.hint,
11 | borderRadius: "50%",
12 | transition: theme.transitions.create("background-color"),
13 | },
14 | dotSmall: {
15 | width: 5,
16 | height: 5
17 | },
18 | dotLarge: {
19 | width: 11,
20 | height: 11,
21 | },
22 | }));
23 |
24 | export default function Dot({ size, color }) {
25 | var classes = useStyles();
26 | var theme = useTheme();
27 |
28 | return (
29 |
39 | );
40 | }
41 |
--------------------------------------------------------------------------------
/src/components/Sidebar/components/SidebarLink/SidebarLink.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | Collapse,
4 | Divider,
5 | List,
6 | ListItem,
7 | ListItemIcon,
8 | ListItemText,
9 | Typography,
10 | } from "@material-ui/core";
11 | import { Inbox as InboxIcon } from "@material-ui/icons";
12 | import { Link } from "react-router-dom";
13 | import classnames from "classnames";
14 |
15 | // styles
16 | import useStyles from "./styles";
17 |
18 | // components
19 | import Dot from "../Dot";
20 |
21 | export default function SidebarLink({
22 | link,
23 | icon,
24 | label,
25 | children,
26 | location,
27 | isSidebarOpened,
28 | nested,
29 | type,
30 | }) {
31 | var classes = useStyles();
32 |
33 | // local
34 | var [isOpen, setIsOpen] = useState(false);
35 | var isLinkActive =
36 | link &&
37 | (location.pathname === link || location.pathname.indexOf(link) !== -1);
38 |
39 | if (type === "title")
40 | return (
41 |
46 | {label}
47 |
48 | );
49 |
50 | if (type === "divider") return ;
51 |
52 | if (!children)
53 | return (
54 |
67 |
72 | {nested ? : icon}
73 |
74 |
83 |
84 | );
85 |
86 | return (
87 | <>
88 |
96 |
101 | {icon ? icon : }
102 |
103 |
112 |
113 | {children && (
114 |
120 |
121 | {children.map(childrenLink => (
122 |
130 | ))}
131 |
132 |
133 | )}
134 | >
135 | );
136 |
137 | // ###########################################################
138 |
139 | function toggleCollapse(e) {
140 | if (isSidebarOpened) {
141 | e.preventDefault();
142 | setIsOpen(!isOpen);
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/src/components/Sidebar/components/SidebarLink/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | link: {
5 | textDecoration: "none",
6 | "&:hover, &:focus": {
7 | backgroundColor: theme.palette.background.light,
8 | },
9 | },
10 | linkActive: {
11 | backgroundColor: theme.palette.background.light,
12 | },
13 | linkNested: {
14 | paddingLeft: 0,
15 | "&:hover, &:focus": {
16 | backgroundColor: "#FFFFFF",
17 | },
18 | },
19 | linkIcon: {
20 | marginRight: theme.spacing(1),
21 | color: theme.palette.text.secondary + "99",
22 | transition: theme.transitions.create("color"),
23 | width: 24,
24 | display: "flex",
25 | justifyContent: "center",
26 | },
27 | linkIconActive: {
28 | color: theme.palette.primary.main,
29 | },
30 | linkText: {
31 | padding: 0,
32 | color: theme.palette.text.secondary + "CC",
33 | transition: theme.transitions.create(["opacity", "color"]),
34 | fontSize: 16,
35 | },
36 | linkTextActive: {
37 | color: theme.palette.text.primary,
38 | },
39 | linkTextHidden: {
40 | opacity: 0,
41 | },
42 | nestedList: {
43 | paddingLeft: theme.spacing(2) + 30,
44 | },
45 | sectionTitle: {
46 | marginLeft: theme.spacing(4.5),
47 | marginTop: theme.spacing(2),
48 | marginBottom: theme.spacing(2),
49 | },
50 | divider: {
51 | marginTop: theme.spacing(2),
52 | marginBottom: theme.spacing(4),
53 | height: 1,
54 | backgroundColor: "#D8D8D880",
55 | },
56 | }));
57 |
--------------------------------------------------------------------------------
/src/components/Sidebar/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Sidebar",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "Sidebar.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/Sidebar/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | const drawerWidth = 240;
4 |
5 | export default makeStyles(theme => ({
6 | menuButton: {
7 | marginLeft: 12,
8 | marginRight: 36,
9 | },
10 | hide: {
11 | display: "none",
12 | },
13 | drawer: {
14 | width: drawerWidth,
15 | flexShrink: 0,
16 | whiteSpace: "nowrap",
17 | },
18 | drawerOpen: {
19 | width: drawerWidth,
20 | transition: theme.transitions.create("width", {
21 | easing: theme.transitions.easing.sharp,
22 | duration: theme.transitions.duration.enteringScreen,
23 | }),
24 | },
25 | drawerClose: {
26 | transition: theme.transitions.create("width", {
27 | easing: theme.transitions.easing.sharp,
28 | duration: theme.transitions.duration.leavingScreen,
29 | }),
30 | overflowX: "hidden",
31 | width: theme.spacing(7) + 40,
32 | [theme.breakpoints.down("sm")]: {
33 | width: drawerWidth,
34 | },
35 | },
36 | toolbar: {
37 | ...theme.mixins.toolbar,
38 | [theme.breakpoints.down("sm")]: {
39 | display: "none",
40 | },
41 | },
42 | content: {
43 | flexGrow: 1,
44 | padding: theme.spacing(3),
45 | },
46 | /* sidebarList: {
47 | marginTop: theme.spacing(6),
48 | }, */
49 | mobileBackButton: {
50 | marginTop: theme.spacing(0.5),
51 | marginLeft: theme.spacing(3),
52 | [theme.breakpoints.only("sm")]: {
53 | marginTop: theme.spacing(0.625),
54 | },
55 | [theme.breakpoints.up("md")]: {
56 | display: "none",
57 | },
58 | },
59 | }));
60 |
--------------------------------------------------------------------------------
/src/components/UserAvatar/UserAvatar.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useTheme } from "@material-ui/styles";
3 |
4 | // styles
5 | import useStyles from "./styles";
6 |
7 | // components
8 | import { Typography } from "../Wrappers";
9 |
10 | export default function UserAvatar({ color = "primary", ...props }) {
11 | var classes = useStyles();
12 | var theme = useTheme();
13 |
14 | var letters = props.name
15 | .split(" ")
16 | .map(word => word[0])
17 | .join("");
18 |
19 | return (
20 |
24 | {letters}
25 |
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/src/components/UserAvatar/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "UserAvatar",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "UserAvatar.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/UserAvatar/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(() => ({
4 | avatar: {
5 | width: 30,
6 | height: 30,
7 | display: "flex",
8 | alignItems: "center",
9 | justifyContent: "center",
10 | borderRadius: "50%",
11 | },
12 | text: {
13 | color: "white",
14 | },
15 | }));
16 |
--------------------------------------------------------------------------------
/src/components/Widget/Widget.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | Paper,
4 | IconButton,
5 | Menu,
6 | MenuItem,
7 | Typography,
8 | } from "@material-ui/core";
9 | import { MoreVert as MoreIcon } from "@material-ui/icons";
10 | import classnames from "classnames";
11 |
12 | // styles
13 | import useStyles from "./styles";
14 |
15 | export default function Widget({
16 | children,
17 | title,
18 | noBodyPadding,
19 | bodyClass,
20 | disableWidgetMenu,
21 | header,
22 | ...props
23 | }) {
24 | var classes = useStyles();
25 |
26 | // local
27 | var [moreButtonRef, setMoreButtonRef] = useState(null);
28 | var [isMoreMenuOpen, setMoreMenuOpen] = useState(false);
29 |
30 | return (
31 |
32 |
33 |
34 | {header ? (
35 | header
36 | ) : (
37 |
38 |
39 | {title}
40 |
41 | {!disableWidgetMenu && (
42 | setMoreMenuOpen(true)}
48 | buttonRef={setMoreButtonRef}
49 | >
50 |
51 |
52 | )}
53 |
54 | )}
55 |
56 |
62 | {children}
63 |
64 |
65 |
85 |
86 | );
87 | }
88 |
--------------------------------------------------------------------------------
/src/components/Widget/WidgetView.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import classnames from "classnames";
3 | import {
4 | Paper,
5 | IconButton,
6 | Menu,
7 | MenuItem,
8 | withStyles
9 | } from "@material-ui/core";
10 | import { MoreVert as MoreIcon } from "@material-ui/icons";
11 | import Typography from "@material-ui/core/es/Typography/Typography";
12 |
13 | const Widget = ({
14 | classes,
15 | children,
16 | title,
17 | noBodyPadding,
18 | bodyClass,
19 | className,
20 | disableWidgetMenu,
21 | ...props
22 | }) => (
23 |
24 |
25 |
26 | {props.header ? (
27 | props.header
28 | ) : (
29 |
30 |
31 | {title}
32 |
33 | {!disableWidgetMenu && (
34 | props.setMoreMenuOpen(true)}
40 | buttonRef={props.setMoreButtonRef}
41 | >
42 |
43 |
44 | )}
45 |
46 | )}
47 |
48 |
54 | {children}
55 |
56 |
57 |
77 |
78 | );
79 |
80 | const styles = theme => ({
81 | widgetWrapper: {
82 | display: "flex",
83 | minHeight: "100%"
84 | },
85 | widgetHeader: {
86 | padding: theme.spacing.unit * 3,
87 | paddingBottom: theme.spacing.unit,
88 | display: "flex",
89 | justifyContent: "space-between",
90 | alignItems: "center"
91 | },
92 | widgetRoot: {
93 | boxShadow: theme.customShadows.widget
94 | },
95 | widgetBody: {
96 | paddingBottom: theme.spacing.unit * 3,
97 | paddingRight: theme.spacing.unit * 3,
98 | paddingLeft: theme.spacing.unit * 3
99 | },
100 | noPadding: {
101 | padding: 0
102 | },
103 | paper: {
104 | display: "flex",
105 | flexDirection: "column",
106 | flexGrow: 1,
107 | overflow: "hidden"
108 | },
109 | moreButton: {
110 | margin: -theme.spacing.unit,
111 | padding: 0,
112 | width: 40,
113 | height: 40,
114 | color: theme.palette.text.hint,
115 | "&:hover": {
116 | backgroundColor: theme.palette.primary.main,
117 | color: "rgba(255, 255, 255, 0.35)"
118 | }
119 | }
120 | });
121 |
122 | export default withStyles(styles, { withTheme: true })(Widget);
123 |
--------------------------------------------------------------------------------
/src/components/Widget/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Widget",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "Widget.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/Widget/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | widgetWrapper: {
5 | display: "flex",
6 | minHeight: "100%",
7 | },
8 | widgetHeader: {
9 | padding: theme.spacing(3),
10 | paddingBottom: theme.spacing(1),
11 | display: "flex",
12 | justifyContent: "space-between",
13 | alignItems: "center",
14 | },
15 | widgetRoot: {
16 | boxShadow: theme.customShadows.widget,
17 | },
18 | widgetBody: {
19 | paddingBottom: theme.spacing(3),
20 | paddingRight: theme.spacing(3),
21 | paddingLeft: theme.spacing(3),
22 | },
23 | noPadding: {
24 | padding: 0,
25 | },
26 | paper: {
27 | display: "flex",
28 | flexDirection: "column",
29 | flexGrow: 1,
30 | overflow: "hidden",
31 | },
32 | moreButton: {
33 | margin: -theme.spacing(1),
34 | padding: 0,
35 | width: 40,
36 | height: 40,
37 | color: theme.palette.text.hint,
38 | "&:hover": {
39 | backgroundColor: theme.palette.primary.main,
40 | color: "rgba(255, 255, 255, 0.35)",
41 | },
42 | },
43 | }));
44 |
--------------------------------------------------------------------------------
/src/components/Wrappers/Wrappers.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | withStyles,
4 | Badge as BadgeBase,
5 | Typography as TypographyBase,
6 | Button as ButtonBase,
7 | } from "@material-ui/core";
8 | import { useTheme, makeStyles } from "@material-ui/styles";
9 | import classnames from "classnames";
10 |
11 | // styles
12 | var useStyles = makeStyles(theme => ({
13 | badge: {
14 | fontWeight: 600,
15 | height: 16,
16 | minWidth: 16,
17 | },
18 | }));
19 |
20 | function Badge({ children, colorBrightness, color, ...props }) {
21 | var classes = useStyles();
22 | var theme = useTheme();
23 | var Styled = createStyled({
24 | badge: {
25 | backgroundColor: getColor(color, theme, colorBrightness),
26 | },
27 | });
28 |
29 | return (
30 |
31 | {styledProps => (
32 |
38 | {children}
39 |
40 | )}
41 |
42 | );
43 | }
44 |
45 | function Typography({
46 | children,
47 | weight,
48 | size,
49 | colorBrightness,
50 | color,
51 | ...props
52 | }) {
53 | var theme = useTheme();
54 |
55 | return (
56 |
64 | {children}
65 |
66 | );
67 | }
68 |
69 | function Button({ children, color, className, ...props }) {
70 | var theme = useTheme();
71 |
72 | var Styled = createStyled({
73 | root: {
74 | color: getColor(color, theme),
75 | },
76 | contained: {
77 | backgroundColor: getColor(color, theme),
78 | boxShadow: theme.customShadows.widget,
79 | color: `${color ? "white" : theme.palette.text.primary} !important`,
80 | "&:hover": {
81 | backgroundColor: getColor(color, theme, "light"),
82 | boxShadow: theme.customShadows.widgetWide,
83 | },
84 | "&:active": {
85 | boxShadow: theme.customShadows.widgetWide,
86 | },
87 | },
88 | outlined: {
89 | color: getColor(color, theme),
90 | borderColor: getColor(color, theme),
91 | },
92 | select: {
93 | backgroundColor: theme.palette.primary.main,
94 | color: "#fff",
95 | },
96 | });
97 |
98 | return (
99 |
100 | {({ classes }) => (
101 |
115 | {children}
116 |
117 | )}
118 |
119 | );
120 | }
121 |
122 | export { Badge, Typography, Button };
123 |
124 | // ########################################################################
125 |
126 | function getColor(color, theme, brigtness = "main") {
127 | if (color && theme.palette[color] && theme.palette[color][brigtness]) {
128 | return theme.palette[color][brigtness];
129 | }
130 | }
131 |
132 | function getFontWeight(style) {
133 | switch (style) {
134 | case "light":
135 | return 300;
136 | case "medium":
137 | return 500;
138 | case "bold":
139 | return 600;
140 | default:
141 | return 400;
142 | }
143 | }
144 |
145 | function getFontSize(size, variant = "", theme) {
146 | var multiplier;
147 |
148 | switch (size) {
149 | case "sm":
150 | multiplier = 0.8;
151 | break;
152 | case "md":
153 | multiplier = 1.5;
154 | break;
155 | case "xl":
156 | multiplier = 2;
157 | break;
158 | case "xxl":
159 | multiplier = 3;
160 | break;
161 | default:
162 | multiplier = 1;
163 | break;
164 | }
165 |
166 | var defaultSize =
167 | variant && theme.typography[variant]
168 | ? theme.typography[variant].fontSize
169 | : theme.typography.fontSize + "px";
170 |
171 | return `calc(${defaultSize} * ${multiplier})`;
172 | }
173 |
174 | function createStyled(styles, options) {
175 | var Styled = function(props) {
176 | const { children, ...other } = props;
177 | return children(other);
178 | };
179 |
180 | return withStyles(styles, options)(Styled);
181 | }
182 |
--------------------------------------------------------------------------------
/src/components/Wrappers/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Wrappers",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "Wrappers.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/context/LayoutContext.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | var LayoutStateContext = React.createContext();
4 | var LayoutDispatchContext = React.createContext();
5 |
6 | function layoutReducer(state, action) {
7 | switch (action.type) {
8 | case "TOGGLE_SIDEBAR":
9 | return { ...state, isSidebarOpened: !state.isSidebarOpened };
10 | default: {
11 | throw new Error(`Unhandled action type: ${action.type}`);
12 | }
13 | }
14 | }
15 |
16 | function LayoutProvider({ children }) {
17 | var [state, dispatch] = React.useReducer(layoutReducer, {
18 | isSidebarOpened: true,
19 | });
20 | return (
21 |
22 |
23 | {children}
24 |
25 |
26 | );
27 | }
28 |
29 | function useLayoutState() {
30 | var context = React.useContext(LayoutStateContext);
31 | if (context === undefined) {
32 | throw new Error("useLayoutState must be used within a LayoutProvider");
33 | }
34 | return context;
35 | }
36 |
37 | function useLayoutDispatch() {
38 | var context = React.useContext(LayoutDispatchContext);
39 | if (context === undefined) {
40 | throw new Error("useLayoutDispatch must be used within a LayoutProvider");
41 | }
42 | return context;
43 | }
44 |
45 | export { LayoutProvider, useLayoutState, useLayoutDispatch, toggleSidebar };
46 |
47 | // ###########################################################
48 | function toggleSidebar(dispatch) {
49 | dispatch({
50 | type: "TOGGLE_SIDEBAR",
51 | });
52 | }
53 |
--------------------------------------------------------------------------------
/src/context/UserContext.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | var UserStateContext = React.createContext();
4 | var UserDispatchContext = React.createContext();
5 |
6 | function userReducer(state, action) {
7 | switch (action.type) {
8 | case "LOGIN_SUCCESS":
9 | return { ...state, isAuthenticated: true };
10 | case "SIGN_OUT_SUCCESS":
11 | return { ...state, isAuthenticated: false };
12 | default: {
13 | throw new Error(`Unhandled action type: ${action.type}`);
14 | }
15 | }
16 | }
17 |
18 | function UserProvider({ children }) {
19 | var [state, dispatch] = React.useReducer(userReducer, {
20 | isAuthenticated: !!localStorage.getItem("id_token"),
21 | });
22 |
23 | return (
24 |
25 |
26 | {children}
27 |
28 |
29 | );
30 | }
31 |
32 | function useUserState() {
33 | var context = React.useContext(UserStateContext);
34 | if (context === undefined) {
35 | throw new Error("useUserState must be used within a UserProvider");
36 | }
37 | return context;
38 | }
39 |
40 | function useUserDispatch() {
41 | var context = React.useContext(UserDispatchContext);
42 | if (context === undefined) {
43 | throw new Error("useUserDispatch must be used within a UserProvider");
44 | }
45 | return context;
46 | }
47 |
48 | export { UserProvider, useUserState, useUserDispatch, loginUser, signOut };
49 |
50 | // ###########################################################
51 |
52 | function loginUser(dispatch, login, password, history, setIsLoading, setError) {
53 | setError(false);
54 | setIsLoading(true);
55 |
56 | if (!!login && !!password) {
57 | setTimeout(() => {
58 | localStorage.setItem('id_token', 1)
59 | setError(null)
60 | setIsLoading(false)
61 | dispatch({ type: 'LOGIN_SUCCESS' })
62 |
63 | history.push('/app/dashboard')
64 | }, 2000);
65 | } else {
66 | dispatch({ type: "LOGIN_FAILURE" });
67 | setError(true);
68 | setIsLoading(false);
69 | }
70 | }
71 |
72 | function signOut(dispatch, history) {
73 | localStorage.removeItem("id_token");
74 | dispatch({ type: "SIGN_OUT_SUCCESS" });
75 | history.push("/login");
76 | }
77 |
--------------------------------------------------------------------------------
/src/images/google.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
48 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import { ThemeProvider } from "@material-ui/styles";
4 | import { CssBaseline } from "@material-ui/core";
5 |
6 | import Themes from "./themes";
7 | import App from "./components/App";
8 | import * as serviceWorker from "./serviceWorker";
9 | import { LayoutProvider } from "./context/LayoutContext";
10 | import { UserProvider } from "./context/UserContext";
11 |
12 | ReactDOM.render(
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | ,
21 | document.getElementById("root"),
22 | );
23 |
24 | // If you want your app to work offline and load faster, you can change
25 | // unregister() to register() below. Note this comes with some pitfalls.
26 | // Learn more about service workers: http://bit.ly/CRA-PWA
27 | serviceWorker.unregister();
28 |
--------------------------------------------------------------------------------
/src/pages/charts/Charts.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { Grid } from "@material-ui/core";
3 | import { useTheme } from "@material-ui/styles";
4 | import {
5 | CartesianGrid,
6 | Legend,
7 | Line,
8 | LineChart,
9 | Pie,
10 | PieChart,
11 | ResponsiveContainer,
12 | Sector,
13 | Tooltip,
14 | XAxis,
15 | YAxis,
16 | } from "recharts";
17 |
18 | // components
19 | import Widget from "../../components/Widget/Widget";
20 | import ApexLineChart from "./components/ApexLineChart";
21 | import ApexHeatmap from "./components/ApexHeatmap";
22 | import PageTitle from "../../components/PageTitle/PageTitle";
23 |
24 | const lineChartData = [
25 | {
26 | name: "Page A",
27 | uv: 4000,
28 | pv: 2400,
29 | amt: 2400,
30 | },
31 | {
32 | name: "Page B",
33 | uv: 3000,
34 | pv: 1398,
35 | amt: 2210,
36 | },
37 | {
38 | name: "Page C",
39 | uv: 2000,
40 | pv: 9800,
41 | amt: 2290,
42 | },
43 | {
44 | name: "Page D",
45 | uv: 2780,
46 | pv: 3908,
47 | amt: 2000,
48 | },
49 | {
50 | name: "Page E",
51 | uv: 1890,
52 | pv: 4800,
53 | amt: 2181,
54 | },
55 | {
56 | name: "Page F",
57 | uv: 2390,
58 | pv: 3800,
59 | amt: 2500,
60 | },
61 | {
62 | name: "Page G",
63 | uv: 3490,
64 | pv: 4300,
65 | amt: 2100,
66 | },
67 | ];
68 |
69 | const pieChartData = [
70 | { name: "Group A", value: 400 },
71 | { name: "Group B", value: 300 },
72 | { name: "Group C", value: 300 },
73 | { name: "Group D", value: 200 },
74 | ];
75 |
76 | export default function Charts(props) {
77 | var theme = useTheme();
78 |
79 | // local
80 | var [activeIndex, setActiveIndexId] = useState(0);
81 |
82 | return (
83 | <>
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
110 |
111 |
112 |
113 |
114 |
115 |
121 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | setActiveIndexId(id)}
145 | />
146 |
147 |
148 |
149 |
150 |
151 | >
152 | );
153 | }
154 |
155 | // ################################################################
156 |
157 | function renderActiveShape(props) {
158 | var RADIAN = Math.PI / 180;
159 | var {
160 | cx,
161 | cy,
162 | midAngle,
163 | innerRadius,
164 | outerRadius,
165 | startAngle,
166 | endAngle,
167 | fill,
168 | payload,
169 | percent,
170 | value,
171 | } = props;
172 | var sin = Math.sin(-RADIAN * midAngle);
173 | var cos = Math.cos(-RADIAN * midAngle);
174 | var sx = cx + (outerRadius + 10) * cos;
175 | var sy = cy + (outerRadius + 10) * sin;
176 | var mx = cx + (outerRadius + 30) * cos;
177 | var my = cy + (outerRadius + 30) * sin;
178 | var ex = mx + (cos >= 0 ? 1 : -1) * 22;
179 | var ey = my;
180 | var textAnchor = cos >= 0 ? "start" : "end";
181 |
182 | return (
183 |
184 |
185 | {payload.name}
186 |
187 |
196 |
205 |
210 |
211 | = 0 ? 1 : -1) * 12}
213 | y={ey}
214 | textAnchor={textAnchor}
215 | fill="#333"
216 | >{`PV ${value}`}
217 | = 0 ? 1 : -1) * 12}
219 | y={ey}
220 | dy={18}
221 | textAnchor={textAnchor}
222 | fill="#999"
223 | >
224 | {`(Rate ${(percent * 100).toFixed(2)}%)`}
225 |
226 |
227 | );
228 | }
229 |
--------------------------------------------------------------------------------
/src/pages/charts/components/ApexHeatmap.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useTheme } from "@material-ui/styles";
3 | import ApexCharts from "react-apexcharts";
4 |
5 | const series = [
6 | {
7 | name: "Metric1",
8 | data: generateData(18, {
9 | min: 0,
10 | max: 90,
11 | }),
12 | },
13 | {
14 | name: "Metric2",
15 | data: generateData(18, {
16 | min: 0,
17 | max: 90,
18 | }),
19 | },
20 | {
21 | name: "Metric3",
22 | data: generateData(18, {
23 | min: 0,
24 | max: 90,
25 | }),
26 | },
27 | {
28 | name: "Metric4",
29 | data: generateData(18, {
30 | min: 0,
31 | max: 90,
32 | }),
33 | },
34 | {
35 | name: "Metric5",
36 | data: generateData(18, {
37 | min: 0,
38 | max: 90,
39 | }),
40 | },
41 | {
42 | name: "Metric6",
43 | data: generateData(18, {
44 | min: 0,
45 | max: 90,
46 | }),
47 | },
48 | {
49 | name: "Metric7",
50 | data: generateData(18, {
51 | min: 0,
52 | max: 90,
53 | }),
54 | },
55 | {
56 | name: "Metric8",
57 | data: generateData(18, {
58 | min: 0,
59 | max: 90,
60 | }),
61 | },
62 | {
63 | name: "Metric9",
64 | data: generateData(18, {
65 | min: 0,
66 | max: 90,
67 | }),
68 | },
69 | ];
70 |
71 | export default function ApexLineChart() {
72 | var theme = useTheme();
73 |
74 | return (
75 |
81 | );
82 | }
83 |
84 | // ##################################################################
85 | function generateData(count, yrange) {
86 | var i = 0;
87 | var series = [];
88 | while (i < count) {
89 | var x = "w" + (i + 1).toString();
90 | var y =
91 | Math.floor(Math.random() * (yrange.max - yrange.min + 1)) + yrange.min;
92 |
93 | series.push({
94 | x: x,
95 | y: y,
96 | });
97 | i++;
98 | }
99 |
100 | return series;
101 | }
102 |
103 | function themeOptions(theme) {
104 | return {
105 | chart: {
106 | toolbar: {
107 | show: false,
108 | },
109 | },
110 | dataLabels: {
111 | enabled: false,
112 | },
113 | colors: [theme.palette.primary.main],
114 | };
115 | }
116 |
--------------------------------------------------------------------------------
/src/pages/charts/components/ApexLineChart.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ApexCharts from "react-apexcharts";
3 | import { useTheme } from "@material-ui/styles";
4 |
5 | const series = [
6 | {
7 | name: "series1",
8 | data: [31, 40, 28, 51, 42, 109, 100],
9 | },
10 | {
11 | name: "series2",
12 | data: [11, 32, 45, 32, 34, 52, 41],
13 | },
14 | ];
15 |
16 | export default function ApexLineChart() {
17 | var theme = useTheme();
18 |
19 | return (
20 |
26 | );
27 | }
28 |
29 | // ############################################################
30 | function themeOptions(theme) {
31 | return {
32 | dataLabels: {
33 | enabled: false,
34 | },
35 | stroke: {
36 | curve: "smooth",
37 | },
38 | xaxis: {
39 | type: "datetime",
40 | categories: [
41 | "2018-09-19T00:00:00",
42 | "2018-09-19T01:30:00",
43 | "2018-09-19T02:30:00",
44 | "2018-09-19T03:30:00",
45 | "2018-09-19T04:30:00",
46 | "2018-09-19T05:30:00",
47 | "2018-09-19T06:30:00",
48 | ],
49 | },
50 | tooltip: {
51 | x: {
52 | format: "dd/MM/yy HH:mm",
53 | },
54 | },
55 | fill: {
56 | colors: [theme.palette.primary.light, theme.palette.success.light],
57 | },
58 | colors: [theme.palette.primary.main, theme.palette.success.main],
59 | chart: {
60 | toolbar: {
61 | show: false,
62 | },
63 | },
64 | legend: {
65 | show: false,
66 | },
67 | };
68 | }
69 |
--------------------------------------------------------------------------------
/src/pages/charts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Charts",
3 | "version": "1.0.0",
4 | "private": true,
5 | "main": "Charts.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/dashboard/Dashboard.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | Grid,
4 | LinearProgress,
5 | Select,
6 | OutlinedInput,
7 | MenuItem,
8 | } from "@material-ui/core";
9 | import { useTheme } from "@material-ui/styles";
10 | import {
11 | ResponsiveContainer,
12 | ComposedChart,
13 | AreaChart,
14 | LineChart,
15 | Line,
16 | Area,
17 | PieChart,
18 | Pie,
19 | Cell,
20 | YAxis,
21 | XAxis,
22 | } from "recharts";
23 |
24 | // styles
25 | import useStyles from "./styles";
26 |
27 | // components
28 | import mock from "./mock";
29 | import Widget from "../../components/Widget";
30 | import PageTitle from "../../components/PageTitle";
31 | import { Typography } from "../../components/Wrappers";
32 | import Dot from "../../components/Sidebar/components/Dot";
33 | import Table from "./components/Table/Table";
34 | import BigStat from "./components/BigStat/BigStat";
35 |
36 | const mainChartData = getMainChartData();
37 | const PieChartData = [
38 | { name: "Group A", value: 400, color: "primary" },
39 | { name: "Group B", value: 300, color: "secondary" },
40 | { name: "Group C", value: 300, color: "warning" },
41 | { name: "Group D", value: 200, color: "success" },
42 | ];
43 |
44 | export default function Dashboard(props) {
45 | var classes = useStyles();
46 | var theme = useTheme();
47 |
48 | // local
49 | var [mainChartState, setMainChartState] = useState("monthly");
50 |
51 | return (
52 | <>
53 |
54 |
55 |
56 |
62 |
63 |
64 | 12, 678
65 |
66 |
78 |
85 |
86 |
87 |
93 |
94 |
95 | Registrations
96 |
97 | 860
98 |
99 |
100 |
101 | Sign Out
102 |
103 | 32
104 |
105 |
106 |
107 | Rate
108 |
109 | 3.25%
110 |
111 |
112 |
113 |
114 |
115 |
121 |
122 |
123 |
124 |
129 | Integration
130 |
131 |
132 |
133 |
134 |
139 | SDK
140 |
141 |
142 |
143 |
144 |
150 | Integration
151 |
152 |
158 |
159 |
160 |
166 | SDK
167 |
168 |
174 |
175 |
176 |
177 |
178 |
184 |
185 |
190 | 60% / 37°С / 3.3 Ghz
191 |
192 |
193 |
194 |
195 |
203 |
204 |
205 |
206 |
207 |
208 |
213 | 54% / 31°С / 3.3 Ghz
214 |
215 |
216 |
217 |
218 |
226 |
227 |
228 |
229 |
230 |
231 |
236 | 57% / 21°С / 3.3 Ghz
237 |
238 |
239 |
240 |
241 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
267 | {PieChartData.map((entry, index) => (
268 | |
272 | ))}
273 |
274 |
275 |
276 |
277 |
278 |
279 | {PieChartData.map(({ name, value, color }, index) => (
280 |
281 |
282 |
283 | {name}
284 |
285 |
286 | {value}
287 |
288 |
289 | ))}
290 |
291 |
292 |
293 |
294 |
295 |
296 |
300 |
305 | Daily Line Chart
306 |
307 |
308 |
309 |
310 |
311 | Tablet
312 |
313 |
314 |
315 |
316 |
317 | Mobile
318 |
319 |
320 |
321 |
322 |
323 | Desktop
324 |
325 |
326 |
327 |
345 |
346 | }
347 | >
348 |
349 |
353 |
359 | i + 1}
361 | tick={{ fill: theme.palette.text.hint + "80", fontSize: 14 }}
362 | stroke={theme.palette.text.hint + "80"}
363 | tickLine={false}
364 | />
365 |
372 |
380 |
391 |
392 |
393 |
394 |
395 | {mock.bigStat.map(stat => (
396 |
397 |
398 |
399 | ))}
400 |
401 |
407 |
408 |
409 |
410 |
411 | >
412 | );
413 | }
414 |
415 | // #######################################################################
416 | function getRandomData(length, min, max, multiplier = 10, maxDiff = 10) {
417 | var array = new Array(length).fill();
418 | let lastValue;
419 |
420 | return array.map((item, index) => {
421 | let randomValue = Math.floor(Math.random() * multiplier + 1);
422 |
423 | while (
424 | randomValue <= min ||
425 | randomValue >= max ||
426 | (lastValue && randomValue - lastValue > maxDiff)
427 | ) {
428 | randomValue = Math.floor(Math.random() * multiplier + 1);
429 | }
430 |
431 | lastValue = randomValue;
432 |
433 | return { value: randomValue };
434 | });
435 | }
436 |
437 | function getMainChartData() {
438 | var resultArray = [];
439 | var tablet = getRandomData(31, 3500, 6500, 7500, 1000);
440 | var desktop = getRandomData(31, 1500, 7500, 7500, 1500);
441 | var mobile = getRandomData(31, 1500, 7500, 7500, 1500);
442 |
443 | for (let i = 0; i < tablet.length; i++) {
444 | resultArray.push({
445 | tablet: tablet[i].value,
446 | desktop: desktop[i].value,
447 | mobile: mobile[i].value,
448 | });
449 | }
450 |
451 | return resultArray;
452 | }
453 |
--------------------------------------------------------------------------------
/src/pages/dashboard/components/BigStat/BigStat.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { Grid, Select, MenuItem, Input } from "@material-ui/core";
3 | import { ArrowForward as ArrowForwardIcon } from "@material-ui/icons";
4 | import { useTheme } from "@material-ui/styles";
5 | import { BarChart, Bar } from "recharts";
6 | import classnames from "classnames";
7 |
8 | // styles
9 | import useStyles from "./styles";
10 |
11 | // components
12 | import Widget from "../../../../components/Widget";
13 | import { Typography } from "../../../../components/Wrappers";
14 |
15 | export default function BigStat(props) {
16 | var { product, total, color, registrations, bounce } = props;
17 | var classes = useStyles();
18 | var theme = useTheme();
19 |
20 | // local
21 | var [value, setValue] = useState("daily");
22 |
23 | return (
24 |
27 | {product}
28 |
29 |
44 |
45 | }
46 | upperTitle
47 | >
48 |
49 |
50 |
51 | {total[value]}
52 |
53 |
54 | {total.percent.profit ? "+" : "-"}
55 | {total.percent.value}%
56 |
57 |
58 |
59 |
65 |
66 |
67 |
68 |
69 |
70 | {registrations[value].value}
71 |
76 |
77 |
78 | Registrations
79 |
80 |
81 |
82 |
83 | {bounce[value].value}%
84 |
89 |
90 |
91 | Bounce Rate
92 |
93 |
94 |
95 |
96 |
97 | {registrations[value].value * 10}
98 |
99 |
104 |
105 |
106 | Views
107 |
108 |
109 |
110 |
111 | );
112 | }
113 |
114 | // #######################################################################
115 |
116 | function getRandomData() {
117 | return Array(7)
118 | .fill()
119 | .map(() => ({ value: Math.floor(Math.random() * 10) + 1 }));
120 | }
121 |
--------------------------------------------------------------------------------
/src/pages/dashboard/components/BigStat/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | title: {
5 | display: "flex",
6 | flexDirection: "row",
7 | justifyContent: "space-between",
8 | alignItems: "center",
9 | width: "100%",
10 | marginBottom: theme.spacing(1),
11 | },
12 | bottomStatsContainer: {
13 | display: "flex",
14 | justifyContent: "space-between",
15 | margin: theme.spacing(1) * -2,
16 | marginTop: theme.spacing(1),
17 | },
18 | statCell: {
19 | padding: theme.spacing(2),
20 | },
21 | totalValueContainer: {
22 | display: "flex",
23 | alignItems: "flex-end",
24 | justifyContent: "space-between",
25 | },
26 | totalValue: {
27 | display: "flex",
28 | alignItems: "baseline",
29 | },
30 | profitArrow: {
31 | transform: "rotate(-45deg)",
32 | fill: theme.palette.success.main,
33 | },
34 | profitArrowDanger: {
35 | transform: "rotate(45deg)",
36 | fill: theme.palette.secondary.main,
37 | },
38 | selectInput: {
39 | padding: 10,
40 | paddingRight: 25,
41 | "&:focus": {
42 | backgroundColor: "white",
43 | },
44 | },
45 | }));
--------------------------------------------------------------------------------
/src/pages/dashboard/components/Table/Table.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | Table,
4 | TableRow,
5 | TableHead,
6 | TableBody,
7 | TableCell,
8 | } from "@material-ui/core";
9 |
10 | // components
11 | import { Button } from "../../../../components/Wrappers";
12 |
13 | const states = {
14 | sent: "success",
15 | pending: "warning",
16 | declined: "secondary",
17 | };
18 |
19 | export default function TableComponent({ data }) {
20 | var keys = Object.keys(data[0]).map(i => i.toUpperCase());
21 | keys.shift(); // delete "id" key
22 |
23 | return (
24 |
25 |
26 |
27 | {keys.map(key => (
28 | {key}
29 | ))}
30 |
31 |
32 |
33 | {data.map(({ id, name, email, product, price, date, city, status }) => (
34 |
35 | {name}
36 | {email}
37 | {product}
38 | {price}
39 | {date}
40 | {city}
41 |
42 |
50 |
51 |
52 | ))}
53 |
54 |
55 | );
56 | }
57 |
--------------------------------------------------------------------------------
/src/pages/dashboard/mock.js:
--------------------------------------------------------------------------------
1 | export default {
2 | tasks: [
3 | {
4 | id: 0,
5 | type: "Meeting",
6 | title: "Meeting with Andrew Piker",
7 | time: "9:00"
8 | },
9 | {
10 | id: 1,
11 | type: "Call",
12 | title: "Call with HT Company",
13 | time: "12:00"
14 | },
15 | {
16 | id: 2,
17 | type: "Meeting",
18 | title: "Meeting with Zoe Alison",
19 | time: "14:00"
20 | },
21 | {
22 | id: 3,
23 | type: "Interview",
24 | title: "Interview with HR",
25 | time: "15:00"
26 | }
27 | ],
28 | bigStat: [
29 | {
30 | product: "Light Blue",
31 | total: {
32 | monthly: 4232,
33 | weekly: 1465,
34 | daily: 199,
35 | percent: { value: 3.7, profit: false }
36 | },
37 | color: "primary",
38 | registrations: {
39 | monthly: { value: 830, profit: false },
40 | weekly: { value: 215, profit: true },
41 | daily: { value: 33, profit: true }
42 | },
43 | bounce: {
44 | monthly: { value: 4.5, profit: false },
45 | weekly: { value: 3, profit: true },
46 | daily: { value: 3.25, profit: true }
47 | }
48 | },
49 | {
50 | product: "Sing App",
51 | total: {
52 | monthly: 754,
53 | weekly: 180,
54 | daily: 27,
55 | percent: { value: 2.5, profit: true }
56 | },
57 | color: "warning",
58 | registrations: {
59 | monthly: { value: 32, profit: true },
60 | weekly: { value: 8, profit: true },
61 | daily: { value: 2, profit: false }
62 | },
63 | bounce: {
64 | monthly: { value: 2.5, profit: true },
65 | weekly: { value: 4, profit: false },
66 | daily: { value: 4.5, profit: false }
67 | }
68 | },
69 | {
70 | product: "RNS",
71 | total: {
72 | monthly: 1025,
73 | weekly: 301,
74 | daily: 44,
75 | percent: { value: 3.1, profit: true }
76 | },
77 | color: "secondary",
78 | registrations: {
79 | monthly: { value: 230, profit: true },
80 | weekly: { value: 58, profit: false },
81 | daily: { value: 15, profit: false }
82 | },
83 | bounce: {
84 | monthly: { value: 21.5, profit: false },
85 | weekly: { value: 19.35, profit: false },
86 | daily: { value: 10.1, profit: true }
87 | }
88 | }
89 | ],
90 | notifications: [
91 | {
92 | id: 0,
93 | icon: "thumbs-up",
94 | color: "primary",
95 | content:
96 | 'Ken accepts your invitation'
97 | },
98 | {
99 | id: 1,
100 | icon: "file",
101 | color: "success",
102 | content: "Report from LT Company"
103 | },
104 | {
105 | id: 2,
106 | icon: "envelope",
107 | color: "danger",
108 | content: '4 Private Mails'
109 | },
110 | {
111 | id: 3,
112 | icon: "comment",
113 | color: "success",
114 | content: '3 Comments to your Post'
115 | },
116 | {
117 | id: 4,
118 | icon: "cog",
119 | color: "light",
120 | content: 'New Version of RNS app'
121 | },
122 | {
123 | id: 5,
124 | icon: "bell",
125 | color: "info",
126 | content:
127 | '15 Notifications from Social Apps'
128 | }
129 | ],
130 | table: [
131 | {
132 | id: 0,
133 | name: "Mark Otto",
134 | email: "ottoto@wxample.com",
135 | product: "ON the Road",
136 | price: "$25 224.2",
137 | date: "11 May 2017",
138 | city: "Otsego",
139 | status: "Sent"
140 | },
141 | {
142 | id: 1,
143 | name: "Jacob Thornton",
144 | email: "thornton@wxample.com",
145 | product: "HP Core i7",
146 | price: "$1 254.2",
147 | date: "4 Jun 2017",
148 | city: "Fivepointville",
149 | status: "Sent"
150 | },
151 | {
152 | id: 2,
153 | name: "Larry the Bird",
154 | email: "bird@wxample.com",
155 | product: "Air Pro",
156 | price: "$1 570.0",
157 | date: "27 Aug 2017",
158 | city: "Leadville North",
159 | status: "Pending"
160 | },
161 | {
162 | id: 3,
163 | name: "Joseph May",
164 | email: "josephmay@wxample.com",
165 | product: "Version Control",
166 | price: "$5 224.5",
167 | date: "19 Feb 2018",
168 | city: "Seaforth",
169 | status: "Declined"
170 | },
171 | {
172 | id: 4,
173 | name: "Peter Horadnia",
174 | email: "horadnia@wxample.com",
175 | product: "Let's Dance",
176 | price: "$43 594.7",
177 | date: "1 Mar 2018",
178 | city: "Hanoverton",
179 | status: "Sent"
180 | }
181 | ]
182 | };
183 |
--------------------------------------------------------------------------------
/src/pages/dashboard/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Dashboard",
3 | "version": "1.0.0",
4 | "private": true,
5 | "main": "Dashboard.js"
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/dashboard/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | card: {
5 | minHeight: "100%",
6 | display: "flex",
7 | flexDirection: "column",
8 | },
9 | visitsNumberContainer: {
10 | display: "flex",
11 | alignItems: "center",
12 | flexGrow: 1,
13 | paddingBottom: theme.spacing(1),
14 | },
15 | progressSection: {
16 | marginBottom: theme.spacing(1),
17 | },
18 | progressTitle: {
19 | marginBottom: theme.spacing(2),
20 | },
21 | progress: {
22 | marginBottom: theme.spacing(1),
23 | backgroundColor: theme.palette.primary.main,
24 | },
25 | pieChartLegendWrapper: {
26 | height: "100%",
27 | display: "flex",
28 | flexDirection: "column",
29 | justifyContent: "center",
30 | alignItems: "flex-end",
31 | marginRight: theme.spacing(1),
32 | },
33 | legendItemContainer: {
34 | display: "flex",
35 | alignItems: "center",
36 | marginBottom: theme.spacing(1),
37 | },
38 | fullHeightBody: {
39 | display: "flex",
40 | flexGrow: 1,
41 | flexDirection: "column",
42 | justifyContent: "space-between",
43 | },
44 | tableWidget: {
45 | overflowX: "auto",
46 | },
47 | progressBar: {
48 | backgroundColor: theme.palette.warning.main,
49 | },
50 | performanceLegendWrapper: {
51 | display: "flex",
52 | flexGrow: 1,
53 | alignItems: "center",
54 | marginBottom: theme.spacing(1),
55 | },
56 | legendElement: {
57 | display: "flex",
58 | alignItems: "center",
59 | marginRight: theme.spacing(2),
60 | },
61 | legendElementText: {
62 | marginLeft: theme.spacing(1),
63 | },
64 | serverOverviewElement: {
65 | display: "flex",
66 | alignItems: "center",
67 | maxWidth: "100%",
68 | },
69 | serverOverviewElementText: {
70 | minWidth: 145,
71 | paddingRight: theme.spacing(2),
72 | },
73 | serverOverviewElementChartWrapper: {
74 | width: "100%",
75 | },
76 | mainChartBody: {
77 | overflowX: "auto",
78 | },
79 | mainChartHeader: {
80 | width: "100%",
81 | display: "flex",
82 | alignItems: "center",
83 | justifyContent: "space-between",
84 | [theme.breakpoints.only("xs")]: {
85 | flexWrap: "wrap",
86 | },
87 | },
88 | mainChartHeaderLabels: {
89 | display: "flex",
90 | alignItems: "center",
91 | [theme.breakpoints.only("xs")]: {
92 | order: 3,
93 | width: "100%",
94 | justifyContent: "center",
95 | marginTop: theme.spacing(3),
96 | marginBottom: theme.spacing(2),
97 | },
98 | },
99 | mainChartHeaderLabel: {
100 | display: "flex",
101 | alignItems: "center",
102 | marginLeft: theme.spacing(3),
103 | },
104 | mainChartSelectRoot: {
105 | borderColor: theme.palette.text.hint + "80 !important",
106 | },
107 | mainChartSelect: {
108 | padding: 10,
109 | paddingRight: 25,
110 | },
111 | mainChartLegentElement: {
112 | fontSize: "18px !important",
113 | marginLeft: theme.spacing(1),
114 | },
115 | }));
116 |
--------------------------------------------------------------------------------
/src/pages/error/Error.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Grid, Paper, Typography, Button } from "@material-ui/core";
3 | import { Link } from "react-router-dom";
4 | import classnames from "classnames";
5 |
6 | // styles
7 | import useStyles from "./styles";
8 |
9 | // logo
10 | import logo from "./logo.svg";
11 |
12 | export default function Error() {
13 | var classes = useStyles();
14 |
15 | return (
16 |
17 |
18 |

19 |
20 | Material Admin
21 |
22 |
23 |
24 |
29 | 404
30 |
31 |
32 | Oops. Looks like the page you're looking for no longer exists
33 |
34 |
40 | But we're here to bring you back to safety
41 |
42 |
52 |
53 |
54 | );
55 | }
56 |
--------------------------------------------------------------------------------
/src/pages/error/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/pages/error/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Error",
3 | "version": "0.0.0",
4 | "main": "Error.js",
5 | "private": true
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/error/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | container: {
5 | height: "100vh",
6 | width: "100vw",
7 | display: "flex",
8 | flexDirection: "column",
9 | justifyContent: "center",
10 | alignItems: "center",
11 | backgroundColor: theme.palette.primary.main,
12 | position: "absolute",
13 | top: 0,
14 | left: 0,
15 | },
16 | logotype: {
17 | display: "flex",
18 | alignItems: "center",
19 | marginBottom: theme.spacing(12),
20 | [theme.breakpoints.down("sm")]: {
21 | display: "none",
22 | },
23 | },
24 | logotypeText: {
25 | fontWeight: 500,
26 | color: "white",
27 | marginLeft: theme.spacing(2),
28 | },
29 | logotypeIcon: {
30 | width: 70,
31 | marginRight: theme.spacing(2),
32 | },
33 | paperRoot: {
34 | boxShadow: theme.customShadows.widgetDark,
35 | display: "flex",
36 | flexDirection: "column",
37 | alignItems: "center",
38 | paddingTop: theme.spacing(8),
39 | paddingBottom: theme.spacing(8),
40 | paddingLeft: theme.spacing(6),
41 | paddingRight: theme.spacing(6),
42 | maxWidth: 404,
43 | },
44 | textRow: {
45 | marginBottom: theme.spacing(10),
46 | textAlign: "center",
47 | },
48 | errorCode: {
49 | fontSize: 148,
50 | fontWeight: 600,
51 | },
52 | safetyText: {
53 | fontWeight: 300,
54 | color: theme.palette.text.hint,
55 | },
56 | backButton: {
57 | boxShadow: theme.customShadows.widget,
58 | textTransform: "none",
59 | fontSize: 22,
60 | },
61 | }));
62 |
--------------------------------------------------------------------------------
/src/pages/icons/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Icons",
3 | "version": "0.0.0",
4 | "main": "Icons.js",
5 | "private": true
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/icons/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | titleBold: {
5 | fontWeight: 600,
6 | },
7 | iconsBar: {
8 | marginBottom: theme.spacing(4),
9 | borderBottom: "1px solid",
10 | borderBottomColor: theme.palette.text.hint + "80",
11 | },
12 | tab: {
13 | color: theme.palette.primary.light + "CC",
14 | },
15 | materailIcon: {
16 | display: "flex",
17 | paddingLeft: `${theme.spacing(4)}px !important`,
18 | paddingRight: `${theme.spacing(4)}px !important`,
19 | color: theme.palette.text.secondary,
20 | fontSize: 24,
21 | overflowX: "hidden",
22 | },
23 | materialIconText: {
24 | marginLeft: theme.spacing(2),
25 | fontSize: 14,
26 | },
27 | iconsContainer: {
28 | boxShadow: theme.customShadows.widget,
29 | overflow: "hidden",
30 | paddingBottom: theme.spacing(2),
31 | },
32 | }));
33 |
--------------------------------------------------------------------------------
/src/pages/login/Login.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | Grid,
4 | CircularProgress,
5 | Typography,
6 | Button,
7 | Tabs,
8 | Tab,
9 | TextField,
10 | Fade,
11 | } from "@material-ui/core";
12 | import { withRouter } from "react-router-dom";
13 | import classnames from "classnames";
14 |
15 | // styles
16 | import useStyles from "./styles";
17 |
18 | // logo
19 | import logo from "./logo.svg";
20 | import google from "../../images/google.svg";
21 |
22 | // context
23 | import { useUserDispatch, loginUser } from "../../context/UserContext";
24 |
25 | function Login(props) {
26 | var classes = useStyles();
27 |
28 | // global
29 | var userDispatch = useUserDispatch();
30 |
31 | // local
32 | var [isLoading, setIsLoading] = useState(false);
33 | var [error, setError] = useState(null);
34 | var [activeTabId, setActiveTabId] = useState(0);
35 | var [nameValue, setNameValue] = useState("");
36 | var [loginValue, setLoginValue] = useState("");
37 | var [passwordValue, setPasswordValue] = useState("");
38 |
39 | return (
40 |
41 |
42 |

43 |
Material Admin
44 |
45 |
46 |
47 |
setActiveTabId(id)}
50 | indicatorColor="primary"
51 | textColor="primary"
52 | centered
53 | >
54 |
55 |
56 |
57 | {activeTabId === 0 && (
58 |
59 |
60 | Good Morning, User
61 |
62 |
66 |
71 |
72 |
73 | Something is wrong with your login or password :(
74 |
75 |
76 | setLoginValue(e.target.value)}
86 | margin="normal"
87 | placeholder="Email Adress"
88 | type="email"
89 | fullWidth
90 | />
91 | setPasswordValue(e.target.value)}
101 | margin="normal"
102 | placeholder="Password"
103 | type="password"
104 | fullWidth
105 | />
106 |
107 | {isLoading ? (
108 |
109 | ) : (
110 |
130 | )}
131 |
138 |
139 |
140 | )}
141 | {activeTabId === 1 && (
142 |
143 |
144 | Welcome!
145 |
146 |
147 | Create your account
148 |
149 |
150 |
151 | Something is wrong with your login or password :(
152 |
153 |
154 | setNameValue(e.target.value)}
164 | margin="normal"
165 | placeholder="Full Name"
166 | type="text"
167 | fullWidth
168 | />
169 | setLoginValue(e.target.value)}
179 | margin="normal"
180 | placeholder="Email Adress"
181 | type="email"
182 | fullWidth
183 | />
184 | setPasswordValue(e.target.value)}
194 | margin="normal"
195 | placeholder="Password"
196 | type="password"
197 | fullWidth
198 | />
199 |
200 | {isLoading ? (
201 |
202 | ) : (
203 |
227 | )}
228 |
229 |
230 |
231 |
or
232 |
233 |
234 |
244 |
245 | )}
246 |
247 |
248 | © 2014-2019 Flatlogic, LLC. All rights reserved.
249 |
250 |
251 |
252 | );
253 | }
254 |
255 | export default withRouter(Login);
256 |
--------------------------------------------------------------------------------
/src/pages/login/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/pages/login/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Login",
3 | "version": "0.0.0",
4 | "main": "Login.js",
5 | "private": true
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/login/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | container: {
5 | height: "100vh",
6 | width: "100vw",
7 | display: "flex",
8 | justifyContent: "center",
9 | alignItems: "center",
10 | position: "absolute",
11 | top: 0,
12 | left: 0,
13 | },
14 | logotypeContainer: {
15 | backgroundColor: theme.palette.primary.main,
16 | width: "60%",
17 | height: "100%",
18 | display: "flex",
19 | flexDirection: "column",
20 | justifyContent: "center",
21 | alignItems: "center",
22 | [theme.breakpoints.down("md")]: {
23 | width: "50%",
24 | },
25 | [theme.breakpoints.down("md")]: {
26 | display: "none",
27 | },
28 | },
29 | logotypeImage: {
30 | width: 165,
31 | marginBottom: theme.spacing(4),
32 | },
33 | logotypeText: {
34 | color: "white",
35 | fontWeight: 500,
36 | fontSize: 84,
37 | [theme.breakpoints.down("md")]: {
38 | fontSize: 48,
39 | },
40 | },
41 | formContainer: {
42 | width: "40%",
43 | height: "100%",
44 | display: "flex",
45 | flexDirection: "column",
46 | justifyContent: "center",
47 | alignItems: "center",
48 | [theme.breakpoints.down("md")]: {
49 | width: "50%",
50 | },
51 | },
52 | form: {
53 | width: 320,
54 | },
55 | tab: {
56 | fontWeight: 400,
57 | fontSize: 18,
58 | },
59 | greeting: {
60 | fontWeight: 500,
61 | textAlign: "center",
62 | marginTop: theme.spacing(4),
63 | },
64 | subGreeting: {
65 | fontWeight: 500,
66 | textAlign: "center",
67 | marginTop: theme.spacing(2),
68 | },
69 | googleButton: {
70 | marginTop: theme.spacing(6),
71 | boxShadow: theme.customShadows.widget,
72 | backgroundColor: "white",
73 | width: "100%",
74 | textTransform: "none",
75 | },
76 | googleButtonCreating: {
77 | marginTop: 0,
78 | },
79 | googleIcon: {
80 | width: 30,
81 | marginRight: theme.spacing(2),
82 | },
83 | creatingButtonContainer: {
84 | marginTop: theme.spacing(2.5),
85 | height: 46,
86 | display: "flex",
87 | justifyContent: "center",
88 | alignItems: "center",
89 | },
90 | createAccountButton: {
91 | height: 46,
92 | textTransform: "none",
93 | },
94 | formDividerContainer: {
95 | marginTop: theme.spacing(4),
96 | marginBottom: theme.spacing(4),
97 | display: "flex",
98 | alignItems: "center",
99 | },
100 | formDividerWord: {
101 | paddingLeft: theme.spacing(2),
102 | paddingRight: theme.spacing(2),
103 | },
104 | formDivider: {
105 | flexGrow: 1,
106 | height: 1,
107 | backgroundColor: theme.palette.text.hint + "40",
108 | },
109 | errorMessage: {
110 | textAlign: "center",
111 | },
112 | textFieldUnderline: {
113 | "&:before": {
114 | borderBottomColor: theme.palette.primary.light,
115 | },
116 | "&:after": {
117 | borderBottomColor: theme.palette.primary.main,
118 | },
119 | "&:hover:before": {
120 | borderBottomColor: `${theme.palette.primary.light} !important`,
121 | },
122 | },
123 | textField: {
124 | borderBottomColor: theme.palette.background.light,
125 | },
126 | formButtons: {
127 | width: "100%",
128 | marginTop: theme.spacing(4),
129 | display: "flex",
130 | justifyContent: "space-between",
131 | alignItems: "center",
132 | },
133 | forgetButton: {
134 | textTransform: "none",
135 | fontWeight: 400,
136 | },
137 | loginLoader: {
138 | marginLeft: theme.spacing(4),
139 | },
140 | copyright: {
141 | marginTop: theme.spacing(4),
142 | whiteSpace: "nowrap",
143 | [theme.breakpoints.up("md")]: {
144 | position: "absolute",
145 | bottom: theme.spacing(2),
146 | },
147 | },
148 | }));
149 |
--------------------------------------------------------------------------------
/src/pages/maps/Maps.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | withGoogleMap,
4 | withScriptjs,
5 | GoogleMap,
6 | Marker,
7 | } from "react-google-maps";
8 |
9 | // styles
10 | import useStyles from "./styles";
11 |
12 | const BasicMap = withScriptjs(
13 | withGoogleMap(() => (
14 |
21 |
22 |
23 | )),
24 | );
25 |
26 | export default function Maps() {
27 | var classes = useStyles();
28 |
29 | return (
30 |
31 |
}
34 | containerElement={
}
35 | mapElement={
}
36 | />
37 |
38 | );
39 | }
40 |
--------------------------------------------------------------------------------
/src/pages/maps/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Maps",
3 | "version": "0.0.0",
4 | "main": "Maps.js",
5 | "private": true
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/maps/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | mapContainer: {
5 | height: "100%",
6 | margin: -theme.spacing(1) * 3,
7 | },
8 | }));
--------------------------------------------------------------------------------
/src/pages/notifications/Notifications.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { Grid } from "@material-ui/core";
3 | import { Close as CloseIcon } from "@material-ui/icons";
4 | import { ToastContainer, toast } from "react-toastify";
5 | import SyntaxHighlighter from "react-syntax-highlighter";
6 | import { docco } from "react-syntax-highlighter/dist/esm/styles/hljs";
7 | import classnames from "classnames";
8 |
9 | // styles
10 | import "react-toastify/dist/ReactToastify.css";
11 | import useStyles from "./styles";
12 |
13 | // components
14 | import Widget from "../../components/Widget/Widget";
15 | import PageTitle from "../../components/PageTitle/PageTitle";
16 | import Notification from "../../components/Notification";
17 | import { Typography, Button } from "../../components/Wrappers/Wrappers";
18 |
19 | const positions = [
20 | toast.POSITION.TOP_LEFT,
21 | toast.POSITION.TOP_CENTER,
22 | toast.POSITION.TOP_RIGHT,
23 | toast.POSITION.BOTTOM_LEFT,
24 | toast.POSITION.BOTTOM_CENTER,
25 | toast.POSITION.BOTTOM_RIGHT,
26 | ];
27 |
28 | export default function NotificationsPage(props) {
29 | var classes = useStyles();
30 |
31 | // local
32 | var [notificationsPosition, setNotificationPosition] = useState(2);
33 | var [errorToastId, setErrorToastId] = useState(null);
34 |
35 | return (
36 | <>
37 |
38 |
39 |
43 | }
44 | closeOnClick={false}
45 | progressClassName={classes.notificationProgress}
46 | />
47 |
48 |
49 |
50 | There are few position options available for notifications. You
51 | can click any of them to change notifications position:
52 |
53 |
54 |
55 |
74 |
75 | Click any position
76 |
77 |
78 | changeNotificationPosition(3)}
80 | className={classnames(classes.layoutButton, {
81 | [classes.layoutButtonActive]: notificationsPosition === 3,
82 | })}
83 | />
84 | changeNotificationPosition(4)}
86 | className={classnames(classes.layoutButton, {
87 | [classes.layoutButtonActive]: notificationsPosition === 4,
88 | })}
89 | />
90 | changeNotificationPosition(5)}
92 | className={classnames(classes.layoutButton, {
93 | [classes.layoutButtonActive]: notificationsPosition === 5,
94 | })}
95 | />
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | Different types of notifications for lost of use cases. Custom
104 | classes are also supported.
105 |
106 |
107 | handleNotificationCall("info")}
111 | className={classnames(classes.notificationCallButton)}
112 | >
113 | Info Message
114 |
115 | handleNotificationCall("error")}
119 | className={classnames(classes.notificationCallButton)}
120 | >
121 | Error + Retry Message
122 |
123 | handleNotificationCall("success")}
127 | className={classnames(classes.notificationCallButton)}
128 | >
129 | Success Message
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | Notifications are created with the help of{" "}
138 |
139 | react-toastify
140 |
141 |
142 |
143 |
{`
148 | // import needed components, functions and styles
149 | import { ToastContainer, toast } from 'react-toastify';
150 | import 'react-toastify/dist/ReactToastify.css';
151 |
152 | const Page = () => {
153 |
154 |
155 | toast('Toast Message')}>
156 | show notification
157 |
158 |
159 | };
160 | `}
161 |
162 | For more API information refer to the library documentation
163 |
164 |
165 |
166 |
167 |
168 |
169 |
177 |
185 |
193 |
201 |
209 |
217 |
218 |
219 |
220 |
221 |
227 |
233 |
239 |
245 |
251 |
257 |
258 |
259 |
260 |
261 |
268 |
275 |
282 |
289 |
296 |
303 |
304 |
305 |
306 | >
307 | );
308 |
309 | // #############################################################
310 | function sendNotification(componentProps, options) {
311 | return toast(
312 | ,
316 | options,
317 | );
318 | }
319 |
320 | function retryErrorNotification() {
321 | var componentProps = {
322 | type: "message",
323 | message: "Message was sent successfully!",
324 | variant: "contained",
325 | color: "success",
326 | };
327 | toast.update(errorToastId, {
328 | render: ,
329 | type: "success",
330 | });
331 | setErrorToastId(null);
332 | }
333 |
334 | function handleNotificationCall(notificationType) {
335 | var componentProps;
336 |
337 | if (errorToastId && notificationType === "error") return;
338 |
339 | switch (notificationType) {
340 | case "info":
341 | componentProps = {
342 | type: "feedback",
343 | message: "New user feedback received",
344 | variant: "contained",
345 | color: "primary",
346 | };
347 | break;
348 | case "error":
349 | componentProps = {
350 | type: "message",
351 | message: "Message was not sent!",
352 | variant: "contained",
353 | color: "secondary",
354 | extraButton: "Resend",
355 | extraButtonClick: retryErrorNotification,
356 | };
357 | break;
358 | default:
359 | componentProps = {
360 | type: "shipped",
361 | message: "The item was shipped",
362 | variant: "contained",
363 | color: "success",
364 | };
365 | }
366 |
367 | var toastId = sendNotification(componentProps, {
368 | type: notificationType,
369 | position: positions[notificationsPosition],
370 | progressClassName: classes.progress,
371 | onClose: notificationType === "error" && (() => setErrorToastId(null)),
372 | className: classes.notification,
373 | });
374 |
375 | if (notificationType === "error") setErrorToastId(toastId);
376 | }
377 |
378 | function changeNotificationPosition(positionId) {
379 | setNotificationPosition(positionId);
380 | }
381 | }
382 |
383 | // #############################################################
384 | function CloseButton({ closeToast, className }) {
385 | return ;
386 | }
387 |
--------------------------------------------------------------------------------
/src/pages/notifications/NotificationsContainer.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { withStyles } from "@material-ui/core";
3 | import { compose, withState, withHandlers } from "recompose";
4 | import { toast } from "react-toastify";
5 |
6 | import Notification from "../../components/Notification";
7 | import NotificationsView from "./NotificationsView";
8 |
9 | const positions = [
10 | toast.POSITION.TOP_LEFT,
11 | toast.POSITION.TOP_CENTER,
12 | toast.POSITION.TOP_RIGHT,
13 | toast.POSITION.BOTTOM_LEFT,
14 | toast.POSITION.BOTTOM_CENTER,
15 | toast.POSITION.BOTTOM_RIGHT
16 | ];
17 |
18 | export default compose(
19 | withStyles(theme => ({
20 | /*progress: {
21 | visibility: "hidden"
22 | },
23 | notification: {
24 | display: "flex",
25 | alignItems: "center",
26 | background: "transparent",
27 | boxShadow: "none",
28 | overflow: "visible"
29 | },
30 | notificationComponent: {
31 | paddingRight: theme.spacing.unit * 4
32 | }*/
33 | })),
34 | withState("notificationsPosition", "setNotificationPosition", 2),
35 | withState("errorToastId", "setErrorToastId", null),
36 | withHandlers({
37 | sendNotification: props => (componentProps, options) => {
38 | return toast(
39 | ,
43 | options
44 | );
45 | }
46 | }),
47 | withHandlers({
48 | retryErrorNotification: props => () => {
49 | const componentProps = {
50 | type: "message",
51 | message: "Message was sent successfully!",
52 | variant: "contained",
53 | color: "success",
54 | };
55 |
56 | toast.update(props.errorToastId, {
57 | render: ,
58 | type: "success"
59 | });
60 | props.setErrorToastId(null);
61 | }
62 | }),
63 | withHandlers({
64 | handleNotificationCall: props => notificationType => {
65 | let componentProps;
66 |
67 | if (props.errorToastId && notificationType === "error") return;
68 |
69 | switch (notificationType) {
70 | case "info":
71 | componentProps = {
72 | type: "feedback",
73 | message: "New user feedback received",
74 | variant: "contained",
75 | color: "primary"
76 | };
77 | break;
78 | case "error":
79 | componentProps = {
80 | type: "message",
81 | message: "Message was not sent!",
82 | variant: "contained",
83 | color: "secondary",
84 | extraButton: "Resend",
85 | extraButtonClick: props.retryErrorNotification
86 | };
87 | break;
88 | default:
89 | componentProps = {
90 | type: "shipped",
91 | message: "The item was shipped",
92 | variant: "contained",
93 | color: "success"
94 | };
95 | }
96 |
97 | const toastId = props.sendNotification(componentProps, {
98 | type: notificationType,
99 | position: positions[props.notificationsPosition],
100 | progressClassName: props.classes.progress,
101 | onClose:
102 | notificationType === "error" && (() => props.setErrorToastId(null)),
103 | className: props.classes.notification
104 | });
105 |
106 | if (notificationType === "error") props.setErrorToastId(toastId);
107 | },
108 | changeNotificationPosition: props => positionId => {
109 | props.setNotificationPosition(positionId);
110 | }
111 | })
112 | )(NotificationsView);
113 |
--------------------------------------------------------------------------------
/src/pages/notifications/NotificationsView.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Grid, withStyles } from '@material-ui/core';
3 | import { Close as CloseIcon } from '@material-ui/icons';
4 | import classnames from 'classnames';
5 | import { ToastContainer } from 'react-toastify';
6 | import SyntaxHighlighter from 'react-syntax-highlighter';
7 | import { docco } from 'react-syntax-highlighter/dist/esm/styles/hljs';
8 | import tinycolor from 'tinycolor2';
9 | import 'react-toastify/dist/ReactToastify.css';
10 |
11 | import Widget from '../../components/Widget';
12 | import PageTitle from '../../components/PageTitle';
13 | import NotificationCustomComponent from '../../components/Notification';
14 | import { Typography, Button } from '../../components/Wrappers';
15 |
16 | const CloseButton = ({ closeToast, className }) => (
17 |
21 | );
22 |
23 | const NotificationsPage = ({ classes, ...props}) => (
24 |
25 |
26 |
27 | } closeOnClick={false} progressClassName={classes.notificationProgress} />
28 |
29 |
30 | There are few position options available for notifications. You can click any of them to change notifications position:
31 |
32 |
33 | props.changeNotificationPosition(0)} className={classnames(classes.layoutButton, { [classes.layoutButtonActive]: props.notificationsPosition === 0})} />
34 | props.changeNotificationPosition(1)} className={classnames(classes.layoutButton, { [classes.layoutButtonActive]: props.notificationsPosition === 1})} />
35 | props.changeNotificationPosition(2)} className={classnames(classes.layoutButton, { [classes.layoutButtonActive]: props.notificationsPosition === 2})} />
36 |
37 |
Click any position
38 |
39 | props.changeNotificationPosition(3)} className={classnames(classes.layoutButton, { [classes.layoutButtonActive]: props.notificationsPosition === 3})} />
40 | props.changeNotificationPosition(4)} className={classnames(classes.layoutButton, { [classes.layoutButtonActive]: props.notificationsPosition === 4})} />
41 | props.changeNotificationPosition(5)} className={classnames(classes.layoutButton, { [classes.layoutButtonActive]: props.notificationsPosition === 5})} />
42 |
43 |
44 |
45 |
46 |
47 |
48 | Different types of notifications for lost of use cases. Custom classes are also supported.
49 |
50 | props.handleNotificationCall('info')} className={classnames(classes.notificationCallButton)}>Info Message
51 | props.handleNotificationCall('error')} className={classnames(classes.notificationCallButton)}>Error + Retry Message
52 | props.handleNotificationCall('success')} className={classnames(classes.notificationCallButton)}>Success Message
53 |
54 |
55 |
56 |
57 |
58 | Notifications are created with the help of react-toastify
59 |
60 |
{`
61 | // import needed components, functions and styles
62 | import { ToastContainer, toast } from 'react-toastify';
63 | import 'react-toastify/dist/ReactToastify.css';
64 |
65 | const Page = () => {
66 |
67 |
68 | toast('Toast Message')}>
69 | show notification
70 |
71 |
72 | };
73 | `}
74 |
For more API information refer to the library documentation
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | );
111 |
112 | const styles = (theme) => ({
113 | layoutContainer: {
114 | height: 200,
115 | display: 'flex',
116 | flexDirection: 'column',
117 | justifyContent: 'space-between',
118 | alignItems: 'center',
119 | marginTop: theme.spacing.unit * 2,
120 | border: '1px dashed',
121 | borderColor: theme.palette.primary.main,
122 | position: 'relative',
123 | },
124 | layoutText: {
125 | color: tinycolor(theme.palette.background.light).darken().toHexString(),
126 | },
127 | layoutButtonsRow: {
128 | width: '100%',
129 | display: 'flex',
130 | justifyContent: 'space-between',
131 | },
132 | layoutButton: {
133 | backgroundColor: theme.palette.background.light,
134 | width: 125,
135 | height: 50,
136 | outline: 'none',
137 | border: 'none',
138 | },
139 | layoutButtonActive: {
140 | backgroundColor: tinycolor(theme.palette.background.light).darken().toHexString(),
141 | },
142 | buttonsContainer: {
143 | display: 'flex',
144 | flexDirection: 'column',
145 | alignItems: 'flex-start',
146 | marginTop: theme.spacing.unit * 2,
147 | },
148 | notificationCallButton: {
149 | color: 'white',
150 | marginBottom: theme.spacing.unit,
151 | textTransform: 'none',
152 | },
153 | codeContainer: {
154 | display: 'flex',
155 | flexDirection: 'column',
156 | marginTop: theme.spacing.unit * 2,
157 | },
158 | codeComponent: {
159 | flexGrow: 1,
160 | },
161 | notificationItem: {
162 | marginTop: theme.spacing.unit * 2,
163 | },
164 | notificationCloseButton: {
165 | position: 'absolute',
166 | right: theme.spacing.unit * 2,
167 | },
168 | toastsContainer: {
169 | width: 400,
170 | marginTop: theme.spacing.unit * 6,
171 | right: 0,
172 | }
173 | });
174 |
175 | export default withStyles(styles, { withTheme: true})(NotificationsPage);
176 |
--------------------------------------------------------------------------------
/src/pages/notifications/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Notifications",
3 | "version": "0.0.0",
4 | "main": "Notifications.js",
5 | "private": true
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/notifications/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 | import tinycolor from "tinycolor2";
3 |
4 | export default makeStyles(theme => ({
5 | layoutContainer: {
6 | height: 200,
7 | display: "flex",
8 | flexDirection: "column",
9 | justifyContent: "space-between",
10 | alignItems: "center",
11 | marginTop: theme.spacing(2),
12 | border: "1px dashed",
13 | borderColor: theme.palette.primary.main,
14 | position: "relative",
15 | },
16 | layoutText: {
17 | color: tinycolor(theme.palette.background.light)
18 | .darken()
19 | .toHexString(),
20 | },
21 | layoutButtonsRow: {
22 | width: "100%",
23 | display: "flex",
24 | justifyContent: "space-between",
25 | },
26 | layoutButton: {
27 | backgroundColor: theme.palette.background.light,
28 | width: 125,
29 | height: 50,
30 | outline: "none",
31 | border: "none",
32 | },
33 | layoutButtonActive: {
34 | backgroundColor: tinycolor(theme.palette.background.light)
35 | .darken()
36 | .toHexString(),
37 | },
38 | buttonsContainer: {
39 | display: "flex",
40 | flexDirection: "column",
41 | alignItems: "flex-start",
42 | marginTop: theme.spacing(2),
43 | },
44 | notificationCallButton: {
45 | color: "white",
46 | marginBottom: theme.spacing(1),
47 | textTransform: "none",
48 | },
49 | codeContainer: {
50 | display: "flex",
51 | flexDirection: "column",
52 | marginTop: theme.spacing(2),
53 | },
54 | codeComponent: {
55 | flexGrow: 1,
56 | },
57 | notificationItem: {
58 | marginTop: theme.spacing(2),
59 | },
60 | notificationCloseButton: {
61 | position: "absolute",
62 | right: theme.spacing(2),
63 | },
64 | toastsContainer: {
65 | width: 400,
66 | marginTop: theme.spacing(6),
67 | right: 0,
68 | },
69 | progress: {
70 | visibility: "hidden",
71 | },
72 | notification: {
73 | display: "flex",
74 | alignItems: "center",
75 | background: "transparent",
76 | boxShadow: "none",
77 | overflow: "visible",
78 | },
79 | notificationComponent: {
80 | paddingRight: theme.spacing(4),
81 | },
82 | }));
83 |
--------------------------------------------------------------------------------
/src/pages/tables/Tables.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Grid } from "@material-ui/core";
3 | import MUIDataTable from "mui-datatables";
4 |
5 | // components
6 | import PageTitle from "../../components/PageTitle";
7 | import Widget from "../../components/Widget";
8 | import Table from "../dashboard/components/Table/Table";
9 |
10 | // data
11 | import mock from "../dashboard/mock";
12 |
13 | const datatableData = [
14 | ["Joe James", "Example Inc.", "Yonkers", "NY"],
15 | ["John Walsh", "Example Inc.", "Hartford", "CT"],
16 | ["Bob Herm", "Example Inc.", "Tampa", "FL"],
17 | ["James Houston", "Example Inc.", "Dallas", "TX"],
18 | ["Prabhakar Linwood", "Example Inc.", "Hartford", "CT"],
19 | ["Kaui Ignace", "Example Inc.", "Yonkers", "NY"],
20 | ["Esperanza Susanne", "Example Inc.", "Hartford", "CT"],
21 | ["Christian Birgitte", "Example Inc.", "Tampa", "FL"],
22 | ["Meral Elias", "Example Inc.", "Hartford", "CT"],
23 | ["Deep Pau", "Example Inc.", "Yonkers", "NY"],
24 | ["Sebastiana Hani", "Example Inc.", "Dallas", "TX"],
25 | ["Marciano Oihana", "Example Inc.", "Yonkers", "NY"],
26 | ["Brigid Ankur", "Example Inc.", "Dallas", "TX"],
27 | ["Anna Siranush", "Example Inc.", "Yonkers", "NY"],
28 | ["Avram Sylva", "Example Inc.", "Hartford", "CT"],
29 | ["Serafima Babatunde", "Example Inc.", "Tampa", "FL"],
30 | ["Gaston Festus", "Example Inc.", "Tampa", "FL"],
31 | ];
32 |
33 | export default function Tables() {
34 | return (
35 | <>
36 |
37 |
38 |
39 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | >
55 | );
56 | }
57 |
--------------------------------------------------------------------------------
/src/pages/tables/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Tables",
3 | "version": "0.0.0",
4 | "main": "Tables.js",
5 | "private": true
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/typography/Typography.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Grid } from "@material-ui/core";
3 |
4 | // styles
5 | import useStyles from "./styles";
6 |
7 | // components
8 | import PageTitle from "../../components/PageTitle";
9 | import Widget from "../../components/Widget";
10 | import { Typography } from "../../components/Wrappers";
11 |
12 | export default function TypographyPage() {
13 | var classes = useStyles();
14 |
15 | return (
16 | <>
17 |
18 |
19 |
20 |
21 |
22 |
23 | h1. Heading
24 |
25 |
26 | h2. Heading
27 |
28 |
29 | h3. Heading
30 |
31 |
32 | h4. Heading
33 |
34 |
35 | h5. Heading
36 |
37 | h6. Heading
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | h1. Heading
46 |
47 |
48 | h2. Heading
49 |
50 |
55 | h3. Heading
56 |
57 |
58 | h4. Heading
59 |
60 |
66 | h5. Heading
67 |
68 |
69 | h6. Heading
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | Basic text
78 |
79 | Basic light text
80 |
81 |
82 | Basic medium text
83 |
84 |
85 | Basic bold text
86 |
87 |
88 | BASIC UPPERCASE TEXT
89 |
90 |
91 | basic lowercase text
92 |
93 |
94 | Basic Capitalized Text
95 |
96 |
97 | Basic Cursive Text
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | Heading Typography SM Font Size
107 |
108 |
109 | Heading Typography Regular Font Size
110 |
111 |
112 | Heading Typography MD Font Size
113 |
114 |
115 | Heading Typography XL Font Size
116 |
117 |
118 | Heading Typography XXL Font Size
119 |
120 |
121 |
122 |
123 |
124 | >
125 | );
126 | }
127 |
--------------------------------------------------------------------------------
/src/pages/typography/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Typography",
3 | "version": "0.0.0",
4 | "main": "Typography.js",
5 | "private": true
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/typography/styles.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from "@material-ui/styles";
2 |
3 | export default makeStyles(theme => ({
4 | dashedBorder: {
5 | border: "1px dashed",
6 | borderColor: theme.palette.primary.main,
7 | padding: theme.spacing(2),
8 | paddingTop: theme.spacing(4),
9 | paddingBottom: theme.spacing(4),
10 | marginTop: theme.spacing(1),
11 | },
12 | text: {
13 | marginBottom: theme.spacing(2),
14 | },
15 | }));
16 |
--------------------------------------------------------------------------------
/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read http://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type');
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload();
115 | });
116 | });
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config);
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | );
126 | });
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister();
133 | });
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/themes/default.js:
--------------------------------------------------------------------------------
1 | import tinycolor from "tinycolor2";
2 |
3 | const primary = "#536DFE";
4 | const secondary = "#FF5C93";
5 | const warning = "#FFC260";
6 | const success = "#3CD4A0";
7 | const info = "#9013FE";
8 |
9 | const lightenRate = 7.5;
10 | const darkenRate = 15;
11 |
12 | export default {
13 | palette: {
14 | primary: {
15 | main: primary,
16 | light: tinycolor(primary)
17 | .lighten(lightenRate)
18 | .toHexString(),
19 | dark: tinycolor(primary)
20 | .darken(darkenRate)
21 | .toHexString(),
22 | },
23 | secondary: {
24 | main: secondary,
25 | light: tinycolor(secondary)
26 | .lighten(lightenRate)
27 | .toHexString(),
28 | dark: tinycolor(secondary)
29 | .darken(darkenRate)
30 | .toHexString(),
31 | contrastText: "#FFFFFF",
32 | },
33 | warning: {
34 | main: warning,
35 | light: tinycolor(warning)
36 | .lighten(lightenRate)
37 | .toHexString(),
38 | dark: tinycolor(warning)
39 | .darken(darkenRate)
40 | .toHexString(),
41 | },
42 | success: {
43 | main: success,
44 | light: tinycolor(success)
45 | .lighten(lightenRate)
46 | .toHexString(),
47 | dark: tinycolor(success)
48 | .darken(darkenRate)
49 | .toHexString(),
50 | },
51 | info: {
52 | main: info,
53 | light: tinycolor(info)
54 | .lighten(lightenRate)
55 | .toHexString(),
56 | dark: tinycolor(info)
57 | .darken(darkenRate)
58 | .toHexString(),
59 | },
60 | text: {
61 | primary: "#4A4A4A",
62 | secondary: "#6E6E6E",
63 | hint: "#B9B9B9",
64 | },
65 | background: {
66 | default: "#F6F7FF",
67 | light: "#F3F5FF",
68 | },
69 | },
70 | customShadows: {
71 | widget:
72 | "0px 3px 11px 0px #E8EAFC, 0 3px 3px -2px #B2B2B21A, 0 1px 8px 0 #9A9A9A1A",
73 | widgetDark:
74 | "0px 3px 18px 0px #4558A3B3, 0 3px 3px -2px #B2B2B21A, 0 1px 8px 0 #9A9A9A1A",
75 | widgetWide:
76 | "0px 12px 33px 0px #E8EAFC, 0 3px 3px -2px #B2B2B21A, 0 1px 8px 0 #9A9A9A1A",
77 | },
78 | overrides: {
79 | MuiBackdrop: {
80 | root: {
81 | backgroundColor: "#4A4A4A1A",
82 | },
83 | },
84 | MuiMenu: {
85 | paper: {
86 | boxShadow:
87 | "0px 3px 11px 0px #E8EAFC, 0 3px 3px -2px #B2B2B21A, 0 1px 8px 0 #9A9A9A1A",
88 | },
89 | },
90 | MuiSelect: {
91 | icon: {
92 | color: "#B9B9B9",
93 | },
94 | },
95 | MuiListItem: {
96 | root: {
97 | "&$selected": {
98 | backgroundColor: "#F3F5FF !important",
99 | "&:focus": {
100 | backgroundColor: "#F3F5FF",
101 | },
102 | },
103 | },
104 | button: {
105 | "&:hover, &:focus": {
106 | backgroundColor: "#F3F5FF",
107 | },
108 | },
109 | },
110 | MuiTouchRipple: {
111 | child: {
112 | backgroundColor: "white",
113 | },
114 | },
115 | MuiTableRow: {
116 | root: {
117 | height: 56,
118 | },
119 | },
120 | MuiTableCell: {
121 | root: {
122 | borderBottom: "1px solid rgba(224, 224, 224, .5)",
123 | },
124 | head: {
125 | fontSize: "0.95rem",
126 | },
127 | body: {
128 | fontSize: "0.95rem",
129 | },
130 | },
131 | },
132 | };
133 |
--------------------------------------------------------------------------------
/src/themes/index.js:
--------------------------------------------------------------------------------
1 | import defaultTheme from "./default";
2 |
3 | import { createMuiTheme } from "@material-ui/core";
4 |
5 | const overrides = {
6 | typography: {
7 | h1: {
8 | fontSize: "3rem",
9 | },
10 | h2: {
11 | fontSize: "2rem",
12 | },
13 | h3: {
14 | fontSize: "1.64rem",
15 | },
16 | h4: {
17 | fontSize: "1.5rem",
18 | },
19 | h5: {
20 | fontSize: "1.285rem",
21 | },
22 | h6: {
23 | fontSize: "1.142rem",
24 | },
25 | },
26 | };
27 |
28 | export default {
29 | default: createMuiTheme({ ...defaultTheme, ...overrides }),
30 | };
31 |
--------------------------------------------------------------------------------