From d2c6f85f9c89dff3c25f087d9af6b77be17b9a35 Mon Sep 17 00:00:00 2001 From: Zahraa Basheer <68440929+zhr9797@users.noreply.github.com> Date: Wed, 22 Dec 2021 15:17:25 +0300 Subject: [PATCH 1/3] Delete public directory --- public/favicon.ico | Bin 3870 -> 0 bytes public/index.html | 43 ------------------------------------------- public/logo192.png | Bin 5347 -> 0 bytes public/logo512.png | Bin 9664 -> 0 bytes public/manifest.json | 25 ------------------------- public/robots.txt | 3 --- 6 files changed, 71 deletions(-) delete mode 100644 public/favicon.ico delete mode 100644 public/index.html delete mode 100644 public/logo192.png delete mode 100644 public/logo512.png delete mode 100644 public/manifest.json delete mode 100644 public/robots.txt diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index a11777cc471a4344702741ab1c8a588998b1311a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/public/index.html b/public/index.html deleted file mode 100644 index aa069f2..0000000 --- a/public/index.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - React App - - - -
- - - diff --git a/public/logo192.png b/public/logo192.png deleted file mode 100644 index fc44b0a3796c0e0a64c3d858ca038bd4570465d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5347 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN diff --git a/public/manifest.json b/public/manifest.json deleted file mode 100644 index 080d6c7..0000000 --- a/public/manifest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} diff --git a/public/robots.txt b/public/robots.txt deleted file mode 100644 index e9e57dc..0000000 --- a/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: From daee7dae2bf6264958b745fe290bf27ad93e0f55 Mon Sep 17 00:00:00 2001 From: Zahraa Basheer <68440929+zhr9797@users.noreply.github.com> Date: Wed, 22 Dec 2021 15:18:55 +0300 Subject: [PATCH 2/3] Delete src directory --- src/App.css | 38 ------ src/App.js | 24 ---- src/App.test.js | 8 -- src/assets/images/1.jpg | Bin 3909 -> 0 bytes src/components/Avatar.jsx | 11 -- src/components/Drawer.jsx | 240 -------------------------------------- src/components/Users.jsx | 11 -- src/index.css | 13 --- src/index.js | 37 ------ src/logo.svg | 1 - src/pages/Categories.jsx | 17 --- src/pages/Dashboard.jsx | 32 ----- src/pages/Login.jsx | 40 ------- src/pages/Products.jsx | 12 -- src/reportWebVitals.js | 13 --- src/setupTests.js | 5 - src/utils/Constants.js | 2 - src/utils/axios.jsx | 4 - 18 files changed, 508 deletions(-) delete mode 100644 src/App.css delete mode 100644 src/App.js delete mode 100644 src/App.test.js delete mode 100644 src/assets/images/1.jpg delete mode 100644 src/components/Avatar.jsx delete mode 100644 src/components/Drawer.jsx delete mode 100644 src/components/Users.jsx delete mode 100644 src/index.css delete mode 100644 src/index.js delete mode 100644 src/logo.svg delete mode 100644 src/pages/Categories.jsx delete mode 100644 src/pages/Dashboard.jsx delete mode 100644 src/pages/Login.jsx delete mode 100644 src/pages/Products.jsx delete mode 100644 src/reportWebVitals.js delete mode 100644 src/setupTests.js delete mode 100644 src/utils/Constants.js delete mode 100644 src/utils/axios.jsx diff --git a/src/App.css b/src/App.css deleted file mode 100644 index 74b5e05..0000000 --- a/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/App.js b/src/App.js deleted file mode 100644 index 7a13708..0000000 --- a/src/App.js +++ /dev/null @@ -1,24 +0,0 @@ -import logo from './logo.svg'; -import './App.css'; -import Dashboard from './pages/Dashboard' -import Categories from './pages/Categories' -import Products from './pages/Products' -import Login from './pages/Login' -import {Navigate, Route, Routes} from 'react-router-dom' -import {useEffect,useState} from 'react' -import Drawer from './components/Drawer' - - -function App(props) { - - - return - }/> - }/> - }/> - }/> - - -} - -export default App; diff --git a/src/App.test.js b/src/App.test.js deleted file mode 100644 index 1f03afe..0000000 --- a/src/App.test.js +++ /dev/null @@ -1,8 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/src/assets/images/1.jpg b/src/assets/images/1.jpg deleted file mode 100644 index 00e8755c8e03c1ea600e78b72df8c98ef4055bf0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3909 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 l#fIs7jG^9L9}IByaSHX?gq=u=r{ - - - ); -} diff --git a/src/components/Drawer.jsx b/src/components/Drawer.jsx deleted file mode 100644 index 9e615f1..0000000 --- a/src/components/Drawer.jsx +++ /dev/null @@ -1,240 +0,0 @@ -import * as React from 'react'; -import { useEffect } from 'react' -import { styled, useTheme } from '@mui/material/styles'; -import Box from '@mui/material/Box'; -import Drawer from '@mui/material/Drawer'; -import CssBaseline from '@mui/material/CssBaseline'; -import MuiAppBar from '@mui/material/AppBar'; -import Toolbar from '@mui/material/Toolbar'; -import List from '@mui/material/List'; -import Typography from '@mui/material/Typography'; -import Divider from '@mui/material/Divider'; -import IconButton from '@mui/material/IconButton'; -import MenuIcon from '@mui/icons-material/Menu'; -import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; -import ChevronRightIcon from '@mui/icons-material/ChevronRight'; -import ListItem from '@mui/material/ListItem'; -import ListItemIcon from '@mui/material/ListItemIcon'; -import ListItemText from '@mui/material/ListItemText'; -import InboxIcon from '@mui/icons-material/MoveToInbox'; -import MailIcon from '@mui/icons-material/Mail'; -import { Routes, Link, Route, useLocation, useNavigate } from 'react-router-dom' -import Dashboard from '../pages/Dashboard' -import Categories from '../pages/Categories' -import Products from '../pages/Products' -import LogoutIcon from '@mui/icons-material/Logout'; -import GridViewIcon from '@mui/icons-material/GridView'; -import CategoryIcon from '@mui/icons-material/Category'; -import ProductionQuantityLimitsIcon from '@mui/icons-material/ProductionQuantityLimits'; -import Login from '../pages/Login' -import Avatar from './Avatar' -import MenuItem from '@mui/material/MenuItem'; -import Menu from '@mui/material/Menu'; -import Tooltip from '@mui/material/Tooltip'; -import {navigate} from 'react-router-dom' -import {TOKEN_KEY} from '../utils/Constants' - -const drawerWidth = 240; - - - -const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })( - ({ theme, open }) => ({ - flexGrow: 1, - padding: theme.spacing(3), - transition: theme.transitions.create('margin', { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.leavingScreen, - }), - marginLeft: `-${drawerWidth}px`, - ...(open && { - transition: theme.transitions.create('margin', { - easing: theme.transitions.easing.easeOut, - duration: theme.transitions.duration.enteringScreen, - }), - marginLeft: 0, - }), - }), -); - -const AppBar = styled(MuiAppBar, { - shouldForwardProp: (prop) => prop !== 'open', -})(({ theme, open }) => ({ - transition: theme.transitions.create(['margin', 'width'], { - easing: theme.transitions.easing.sharp, - duration: theme.transitions.duration.leavingScreen, - }), - ...(open && { - width: `calc(100% - ${drawerWidth}px)`, - marginLeft: `${drawerWidth}px`, - transition: theme.transitions.create(['margin', 'width'], { - easing: theme.transitions.easing.easeOut, - duration: theme.transitions.duration.enteringScreen, - }), - }), -})); - -const DrawerHeader = styled('div')(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - padding: theme.spacing(0, 1), - // necessary for content to be below app bar - ...theme.mixins.toolbar, - justifyContent: 'flex-end', -})); - -function PersistentDrawerLeft(props) { - const location = useLocation() - const navigate = useNavigate() - const theme = useTheme(); - const [open, setOpen] = React.useState(false); - - const [anchorElUser, setAnchorElUser] = React.useState(null); - - const handleDrawerOpen = () => { - setOpen(true); - }; - - const handleDrawerClose = () => { - setOpen(false); - }; - - const logout = () => { - localStorage.removeItem(TOKEN_KEY) - navigate('/login') - handleCloseUserMenu() - } - useEffect(() => { - - }, []) - const renderContent = (routeName) => { - console.log(routeName) - switch (routeName) { - case '/login': - return - case '/products': - return - case '/dashboard': - return - case '/categories': - return - } - } - const handleOpenUserMenu = (event) => { - setAnchorElUser(event.currentTarget); - }; - const handleCloseUserMenu = () => { - setAnchorElUser(null); - }; - return ( - - - - - - - - - - - - - - - - - - - - - Logout - - - - - - - - - - {theme.direction === 'ltr' ? : } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - {renderContent(location.pathname)} -
-
- ); -} - -export default PersistentDrawerLeft \ No newline at end of file diff --git a/src/components/Users.jsx b/src/components/Users.jsx deleted file mode 100644 index 5b3b0d7..0000000 --- a/src/components/Users.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -function Users(props) { - return ( -
-

Users component

-
- ); -} - -export default Users; \ No newline at end of file diff --git a/src/index.css b/src/index.css deleted file mode 100644 index ec2585e..0000000 --- a/src/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} diff --git a/src/index.js b/src/index.js deleted file mode 100644 index bb29a24..0000000 --- a/src/index.js +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; -import {BrowserRouter} from 'react-router-dom' -import Drawer from './components/Drawer' -import { createTheme, ThemeProvider, styled } from '@mui/material/styles'; - -const theme = createTheme({ - - palette: { - type: 'light', - primary: { - main: '#000000', - }, - secondary: { - main: '#f50057', - }, - }, -}) - -ReactDOM.render( - - - - - - - , - document.getElementById('root') -); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); diff --git a/src/logo.svg b/src/logo.svg deleted file mode 100644 index 9dfc1c0..0000000 --- a/src/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/pages/Categories.jsx b/src/pages/Categories.jsx deleted file mode 100644 index 0e9ce54..0000000 --- a/src/pages/Categories.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import React, { useEffect } from 'react'; - -function Categories(props) { - console.log(props) - useEffect(()=>{ - console.log('use effect') - let userData = JSON.parse(localStorage.getItem('myData')) - console.log(userData) - },[]) - return ( -
- Categories -
- ); -} - -export default Categories; \ No newline at end of file diff --git a/src/pages/Dashboard.jsx b/src/pages/Dashboard.jsx deleted file mode 100644 index 3c13707..0000000 --- a/src/pages/Dashboard.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import {Navigate} from 'react-router-dom' -function Dashboard(props) { - const [isLogged, setIsLogged] = React.useState(true) - useEffect(()=>{ - console.log('1') - let token; - try { - token = JSON.parse(localStorage.getItem('token')) - console.log('2') - if(!token) - setIsLogged(false) - - } catch (error) { - console.log(error) - setIsLogged(false) - } - - },[]) - console.log('3') - - if(!isLogged) - return - - return ( -
- Dashboard -
- ); -} - -export default Dashboard; \ No newline at end of file diff --git a/src/pages/Login.jsx b/src/pages/Login.jsx deleted file mode 100644 index cf8b851..0000000 --- a/src/pages/Login.jsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import { useNavigate } from 'react-router-dom'; -import axios from '../utils/axios' -import {TOKEN_KEY} from '../utils/Constants' -function Login(props) { - const navigate = useNavigate() - const [email, setEmail] = React.useState('') - const [password, setPassword] = React.useState('') - - const login = (e)=>{ - e.preventDefault() - axios.post('/api/academy/auth/login', - { - email:email, - password:password - } - ) - .then((response)=>{ - console.log(response) - let token = response.data.token.access_token; - let data = response.data; - localStorage.setItem(TOKEN_KEY, JSON.stringify(data)) - navigate('/dashboard') - }) - .catch((err)=>{ - console.log(err) - }) - } - return ( -
-
- setEmail(e.target.value)} type="email" /> - setPassword(e.target.value)} type="password" /> - -
-
- ); -} - -export default Login; \ No newline at end of file diff --git a/src/pages/Products.jsx b/src/pages/Products.jsx deleted file mode 100644 index e3fcba4..0000000 --- a/src/pages/Products.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import React, { useEffect } from 'react'; - -function Products(props) { - - return ( -
- Products -
- ); -} - -export default Products; \ No newline at end of file diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js deleted file mode 100644 index 5253d3a..0000000 --- a/src/reportWebVitals.js +++ /dev/null @@ -1,13 +0,0 @@ -const reportWebVitals = onPerfEntry => { - if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); - } -}; - -export default reportWebVitals; diff --git a/src/setupTests.js b/src/setupTests.js deleted file mode 100644 index 8f2609b..0000000 --- a/src/setupTests.js +++ /dev/null @@ -1,5 +0,0 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; diff --git a/src/utils/Constants.js b/src/utils/Constants.js deleted file mode 100644 index 1574da1..0000000 --- a/src/utils/Constants.js +++ /dev/null @@ -1,2 +0,0 @@ -export const TOKEN_KEY = 'token' -export const BASE_URL = 'https://website-backend.computiq.tech' \ No newline at end of file diff --git a/src/utils/axios.jsx b/src/utils/axios.jsx deleted file mode 100644 index 5610218..0000000 --- a/src/utils/axios.jsx +++ /dev/null @@ -1,4 +0,0 @@ -import axios from 'axios' -import {BASE_URL} from './Constants' -axios.defaults.baseURL = BASE_URL; -export default axios \ No newline at end of file From 86d8812c45f46a6a2ed626fbcbe6b684d144ef1e Mon Sep 17 00:00:00 2001 From: Zahraa Basheer <68440929+zhr9797@users.noreply.github.com> Date: Wed, 22 Dec 2021 15:21:01 +0300 Subject: [PATCH 3/3] Add files via upload --- public/favicon.ico | Bin 0 -> 3870 bytes public/index.html | 43 +++ public/logo192.png | Bin 0 -> 5347 bytes public/logo512.png | Bin 0 -> 9664 bytes public/manifest.json | 25 ++ public/robots.txt | 3 + src/App.css | 38 +++ src/App.js | 33 +++ src/App.test.js | 8 + src/common/Constants.js | 8 + src/components/BoardItems.jsx | 47 ++++ src/components/LoadingScreen.jsx | 11 + src/components/TaskItem.jsx | 43 +++ src/components/TaskItems.jsx | 13 + src/components/guards/AuthGuard.jsx | 24 ++ src/components/guards/GuestGuard.jsx | 24 ++ src/contexts/AuthContext.js | 255 ++++++++++++++++++ src/contexts/SettingsContext.js | 78 ++++++ src/hooks/useAuth.js | 6 + src/hooks/useSettings.js | 6 + src/index.css | 17 ++ src/index.js | 23 ++ src/layouts/DashboardLayout/NavBar/NavItem.js | 168 ++++++++++++ src/layouts/DashboardLayout/NavBar/index.js | 96 +++++++ src/layouts/DashboardLayout/TopBar/Account.js | 114 ++++++++ .../DashboardLayout/TopBar/Settings.js | 172 ++++++++++++ src/layouts/DashboardLayout/TopBar/index.js | 85 ++++++ src/layouts/DashboardLayout/index.js | 62 +++++ src/logo.svg | 1 + src/reportWebVitals.js | 13 + src/routes.js | 66 +++++ src/services/Http/DashoardService.js | 10 + src/services/Http/LoginService.js | 10 + src/setupTests.js | 5 + src/theme/index.js | 128 +++++++++ src/utils/axios.js | 29 ++ src/utils/classes/BaseHttp.js | 30 +++ src/utils/classes/HttpHelper.js | 92 +++++++ src/utils/responseHandler.js | 60 +++++ src/views/BoardView.jsx | 76 ++++++ src/views/LoginView.jsx | 82 ++++++ src/views/NotFoundView.jsx | 11 + 42 files changed, 2015 insertions(+) create mode 100644 public/favicon.ico create mode 100644 public/index.html create mode 100644 public/logo192.png create mode 100644 public/logo512.png create mode 100644 public/manifest.json create mode 100644 public/robots.txt create mode 100644 src/App.css create mode 100644 src/App.js create mode 100644 src/App.test.js create mode 100644 src/common/Constants.js create mode 100644 src/components/BoardItems.jsx create mode 100644 src/components/LoadingScreen.jsx create mode 100644 src/components/TaskItem.jsx create mode 100644 src/components/TaskItems.jsx create mode 100644 src/components/guards/AuthGuard.jsx create mode 100644 src/components/guards/GuestGuard.jsx create mode 100644 src/contexts/AuthContext.js create mode 100644 src/contexts/SettingsContext.js create mode 100644 src/hooks/useAuth.js create mode 100644 src/hooks/useSettings.js create mode 100644 src/index.css create mode 100644 src/index.js create mode 100644 src/layouts/DashboardLayout/NavBar/NavItem.js create mode 100644 src/layouts/DashboardLayout/NavBar/index.js create mode 100644 src/layouts/DashboardLayout/TopBar/Account.js create mode 100644 src/layouts/DashboardLayout/TopBar/Settings.js create mode 100644 src/layouts/DashboardLayout/TopBar/index.js create mode 100644 src/layouts/DashboardLayout/index.js create mode 100644 src/logo.svg create mode 100644 src/reportWebVitals.js create mode 100644 src/routes.js create mode 100644 src/services/Http/DashoardService.js create mode 100644 src/services/Http/LoginService.js create mode 100644 src/setupTests.js create mode 100644 src/theme/index.js create mode 100644 src/utils/axios.js create mode 100644 src/utils/classes/BaseHttp.js create mode 100644 src/utils/classes/HttpHelper.js create mode 100644 src/utils/responseHandler.js create mode 100644 src/views/BoardView.jsx create mode 100644 src/views/LoginView.jsx create mode 100644 src/views/NotFoundView.jsx diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a11777cc471a4344702741ab1c8a588998b1311a GIT binary patch literal 3870 zcma);c{J4h9>;%nil|2-o+rCuEF-(I%-F}ijC~o(k~HKAkr0)!FCj~d>`RtpD?8b; zXOC1OD!V*IsqUwzbMF1)-gEDD=A573Z-&G7^LoAC9|WO7Xc0Cx1g^Zu0u_SjAPB
3vGa^W|sj)80f#V0@M_CAZTIO(t--xg= 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..aa069f2 --- /dev/null +++ b/public/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + React App + + + +
+ + + diff --git a/public/logo192.png b/public/logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..fc44b0a3796c0e0a64c3d858ca038bd4570465d9 GIT binary patch literal 5347 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN literal 0 HcmV?d00001 diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..080d6c7 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..74b5e05 --- /dev/null +++ b/src/App.css @@ -0,0 +1,38 @@ +.App { + text-align: center; +} + +.App-logo { + height: 40vmin; + pointer-events: none; +} + +@media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } +} + +.App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +.App-link { + color: #61dafb; +} + +@keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/src/App.js b/src/App.js new file mode 100644 index 0000000..c08e629 --- /dev/null +++ b/src/App.js @@ -0,0 +1,33 @@ +import "./App.css"; +import routes, { renderRoutes } from "./routes"; +import { Router } from "react-router-dom"; +import { AuthProvider } from "./contexts/AuthContext"; +import { createBrowserHistory } from "history"; +import { createTheme } from "./theme"; +import { create } from "jss"; +import rtl from "jss-rtl"; +import { useContext } from "react"; +import { jssPreset, StylesProvider, ThemeProvider } from "@material-ui/core"; +import SettingsContext from './contexts/SettingsContext' +const history = createBrowserHistory(); +const jss = create({ plugins: [...jssPreset().plugins, rtl()] }); + +function App() { + const { settings } = useContext(SettingsContext); + const theme = createTheme({ + direction: settings.direction, + responsiveFontSizes: settings.responsiveFontSizes, + theme: settings.theme, + }); + return ( + + + + {renderRoutes(routes)} + + + + ); +} + +export default App; diff --git a/src/App.test.js b/src/App.test.js new file mode 100644 index 0000000..1f03afe --- /dev/null +++ b/src/App.test.js @@ -0,0 +1,8 @@ +import { render, screen } from '@testing-library/react'; +import App from './App'; + +test('renders learn react link', () => { + render(); + const linkElement = screen.getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); diff --git a/src/common/Constants.js b/src/common/Constants.js new file mode 100644 index 0000000..0c33a95 --- /dev/null +++ b/src/common/Constants.js @@ -0,0 +1,8 @@ +export const SESSION_KEY = "CompUserData"; +export const BASE_URL = "https://website-backend.computiq.tech"; + +export const THEMES = { + LIGHT: 'LIGHT', + ONE_DARK: 'ONE_DARK' + }; + \ No newline at end of file diff --git a/src/components/BoardItems.jsx b/src/components/BoardItems.jsx new file mode 100644 index 0000000..2571708 --- /dev/null +++ b/src/components/BoardItems.jsx @@ -0,0 +1,47 @@ +import React from 'react' +import { Box,makeStyles, Typography } from '@material-ui/core'; + + +const useStyles = makeStyles(()=>({ + flx:{ + color: '#575756', + display: 'flex', + justifyContent: 'space-between', + alignItems:'center' + }, + + box: { + display: 'flex', + alignItems:'center' + }, + + img: { + fontSize: 35, + marginLeft: 5 + } + +})) + + +export default function BoardItems(props) { + const classes = useStyles() + return ( + <> + SCORE BOARD + { + props.dataP.map((item,i)=>{ + return ( + + + #{props.data.findIndex((data)=> (data.user__first_name+' '+data.user__last_name)===(item.user__first_name+' '+item.user__last_name) )} + {item.user__score_profile__photo} + + {item.user__first_name+' '+item.user__last_name} + {item.total_score} points + + ) + }) + } + + ) +} diff --git a/src/components/LoadingScreen.jsx b/src/components/LoadingScreen.jsx new file mode 100644 index 0000000..f72b4c8 --- /dev/null +++ b/src/components/LoadingScreen.jsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function LoadingScreen(props) { + return ( +
+ LoadingScreen +
+ ); +} + +export default LoadingScreen; \ No newline at end of file diff --git a/src/components/TaskItem.jsx b/src/components/TaskItem.jsx new file mode 100644 index 0000000..9ba62dd --- /dev/null +++ b/src/components/TaskItem.jsx @@ -0,0 +1,43 @@ +import React from 'react' +import parse from 'html-react-parser'; + +import { Box , makeStyles} from '@material-ui/core'; +import Collapse from '@mui/material/Collapse'; +import ExpandLess from '@mui/icons-material/ExpandLess'; +import ExpandMore from '@mui/icons-material/ExpandMore'; + +const useStyles = makeStyles(()=>({ + flx:{ + color: '#575756', + display: 'flex', + justifyContent: 'space-between', + alignItems:'center' + }, + + box: { + backgroundColor: 'white', + padding: 20, + borderRadius: 20, + border: '1px solid #c6c6c6', + color: '#575756', + marginBottom: 20, + cursor: 'pointer' + }, + +})) + +export default function TaskItem(props) { + const classes = useStyles() + const [open, setOpen] = React.useState(false); + + return ( + setOpen(!open)} className={classes.box}> + + {props.title} {open ? : } + + + { parse(props.desc) } + + + ) +} diff --git a/src/components/TaskItems.jsx b/src/components/TaskItems.jsx new file mode 100644 index 0000000..89a5e97 --- /dev/null +++ b/src/components/TaskItems.jsx @@ -0,0 +1,13 @@ +import React from 'react' +import TaskItem from './TaskItem' + + +export default function TaskItems(props) { + return ( + <> + { + props.tasks.map((task,i)=> ) + } + + ) +} diff --git a/src/components/guards/AuthGuard.jsx b/src/components/guards/AuthGuard.jsx new file mode 100644 index 0000000..0f9fa2c --- /dev/null +++ b/src/components/guards/AuthGuard.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { Redirect } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import useAuth from '../../hooks/useAuth'; + +const AuthGuard = ({ children }) => { + const { isAuthenticated } = useAuth(); + + if (!isAuthenticated) { + return ; + } + + return ( + <> + {children} + + ); +}; + +AuthGuard.propTypes = { + children: PropTypes.node +}; + +export default AuthGuard; diff --git a/src/components/guards/GuestGuard.jsx b/src/components/guards/GuestGuard.jsx new file mode 100644 index 0000000..1a5917d --- /dev/null +++ b/src/components/guards/GuestGuard.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { Redirect } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import useAuth from '../../hooks/useAuth'; + +const GuestGuard = ({ children }) => { + const { isAuthenticated } = useAuth(); + + if (isAuthenticated) { + return ; + } + + return ( + <> + {children} + + ); +}; + +GuestGuard.propTypes = { + children: PropTypes.node +}; + +export default GuestGuard; diff --git a/src/contexts/AuthContext.js b/src/contexts/AuthContext.js new file mode 100644 index 0000000..2e94f6c --- /dev/null +++ b/src/contexts/AuthContext.js @@ -0,0 +1,255 @@ +import React, { + createContext, + useEffect, + useReducer + } from 'react'; + import jwtDecode from 'jwt-decode'; + import LoadingScreen from '../components/LoadingScreen'; + import axios from '../utils/axios'; + import { LoginService } from '../services/Http/LoginService'; + import { handleResponse } from '../utils/responseHandler'; + import {SESSION_KEY} from '../common/Constants' + const initialAuthState = { + isAuthenticated: false, + isInitialised: false, + user: null, + error:null + }; + + const isValidToken = (tokenObj) => { + console.log(tokenObj) + if (!tokenObj) { + return false; + } + const decoded = jwtDecode(tokenObj.access_token); + const currentTime = Date.now() / 1000; + return decoded.exp > currentTime; + }; + + + const setSessionData = (data) => { + if (data) { + localStorage.setItem(SESSION_KEY, JSON.stringify(data)); + axios.defaults.headers.common.Authorization = `Bearer ${data.token.access_token}`; + } else { + localStorage.removeItem(SESSION_KEY); + delete axios.defaults.headers.common.Authorization; + } + }; + const reducer = (state, action) => { + + switch (action.type) { + case 'INITIALISE': { + const { isAuthenticated, user } = action.payload; + + return { + ...state, + isAuthenticated, + isInitialised: true, + user, + error:null + }; + } + case 'LOGIN': { + const { data } = action.payload; + const user = data; + console.log('in login reducer, user fetched is: ' ) + console.log(data,user) + return { + ...state, + isAuthenticated: true, + user, + error:null + }; + } + case 'LOGOUT': { + return { + ...state, + isAuthenticated: false, + user: null, + error:null + }; + } + + case 'ERROR': { + const errorMSG = action.payload; + + console.log('error dispatched') + console.log(errorMSG) + return { + ...state, + isAuthenticated: false, + error:errorMSG.error.message + }; + } + default: { + return { ...state }; + } + } + }; + + const AuthContext = createContext({ + ...initialAuthState, + method: 'JWT', + login: () => Promise.resolve(), + logout: () => { } + }); + + export const AuthProvider = ({ children }) => { + const [state, dispatch] = useReducer(reducer, initialAuthState); + + const login = (email, password) =>{ + (new LoginService).login({ + email:email, + password:password + }) + .then((res)=>{ + console.log('response is: ',res) + if(res.status == '200') + { + const data = res.data; + // // origin + setSessionData(data) + // setSession(data); + console.log('after set session data,',data) + dispatch({ + type: 'LOGIN', + payload: { + data + } + }); + } + else{ // 404, 400, + let resp = handleResponse(res) + console.log('error of resp handler is : ') + console.log(resp) + dispatch({ + type: 'ERROR', + payload: { + error:resp + } + }); + } + + }) + .catch((err)=>{ + let resp = handleResponse(err) + console.log('error caught: ',err) + dispatch({ + type:'ERROR', + payload:{ + error:resp + } + }) + }) + } + // const login = async (email, password) => { + + // try{ + // const response = await (new LoginService).login({email,password}); + // console.log('response is',response) + // if(!response.data) + // return response + // const data = response.data; + // // origin + // setSessionData(data) + // // setSession(data); + // console.log('after set session data,',data) + // dispatch({ + // type: 'LOGIN', + // payload: { + // data + // } + // }); + + + // return response; + // } + // catch(err) + // { + // console.log('error caught',err) + // dispatch({ + // type: 'ERROR', + // payload: { + // err + // } + // }); + // } + + + + + + // }; + + const logout = () => { + setSessionData(null); + dispatch({ type: 'LOGOUT' }); + }; + + + useEffect(() => { + const initialise = async () => { + try { + console.log('try to load userData from localstaorage') + // const accessToken = window.localStorage.getItem('accessToken'); + let user = window.localStorage.getItem(SESSION_KEY); + if(user) + { + user = JSON.parse(user); + } + console.log(user) + if (user && user.token && isValidToken(user.token)) { + setSessionData(user); + dispatch({ + type: 'INITIALISE', + payload: { + isAuthenticated: true, + user + } + }); + } else { + console.log('user data not found or expired') + dispatch({ + type: 'INITIALISE', + payload: { + isAuthenticated: false, + user: null + } + }); + } + } catch (err) { + let resp = handleResponse(err) + dispatch({ + type: 'INITIALISE', + payload: { + isAuthenticated: false, + user: null + } + }); + } + }; + + initialise(); + }, []); + if (!state.isInitialised) { + return ; + } + + return ( + + {children} + + ); + }; + + export default AuthContext; \ No newline at end of file diff --git a/src/contexts/SettingsContext.js b/src/contexts/SettingsContext.js new file mode 100644 index 0000000..67cf25c --- /dev/null +++ b/src/contexts/SettingsContext.js @@ -0,0 +1,78 @@ +import React, { + createContext, + useEffect, + useState +} from 'react'; +import _ from 'lodash'; +import { THEMES } from '../common/Constants'; +// 1 +const defaultSettings = { + direction: 'ltr', + responsiveFontSizes: true, + theme: THEMES.LIGHT +}; + +export const restoreSettings = () => { + let settings = null; + + try { + const storedData = window.localStorage.getItem('settings'); + + if (storedData) { + settings = JSON.parse(storedData); + } + } catch (err) { + console.error(err); + // If stored data is not a strigified JSON this will fail, + // that's why we catch the error + } + + return settings; +}; + +export const storeSettings = (settings) => { + window.localStorage.setItem('settings', JSON.stringify(settings)); +}; +// 2 +const SettingsContext = createContext({ + settings: defaultSettings, + saveSettings: () => { } +}); + +export const SettingsProvider = ({ settings, children }) => { + const [currentSettings, setCurrentSettings] = useState(settings || defaultSettings); + + const handleSaveSettings = (update = {}) => { + const mergedSettings = _.merge({}, currentSettings, update); + + setCurrentSettings(mergedSettings); + storeSettings(mergedSettings); + }; + + useEffect(() => { + const restoredSettings = restoreSettings(); + + if (restoredSettings) { + setCurrentSettings(restoredSettings); + } + }, []); + + useEffect(() => { + document.dir = currentSettings.direction; + }, [currentSettings]); + + return ( + + {children} + + ); +}; + +export const SettingsConsumer = SettingsContext.Consumer; + +export default SettingsContext; diff --git a/src/hooks/useAuth.js b/src/hooks/useAuth.js new file mode 100644 index 0000000..a5b69fd --- /dev/null +++ b/src/hooks/useAuth.js @@ -0,0 +1,6 @@ +import { useContext } from 'react'; +import AuthContext from '../contexts/AuthContext'; + +const useAuth = () => useContext(AuthContext); + +export default useAuth; diff --git a/src/hooks/useSettings.js b/src/hooks/useSettings.js new file mode 100644 index 0000000..fe0fb11 --- /dev/null +++ b/src/hooks/useSettings.js @@ -0,0 +1,6 @@ +import { useContext } from 'react'; +import SettingsContext from '../contexts/SettingsContext'; + +const useSettings = () => useContext(SettingsContext); + +export default useSettings; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..17c3491 --- /dev/null +++ b/src/index.css @@ -0,0 +1,17 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} + +.MuiPagination-ul { + justify-content: space-around; +} \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..9a5b6c0 --- /dev/null +++ b/src/index.js @@ -0,0 +1,23 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import reportWebVitals from './reportWebVitals'; +import { SnackbarProvider } from 'notistack'; +import {SettingsProvider} from './contexts/SettingsContext' +ReactDOM.render( + + + + + + + + , + document.getElementById('root') +); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/src/layouts/DashboardLayout/NavBar/NavItem.js b/src/layouts/DashboardLayout/NavBar/NavItem.js new file mode 100644 index 0000000..1300812 --- /dev/null +++ b/src/layouts/DashboardLayout/NavBar/NavItem.js @@ -0,0 +1,168 @@ +import React, { useState } from 'react'; +import { NavLink as RouterLink } from 'react-router-dom'; +import clsx from 'clsx'; +import PropTypes from 'prop-types'; +import { + Button, + Collapse, + ListItem, + makeStyles +} from '@material-ui/core'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import ExpandLessIcon from '@mui/icons-material/ExpandLess'; + +const useStyles = makeStyles((theme) => ({ + item: { + display: 'block', + paddingTop: 0, + paddingBottom: 0 + }, + itemLeaf: { + display: 'flex', + paddingTop: 0, + paddingBottom: 0 + }, + button: { + color: theme.palette.text.secondary, + padding: '10px 8px', + justifyContent: 'flex-start', + textTransform: 'none', + letterSpacing: 0, + width: '100%' + }, + buttonLeaf: { + color: theme.palette.text.secondary, + padding: '10px 8px', + justifyContent: 'flex-start', + textTransform: 'none', + letterSpacing: 0, + width: '100%', + fontWeight: theme.typography.fontWeightRegular, + '&.depth-0': { + '& $title': { + fontWeight: theme.typography.fontWeightMedium + } + } + }, + icon: { + display: 'flex', + alignItems: 'center', + marginRight: theme.spacing(1) + }, + title: { + marginRight: 'auto' + }, + active: { + color: theme.palette.secondary.main, + '& $title': { + fontWeight: theme.typography.fontWeightMedium + }, + '& $icon': { + color: theme.palette.secondary.main + } + } +})); + +const NavItem = ({ + children, + className, + depth, + href, + icon: Icon, + info: Info, + open: openProp, + title, + ...rest +}) => { + const classes = useStyles(); + const [open, setOpen] = useState(openProp); + + const handleToggle = () => { + setOpen((prevOpen) => !prevOpen); + }; + + let paddingLeft = 8; + + if (depth > 0) { + paddingLeft = 32 + 8 * depth; + } + + const style = { paddingLeft }; + + if (children) { + return ( + + + + {children} + + + ); + } + + return ( + + + + ); +}; + +NavItem.propTypes = { + children: PropTypes.node, + className: PropTypes.string, + depth: PropTypes.number.isRequired, + href: PropTypes.string, + icon: PropTypes.elementType, + info: PropTypes.elementType, + open: PropTypes.bool, + title: PropTypes.string.isRequired +}; + +NavItem.defaultProps = { + open: false +}; + +export default NavItem; diff --git a/src/layouts/DashboardLayout/NavBar/index.js b/src/layouts/DashboardLayout/NavBar/index.js new file mode 100644 index 0000000..3e6e530 --- /dev/null +++ b/src/layouts/DashboardLayout/NavBar/index.js @@ -0,0 +1,96 @@ +/* eslint-disable no-use-before-define */ +import React, { useEffect } from 'react'; +import { useLocation, matchPath } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import { + Box, + Drawer, + Hidden, + makeStyles +} from '@material-ui/core'; +import useAuth from '../../../hooks/useAuth'; + + + +function renderNavItems({ + items, + pathname, + depth = 0 +}) { + return ( +

+ ); +} + + +const useStyles = makeStyles(() => ({ + mobileDrawer: { + width: 256 + }, + desktopDrawer: { + width: 256, + top: 64, + height: 'calc(100% - 64px)' + }, + avatar: { + cursor: 'pointer', + width: 64, + height: 64 + } +})); + +const NavBar = ({ onMobileClose, openMobile }) => { + const classes = useStyles(); + const location = useLocation(); + const { user } = useAuth(); + + useEffect(() => { + if (openMobile && onMobileClose) { + onMobileClose(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [location.pathname]); + + const content = ( + + + + ); + + return ( + <> + + + {content} + + + + + {content} + + + + ); +}; + +NavBar.propTypes = { + onMobileClose: PropTypes.func, + openMobile: PropTypes.bool +}; + +export default NavBar; diff --git a/src/layouts/DashboardLayout/TopBar/Account.js b/src/layouts/DashboardLayout/TopBar/Account.js new file mode 100644 index 0000000..dd0d1db --- /dev/null +++ b/src/layouts/DashboardLayout/TopBar/Account.js @@ -0,0 +1,114 @@ +import React, { + useRef, + useState +} from 'react'; +import { Link as RouterLink } from 'react-router-dom'; +import { useHistory } from 'react-router-dom'; +import { useSnackbar } from 'notistack'; +import { + Avatar, + Box, + ButtonBase, + Hidden, + Menu, + MenuItem, + Typography, + makeStyles +} from '@material-ui/core'; +import useAuth from '../../../hooks/useAuth'; + +const useStyles = makeStyles((theme) => ({ + avatar: { + height: 32, + width: 32, + marginRight: theme.spacing(1) + }, + popover: { + width: 200 + } +})); + +const Account = () => { + const classes = useStyles(); + const history = useHistory(); + const ref = useRef(null); + const { user, logout} = useAuth(); + + const { enqueueSnackbar } = useSnackbar(); + const [isOpen, setOpen] = useState(false); + + const handleOpen = () => { + setOpen(true); + }; + + const handleClose = () => { + setOpen(false); + }; + + const handleLogout = async () => { + try { + handleClose(); + await logout(); + history.push('/login'); + } catch (err) { + enqueueSnackbar('Unable to logout', { + variant: 'error' + }); + } + }; + return ( + <> + + + + + {user.profile.user.first_name} + + + + + + Profile + + + Account + + + Logout + + + + ); +} + +export default Account; diff --git a/src/layouts/DashboardLayout/TopBar/Settings.js b/src/layouts/DashboardLayout/TopBar/Settings.js new file mode 100644 index 0000000..c0cd85e --- /dev/null +++ b/src/layouts/DashboardLayout/TopBar/Settings.js @@ -0,0 +1,172 @@ +import React, { + useState, + useRef +} from 'react'; +import { capitalCase } from 'change-case'; +import { + Badge, + Box, + Button, + FormControlLabel, + IconButton, + Popover, + SvgIcon, + Switch, + TextField, + Tooltip, + Typography, + makeStyles +} from '@material-ui/core'; +import { Settings as SettingsIcon } from 'react-feather'; +import useSettings from '../../../hooks/useSettings'; +import { THEMES } from '../../../common/Constants'; + +const useStyles = makeStyles((theme) => ({ + badge: { + height: 10, + width: 10, + borderRadius: 5, + marginTop: 10, + marginRight: 5 + }, + popover: { + width: 320, + padding: theme.spacing(2) + } +})); + +const Settings = () => { + const classes = useStyles(); + const ref = useRef(null); + const { settings, saveSettings } = useSettings(); + const [isOpen, setOpen] = useState(false); + const [values, setValues] = useState({ + direction: settings.direction, + responsiveFontSizes: settings.responsiveFontSizes, + theme: settings.theme + }); + + const handleOpen = () => { + setOpen(true); + }; + + const handleClose = () => { + setOpen(false); + }; + + const handleChange = (field, value) => { + setValues({ + ...values, + [field]: value + }); + }; + + const handleSave = () => { + saveSettings(values); + setOpen(false); + }; + + return ( + <> + + + + + + + + + + + + Settings + + + handleChange('direction', event.target.checked ? 'rtl' : 'ltr')} + /> + )} + label="RTL" + /> + + + handleChange('responsiveFontSizes', event.target.checked)} + /> + )} + label="Responsive font sizes" + /> + + + handleChange('theme', event.target.value)} + select + SelectProps={{ native: true }} + value={values.theme} + variant="outlined" + > + {Object.keys(THEMES).map((theme) => ( + + ))} + + + + + + + + ); +} + +export default Settings; diff --git a/src/layouts/DashboardLayout/TopBar/index.js b/src/layouts/DashboardLayout/TopBar/index.js new file mode 100644 index 0000000..5f467fb --- /dev/null +++ b/src/layouts/DashboardLayout/TopBar/index.js @@ -0,0 +1,85 @@ +import React from 'react'; +import { Link as RouterLink } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; +import { + AppBar, + Box, + Hidden, + IconButton, + Toolbar, + makeStyles, + SvgIcon +} from '@material-ui/core'; +import { Menu as MenuIcon } from 'react-feather'; +import { THEMES } from '../../../common/Constants'; +import Account from './Account'; +import Settings from './Settings'; + +const useStyles = makeStyles((theme) => ({ + root: { + ...theme.name === THEMES.LIGHT ? { + boxShadow: 'none', + backgroundColor: theme.palette.primary.main + } : {}, + ...theme.name === THEMES.ONE_DARK ? { + backgroundColor: theme.palette.background.default + } : {} + }, + toolbar: { + minHeight: 64 + }, + logo:{ + maxHeight:'40px', + maxWidth:'40px' + } +})); + +const TopBar = ({ + className, + onMobileNavOpen, + ...rest +}) => { + const classes = useStyles(); + + return ( + + + + + + + + + + + + + + + + + + + ); +}; + +TopBar.propTypes = { + className: PropTypes.string, + onMobileNavOpen: PropTypes.func +}; + +TopBar.defaultProps = { + onMobileNavOpen: () => {} +}; + +export default TopBar; diff --git a/src/layouts/DashboardLayout/index.js b/src/layouts/DashboardLayout/index.js new file mode 100644 index 0000000..cd647c7 --- /dev/null +++ b/src/layouts/DashboardLayout/index.js @@ -0,0 +1,62 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import { makeStyles } from '@material-ui/core'; +import NavBar from './NavBar'; +import TopBar from './TopBar'; + +const useStyles = makeStyles((theme) => ({ + root: { + backgroundColor: theme.palette.background.dark, + display: 'flex', + height: '100%', + overflow: 'hidden', + width: '100%' + }, + wrapper: { + display: 'flex', + flex: '1 1 auto', + overflow: 'hidden', + paddingTop: 64, + // [theme.breakpoints.up('lg')]: { + // paddingLeft: 256 + // } + }, + contentContainer: { + display: 'flex', + flex: '1 1 auto', + overflow: 'hidden' + }, + content: { + flex: '1 1 auto', + height: '100%', + overflow: 'auto' + } +})); + +const DashboardLayout = ({ children }) => { + const classes = useStyles(); + const [isMobileNavOpen, setMobileNavOpen] = useState(false); + + return ( +
+ setMobileNavOpen(true)} /> + {/* setMobileNavOpen(false)} + openMobile={isMobileNavOpen} + /> */} +
+
+
+ {children} +
+
+
+
+ ); +}; + +DashboardLayout.propTypes = { + children: PropTypes.node +}; + +export default DashboardLayout; diff --git a/src/logo.svg b/src/logo.svg new file mode 100644 index 0000000..9dfc1c0 --- /dev/null +++ b/src/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js new file mode 100644 index 0000000..5253d3a --- /dev/null +++ b/src/reportWebVitals.js @@ -0,0 +1,13 @@ +const reportWebVitals = onPerfEntry => { + if (onPerfEntry && onPerfEntry instanceof Function) { + import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + getCLS(onPerfEntry); + getFID(onPerfEntry); + getFCP(onPerfEntry); + getLCP(onPerfEntry); + getTTFB(onPerfEntry); + }); + } +}; + +export default reportWebVitals; diff --git a/src/routes.js b/src/routes.js new file mode 100644 index 0000000..72a91e2 --- /dev/null +++ b/src/routes.js @@ -0,0 +1,66 @@ +import React, { + Suspense, + Fragment, + lazy +} from 'react'; +import { + Switch, + Redirect, + Route +} from 'react-router-dom'; +import DashboardLayout from './layouts/DashboardLayout'; +import LoadingScreen from './components/LoadingScreen'; +import AuthGuard from './components/guards/AuthGuard'; +import GuestGuard from './components/guards/GuestGuard'; + +export const renderRoutes = (routes = []) => ( + }> + + {routes.map((route, i) => { + const Guard = route.guard || Fragment; + const Layout = route.layout || Fragment; + const Component = route.component; + + return ( + ( + + + + + + + + )} + /> + ); + })} + + +); + +export const routes = [ + { + exact: true, + path: '/404', + component: lazy(() => import('./views/NotFoundView')) + }, + { + exact: true, + guard: GuestGuard, + path: '/login', + component: lazy(() => import('./views/LoginView')) + }, + { + exact: true, + guard: AuthGuard, + path: '/board', + layout:DashboardLayout, + component: lazy(() => import('./views/BoardView')) + } +]; + +export default routes; diff --git a/src/services/Http/DashoardService.js b/src/services/Http/DashoardService.js new file mode 100644 index 0000000..333f479 --- /dev/null +++ b/src/services/Http/DashoardService.js @@ -0,0 +1,10 @@ +import { BaseService } from "../../utils/classes/BaseHttp" + +export class DashboradService extends BaseService { + constructor() { + super('') + } + async loadPoints(){ + return await this.http.get("api/score/data/5") + } +} \ No newline at end of file diff --git a/src/services/Http/LoginService.js b/src/services/Http/LoginService.js new file mode 100644 index 0000000..c86883f --- /dev/null +++ b/src/services/Http/LoginService.js @@ -0,0 +1,10 @@ +import { BaseService } from "../../utils/classes/BaseHttp" + +export class LoginService extends BaseService { + constructor() { + super('') + } + async login(body){ + return await this.http.post("/api/score/auth/login",body) + } +} \ No newline at end of file diff --git a/src/setupTests.js b/src/setupTests.js new file mode 100644 index 0000000..8f2609b --- /dev/null +++ b/src/setupTests.js @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom'; diff --git a/src/theme/index.js b/src/theme/index.js new file mode 100644 index 0000000..c00e818 --- /dev/null +++ b/src/theme/index.js @@ -0,0 +1,128 @@ + + +import _ from 'lodash' +import {THEMES} from '../common/Constants' +import { + colors, + createMuiTheme, + responsiveFontSizes +} from '@material-ui/core'; +const themesOptions = [ + { + name: THEMES.LIGHT, + overrides: { + MuiInputBase: { + input: { + '&::placeholder': { + opacity: 1, + color: colors.blueGrey[600] + } + } + } + }, + palette: { + type: 'light', + action: { + active: colors.blueGrey[600] + }, + background: { + default: colors.common.white, + dark: colors.common.white, + paper: colors.common.white + }, + primary: { + main: '#00bbf0'//ex: top bar + }, + secondary: { + main: '#fdb44b' // + }, + text: { + primary: colors.blueGrey[900], + secondary: colors.blueGrey[600] + } + } + }, + { + name: THEMES.ONE_DARK, + palette: { + type: 'dark', + action: { + active: 'rgba(255, 255, 255, 0.54)', + hover: 'rgba(255, 255, 255, 0.04)', + selected: 'rgba(255, 255, 255, 0.08)', + disabled: 'rgba(255, 255, 255, 0.26)', + disabledBackground: 'rgba(255, 255, 255, 0.12)', + focus: 'rgba(255, 255, 255, 0.12)' + }, + background: { + default: '#005792', + dark:'#f0f0f0', + paper: colors.common.white + }, + primary: { + main: '#00204a' + }, + secondary: { + main: '#fdb44b' + }, + text: { + primary: '#2d2d2e', + secondary: '#8a8a8a' + } + } + }, + { + name: THEMES.UNICORN, + palette: { + type: 'dark', + action: { + active: 'rgba(255, 255, 255, 0.54)', + hover: 'rgba(255, 255, 255, 0.04)', + selected: 'rgba(255, 255, 255, 0.08)', + disabled: 'rgba(255, 255, 255, 0.26)', + disabledBackground: 'rgba(255, 255, 255, 0.12)', + focus: 'rgba(255, 255, 255, 0.12)' + }, + background: { + default: '#2a2d3d', + dark: '#00204a', + paper: '#005792' + }, + primary: { + main: '#00bbf0' + }, + secondary: { + main: '#fdb44b' + }, + text: { + primary: '#f6f5f8', + secondary: '#9699a4' + } + } + } +]; + +const baseOptions = { + direction:'ltr' +} +export const createTheme = (config = {}) => { + let themeOptions = themesOptions.find((theme) => theme.name === config.theme); + console.log('selected theme is ', themeOptions) + if (!themeOptions) { + console.warn(new Error(`The theme ${config.theme} is not valid`)); + [themeOptions] = themesOptions; + } + console.log('theme before update,' , themeOptions) + let theme = createMuiTheme( + _.merge( + {}, + baseOptions, + themeOptions, + { direction: config.direction } + ) + ); + + console.log('last theme object: ',theme) + return theme; + } + \ No newline at end of file diff --git a/src/utils/axios.js b/src/utils/axios.js new file mode 100644 index 0000000..8ae7635 --- /dev/null +++ b/src/utils/axios.js @@ -0,0 +1,29 @@ +import axios from 'axios'; +import { SESSION_KEY, BASE_URL} from "../common/Constants"; + +const axiosInstance = axios.create(); +axiosInstance.defaults.baseURL=BASE_URL; +axiosInstance.interceptors.response.use( + (response) => response + // ,(error) => Promise.reject((error.response && error.response.data) || 'Something went wrong') +); + +function getSession() { + let session = localStorage.getItem(SESSION_KEY) + if (session) { + return JSON.parse(session) + } + return session +} +function checkSession() { + return localStorage.getItem(SESSION_KEY) !== null +} + +if (checkSession()) { + let sessionData = getSession(); + console.log('local storage: ',sessionData) + let apiToken = sessionData.token.access_token + console.log(apiToken) + axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${apiToken}`; +} +export default axiosInstance; diff --git a/src/utils/classes/BaseHttp.js b/src/utils/classes/BaseHttp.js new file mode 100644 index 0000000..ffda785 --- /dev/null +++ b/src/utils/classes/BaseHttp.js @@ -0,0 +1,30 @@ +import { HttpService } from "./HttpHelper"; + +export class BaseService { + + http + + constructor(url_prefix = "") { + this.http = (new HttpService(url_prefix)) + } + + async getAll() { + return await this.http.get(``) + } + + async get(id) { + return await this.http.get(`/${id}`) + } + + async create(body) { + return await this.http.post(``, body) + } + + async update(id, body) { + return await this.http.put(`/${id}`, body) + } + + async delete(id) { + return await this.http.remove(`/${id}`) + } +} \ No newline at end of file diff --git a/src/utils/classes/HttpHelper.js b/src/utils/classes/HttpHelper.js new file mode 100644 index 0000000..c730d97 --- /dev/null +++ b/src/utils/classes/HttpHelper.js @@ -0,0 +1,92 @@ +import axios from '../axios' + + +export class HttpService { + + headers = { + + } + + constructor(url_prefix = "") { + this.url_prefix = url_prefix + this.getHeaders() + } + + async get(url, queryParams) { + try { + let response = await axios.get(this.getUrl(url) + this.mapQueryParams(queryParams), { + headers: this.headers + }) + + return response + } catch (error) { + console.log(error) + return error + } + } + + async post(url, body, queryParams = null) { + try { + let response = await axios.post(this.getUrl(url) + this.mapQueryParams(queryParams),body ,{ + method: "POST", + headers: this.headers + }) + + return response + } catch (error) { + // console.log('error in response of axios is',error) + // let res = handleResponse(error) + return error; // null or object of msg + } + + } + + async put(url, body, queryParams = null) { + try { + let response = await fetch(this.getUrl(url) + this.mapQueryParams(queryParams), { + method: "PUT", + headers: this.headers, + body: JSON.stringify(body) + }) + + return response + } catch (error) { + console.log(error); + return null + } + } + + async remove(url, queryParams = null) { + try { + let response = await fetch(this.getUrl(url) + this.mapQueryParams(queryParams), { + method: "DELETE", + headers: this.headers + }) + + return response + } catch (error) { + console.log(error) + return null + } + } + + getUrl(url) { + return this.url_prefix + url + } + + getHeaders() { + this.headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Access-Control-Allow-Origin': '*' + } + } + + mapQueryParams(queryParams) { + return queryParams + ? Object.keys(queryParams).map(function (key) { + return key + '=' + queryParams[key] + }).join('&') + : "" + } +} \ No newline at end of file diff --git a/src/utils/responseHandler.js b/src/utils/responseHandler.js new file mode 100644 index 0000000..ed803d7 --- /dev/null +++ b/src/utils/responseHandler.js @@ -0,0 +1,60 @@ +export const handleResponse = (err) => { + let resp = null + if(err.response) + { + resp = {} + + switch(err.response.status) + { + case 401: + resp = { + message:err.response.data.message, + statusCode:err.response.status + } + console.log(resp) + // window.location.href='/login' + break; + case 422: + let msg = ''; + console.log('err object: ',err.response) + let details = err.response.data.detail + if(details) + { + details.map((m)=>{ + msg = msg + ", "+m.msg + }) + } + resp = { + message:msg, + statusCode:err.response.status + } + console.log('object created: ',resp) + // window.location.href='/login' + break; + + case 404: + resp ={ + message:err.response.data.message, + statusCode:err.response.status + } + break; + + } + + } + else if(err.request) + { + console.log(err.status) + console.log("Error in the client side at request") + + } + else{ + resp = { + message:'Unknown error!', + statusCode:-1 + } + } + console.log('respo in handler is: ',resp) + return resp; + +} \ No newline at end of file diff --git a/src/views/BoardView.jsx b/src/views/BoardView.jsx new file mode 100644 index 0000000..2ea6f22 --- /dev/null +++ b/src/views/BoardView.jsx @@ -0,0 +1,76 @@ +import { makeStyles, Typography, Box} from '@material-ui/core'; +import React, { useEffect, useState} from 'react'; +import { DashboradService } from '../services/Http/DashoardService'; +import Pagination from '@mui/material/Pagination'; +import BoardItems from '../components/BoardItems'; +import Container from '@mui/material/Container'; +import Grid from '@mui/material/Grid'; +import TaskItems from '../components/TaskItems' +import CircularProgress from '@mui/material/CircularProgress'; + +const useStyles = makeStyles((theme)=>({ + bg:{ + backgroundColor: 'white', + borderRadius: 20, + boxSizing: 'border-box', + padding: 20, + border: '1px #1a8cf7 solid', + boxShadow: '5px 5px 0 #1a8cf7', + }, + + +})) +function BoardView(props) { + const classes = useStyles() + let perPage = 10 + const [data, setData] = useState([]) + const [page, setPage] = useState(1) + const [pages, setPages] = useState(1) + const [dataPaginate, setDataPaginate] = useState([]) + const [tasks, setTasks] = useState([]) + + const handleClick = (event, value)=> { + let fromRecord = perPage * (value - 1) + let toRecord = ((fromRecord + perPage) <= data.length) ? (fromRecord + perPage) : (data.length % perPage) + fromRecord + setPage(value) + setDataPaginate(data.slice(fromRecord,toRecord)) + } + + + useEffect(()=>{ + + (new DashboradService).loadPoints().then((res)=> { + let dataRes = res.data + let boardData = dataRes.data + let tasksData = dataRes.program.tasks + + setTasks(tasksData) + setData([...boardData]) + setPages(Math.ceil(boardData.length/perPage)) + setDataPaginate(boardData.slice(0,10)) + }).catch((err)=> console.log(err)) + + },[]) + + return ( + + {dataPaginate.length==0? : + + + Computiq Score Board + Full-Stack Development Bootcamp + + + + + + + + + + } + + ); +} + +export default BoardView; \ No newline at end of file diff --git a/src/views/LoginView.jsx b/src/views/LoginView.jsx new file mode 100644 index 0000000..2b32ed5 --- /dev/null +++ b/src/views/LoginView.jsx @@ -0,0 +1,82 @@ +import React, { useState } from 'react'; +// import { makeStyles } from '@mui/styles'; +import { Box,makeStyles } from '@material-ui/core'; +import TextField from '@mui/material/TextField'; +import Button from '@mui/material/Button'; +import useAuth from '../hooks/useAuth'; +import Snackbar from '@mui/material/Snackbar'; +import MuiAlert from '@mui/material/Alert'; + + +const Alert = React.forwardRef(function Alert(props, ref) { + return ; + }); + +const useStyles = makeStyles(()=>({ + root:{ + display:'flex', + flexGrow:1, + justifyContent:'center', + alignItems:'center', + backgroundColor:'#e0e0e0', + height:'100vh' + }, + loginBox:{ + width:'400px', + height:'250px', + backgroundColor:'white', + borderRadius:'5px' + }, + form:{ + width:'75%', + margin:'auto', + paddingTop:'15px', + paddingBottom:'15px', + boxSizing:'border-box', + display:'flex', + flexDirection:'column', + justifyContent:'space-between', + height:'100%' + }, + + field:{ + width:'100%' + } + +})) +function LoginView(props) { + const classes = useStyles() + const {login,error} = useAuth() + console.log(' error is ',error) + const [email,setEmail] = useState('') + const [password,setPassword] = useState('') + const auth = (e)=>{ + e.preventDefault(); + login(email, password); + + + } + return ( + + +
+ + + setEmail(e.target.value)} className={classes.field} type="email" id="email" label="Email" variant="standard" /> + setPassword(e.target.value)} className={classes.field} type="password" id="password" label="Password" variant="standard" /> + + + + +
+
+ { + error && {error} + } +
+ ); +} + +export default LoginView; \ No newline at end of file diff --git a/src/views/NotFoundView.jsx b/src/views/NotFoundView.jsx new file mode 100644 index 0000000..1e19bd9 --- /dev/null +++ b/src/views/NotFoundView.jsx @@ -0,0 +1,11 @@ +import React from 'react'; + +function ViewNotFound(props) { + return ( +
+ 404 Not Found +
+ ); +} + +export default ViewNotFound; \ No newline at end of file