├── src ├── _helpers │ ├── index.js │ └── history.js ├── _services │ ├── index.js │ └── user.service.js ├── home │ ├── index.js │ └── home.component.js ├── login │ ├── index.js │ ├── login.component.css │ └── login.component.js ├── _actions │ ├── index.js │ ├── user.actions.js │ └── vendor.actions.js ├── config │ └── config.js ├── index.css ├── _components │ ├── index.js │ ├── PrivateRoute.jsx │ ├── appbar.js │ └── nav.js ├── App.test.js ├── _reducers │ ├── index.js │ ├── auth.reducer.js │ └── vendor.reducer.js ├── App.css ├── index.js ├── App.js ├── logo.svg ├── registerServiceWorker.js └── vendors │ ├── vendor.component.js │ └── addvendor.component.js ├── public ├── favicon.ico ├── manifest.json └── index.html ├── README.md ├── .gitignore └── package.json /src/_helpers/index.js: -------------------------------------------------------------------------------- 1 | export * from './history'; 2 | -------------------------------------------------------------------------------- /src/_services/index.js: -------------------------------------------------------------------------------- 1 | export * from './user.service'; -------------------------------------------------------------------------------- /src/home/index.js: -------------------------------------------------------------------------------- 1 | export * from './home.component'; -------------------------------------------------------------------------------- /src/login/index.js: -------------------------------------------------------------------------------- 1 | export * from './login.component'; -------------------------------------------------------------------------------- /src/_actions/index.js: -------------------------------------------------------------------------------- 1 | export * from './user.actions'; 2 | export * from './vendor.actions' -------------------------------------------------------------------------------- /src/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | baseUrl: 'http://localhost:8001/api/v1/' 3 | } -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /src/login/login.component.css: -------------------------------------------------------------------------------- 1 | .login-margin{ 2 | margin-top: 300px; 3 | display: 'flex'; 4 | } -------------------------------------------------------------------------------- /src/_components/index.js: -------------------------------------------------------------------------------- 1 | export * from './PrivateRoute'; 2 | export * from './nav'; 3 | export * from './appbar' -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emanuelraj/vendor-crud-react-redux-medium-post/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Run the application 2 | 3 | * `npm install` to install all dependencies. 4 | * `npm start` to run the application. 5 | -------------------------------------------------------------------------------- /src/_helpers/history.js: -------------------------------------------------------------------------------- 1 | import { createBrowserHistory } from 'history'; 2 | 3 | export const history = createBrowserHistory(); 4 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /src/_reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import { authentication } from './auth.reducer'; 4 | import { vendor } from './vendor.reducer'; 5 | 6 | 7 | const rootReducer = combineReducers({ 8 | authentication, 9 | vendor 10 | }); 11 | 12 | export default rootReducer; 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/_components/PrivateRoute.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, Redirect } from 'react-router-dom'; 3 | export const PrivateRoute = ({ component: Component, ...rest }) => ( 4 | ( 5 | localStorage.getItem('auth') 6 | ? 7 | : 8 | )} /> 9 | ) -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /src/_reducers/auth.reducer.js: -------------------------------------------------------------------------------- 1 | 2 | let token = '';//localStorage.getItem('token'); 3 | let auth = '';//localStorage.getItem('auth'); 4 | const initialState = auth ? { loggedIn: true, auth, token } : {}; 5 | 6 | export function authentication(state = initialState, action) { 7 | switch (action.type) { 8 | case 'LOGIN_SUCCESS': 9 | return { 10 | loggingIn: true, 11 | auth: action.auth, 12 | token: action.token 13 | }; 14 | case 'LOGOUT_SUCCESS': 15 | return { 16 | auth: false 17 | }; 18 | default: 19 | return state 20 | } 21 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import { createStore, applyMiddleware } from 'redux'; 6 | import { Provider } from 'react-redux'; 7 | import thunk from 'redux-thunk'; 8 | import reducer from './_reducers'; 9 | 10 | import registerServiceWorker from './registerServiceWorker'; 11 | 12 | const store = createStore(reducer, applyMiddleware(thunk)) 13 | 14 | 15 | ReactDOM.render( 16 | 17 | 18 | 19 | , document.getElementById('root')); 20 | registerServiceWorker(); 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ven-crud", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@material-ui/core": "^1.5.1", 7 | "@material-ui/icons": "^2.0.3", 8 | "axios": "^0.18.0", 9 | "classnames": "^2.2.6", 10 | "history": "^4.7.2", 11 | "prop-types": "^15.6.2", 12 | "react": "^16.4.2", 13 | "react-dom": "^16.4.2", 14 | "react-redux": "^5.0.7", 15 | "react-router-dom": "^4.3.1", 16 | "react-scripts": "1.1.5", 17 | "redux": "^4.0.0", 18 | "redux-thunk": "^2.3.0" 19 | }, 20 | "scripts": { 21 | "start": "react-scripts start", 22 | "build": "react-scripts build", 23 | "test": "react-scripts test --env=jsdom", 24 | "eject": "react-scripts eject" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/_reducers/vendor.reducer.js: -------------------------------------------------------------------------------- 1 | const initialState = { anchor: 'left', 2 | vendor: [], 3 | open: false, 4 | id: '', 5 | name: '', 6 | mobile: '', 7 | phone_number: '', 8 | address: '' 9 | }; 10 | 11 | 12 | export function vendor(state = initialState, action) { 13 | switch (action.type) { 14 | case 'FETECHED_ALL_VENDOR': 15 | return { 16 | ...state, 17 | vendor: action.vendor 18 | }; 19 | case 'VENDOR_DETAIL': 20 | return { 21 | ...state, 22 | id: action.id, 23 | name: action.name, 24 | mobile: action.mobile, 25 | phone_number: action.phone_number, 26 | address: action.address 27 | }; 28 | case "USER_UPDATED": 29 | return state; 30 | case "HANDLE_ON_CHANGE": 31 | return { 32 | ...state, 33 | [action.props]: action.value 34 | }; 35 | default: 36 | return state 37 | } 38 | } -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import './App.css'; 3 | import { Router, Switch, Route} from 'react-router-dom'; 4 | import { Vendor } from './vendors/vendor.component'; 5 | import { AddVendor } from './vendors/addvendor.component' 6 | import { Login } from './login/'; 7 | import { Home } from './home/'; 8 | import { history } from './_helpers'; 9 | import { PrivateRoute } from './_components'; 10 | 11 | 12 | class App extends Component { 13 | render() { 14 | return ( 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ); 29 | } 30 | } 31 | 32 | export default App; 33 | -------------------------------------------------------------------------------- /src/_services/user.service.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import config from '../config/config'; 3 | 4 | 5 | export const userService = { 6 | get, 7 | post, 8 | put, 9 | deleteDetail 10 | }; 11 | 12 | function get(apiEndpoint){ 13 | return axios.get(config.baseUrl+apiEndpoint, getOptions()).then((response)=>{ 14 | return response; 15 | }).catch((err)=>{ 16 | console.log("Error in response"); 17 | console.log(err); 18 | }) 19 | } 20 | 21 | function post(apiEndpoint, payload){ 22 | return axios.post(config.baseUrl+apiEndpoint, payload, getOptions()).then((response)=>{ 23 | return response; 24 | }).catch((err)=>{ 25 | console.log(err); 26 | }) 27 | } 28 | 29 | function put(apiEndpoint, payload){ 30 | return axios.put(config.baseUrl+apiEndpoint, payload, getOptions()).then((response)=>{ 31 | return response; 32 | }).catch((err)=>{ 33 | console.log(err); 34 | }) 35 | } 36 | 37 | function deleteDetail(apiEndpoint){ 38 | return axios.delete(config.baseUrl+apiEndpoint, getOptions()).then((response)=>{ 39 | return response; 40 | }).catch((err)=>{ 41 | console.log(err); 42 | }) 43 | } 44 | 45 | function getOptions(){ 46 | let options = {}; 47 | if(localStorage.getItem('token')){ 48 | options.headers = { 'x-access-token': localStorage.getItem('token') }; 49 | } 50 | return options; 51 | } -------------------------------------------------------------------------------- /src/_actions/user.actions.js: -------------------------------------------------------------------------------- 1 | import { userService } from '../_services/'; 2 | import { history } from '../_helpers'; 3 | 4 | export const userActions = { 5 | login, 6 | logout 7 | }; 8 | 9 | function login(username, password){ 10 | return dispatch => { 11 | let apiEndpoint = 'auths'; 12 | let payload = { 13 | username: username, 14 | password: password 15 | } 16 | userService.post(apiEndpoint, payload) 17 | .then((response)=>{ 18 | console.log(response.data); 19 | if (response.data.token) { 20 | localStorage.setItem('token', response.data.token); 21 | localStorage.setItem('auth', response.data.auth); 22 | dispatch(setUserDetails(response.data)); 23 | history.push('/home'); 24 | } 25 | }) 26 | }; 27 | } 28 | 29 | function logout(){ 30 | return dispatch => { 31 | localStorage.removeItem('auth'); 32 | localStorage.removeItem('token'); 33 | dispatch(logoutUser()); 34 | history.push('/'); 35 | } 36 | } 37 | 38 | export function setUserDetails(user){ 39 | return{ 40 | type: "LOGIN_SUCCESS", 41 | auth: user.auth, 42 | token: user.token 43 | } 44 | } 45 | 46 | export function logoutUser(){ 47 | return{ 48 | type: "LOGOUT_SUCCESS", 49 | auth: false, 50 | token: '' 51 | } 52 | } -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 26 | You need to enable JavaScript to run this app. 27 | 28 | 29 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/_components/appbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import classNames from 'classnames'; 4 | import { withStyles } from '@material-ui/core/styles'; 5 | import AppBar from '@material-ui/core/AppBar'; 6 | import Toolbar from '@material-ui/core/Toolbar'; 7 | import Typography from '@material-ui/core/Typography'; 8 | 9 | const drawerWidth = 240; 10 | 11 | const styles = theme => ({ 12 | root: { 13 | flexGrow: 1, 14 | }, 15 | appFrame: { 16 | zIndex: 1, 17 | overflow: 'hidden', 18 | position: 'relative', 19 | display: 'flex', 20 | width: '100%', 21 | }, 22 | appBar: { 23 | width: `calc(100% - ${drawerWidth}px)`, 24 | }, 25 | 'appBar-left': { 26 | marginLeft: drawerWidth, 27 | }, 28 | 'appBar-right': { 29 | marginRight: drawerWidth, 30 | }, 31 | drawerPaper: { 32 | position: 'relative', 33 | width: drawerWidth, 34 | }, 35 | toolbar: theme.mixins.toolbar, 36 | content: { 37 | flexGrow: 1, 38 | backgroundColor: theme.palette.background.default, 39 | padding: theme.spacing.unit * 3, 40 | }, 41 | }); 42 | 43 | class PermanentDrawer extends React.Component { 44 | state = { 45 | anchor: 'left', 46 | }; 47 | 48 | handleChange = event => { 49 | this.setState({ 50 | anchor: event.target.value, 51 | }); 52 | }; 53 | 54 | render() { 55 | const { classes } = this.props; 56 | const { anchor } = this.state; 57 | 58 | return ( 59 | 63 | 64 | 65 | CRUD 66 | 67 | 68 | 69 | ); 70 | } 71 | } 72 | 73 | PermanentDrawer.propTypes = { 74 | classes: PropTypes.object.isRequired, 75 | }; 76 | 77 | export default withStyles(styles)(PermanentDrawer); -------------------------------------------------------------------------------- /src/home/home.component.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from '@material-ui/core/styles'; 4 | import { connect } from 'react-redux'; 5 | import { withRouter } from 'react-router-dom'; 6 | import Typography from '@material-ui/core/Typography'; 7 | import AppBar from '../_components/appbar'; 8 | import Nav from '../_components/nav'; 9 | 10 | 11 | const drawerWidth = 240; 12 | 13 | const styles = theme => ({ 14 | root: { 15 | flexGrow: 1, 16 | }, 17 | appFrame: { 18 | zIndex: 1, 19 | overflow: 'hidden', 20 | position: 'relative', 21 | display: 'flex', 22 | width: '100%', 23 | }, 24 | appBar: { 25 | width: `calc(100% - ${drawerWidth}px)`, 26 | }, 27 | 'appBar-left': { 28 | marginLeft: drawerWidth, 29 | }, 30 | 'appBar-right': { 31 | marginRight: drawerWidth, 32 | }, 33 | drawerPaper: { 34 | position: 'relative', 35 | width: drawerWidth, 36 | }, 37 | toolbar: theme.mixins.toolbar, 38 | content: { 39 | flexGrow: 1, 40 | backgroundColor: theme.palette.background.default, 41 | padding: theme.spacing.unit * 3, 42 | }, 43 | }); 44 | 45 | 46 | class Home extends Component { 47 | 48 | render() { 49 | const { classes } = this.props; 50 | 51 | return ( 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | {'Home'} 60 | 61 | 62 | 63 | ); 64 | } 65 | } 66 | 67 | Home.propTypes = { 68 | classes: PropTypes.object.isRequired, 69 | }; 70 | 71 | 72 | function mapStateToProps(state) { 73 | return state; 74 | } 75 | 76 | 77 | const connectedHomePage = withRouter(connect(mapStateToProps, null, null, { 78 | pure: false 79 | })(withStyles(styles)(Home))); 80 | 81 | export { connectedHomePage as Home }; 82 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/_actions/vendor.actions.js: -------------------------------------------------------------------------------- 1 | import { userService } from '../_services/'; 2 | import { history } from '../_helpers'; 3 | 4 | export const vendorAction = { 5 | getVendor, 6 | getVendorById, 7 | onChangeProps, 8 | editVendorInfo, 9 | createVendor, 10 | deleteVendorById 11 | }; 12 | 13 | function getVendor(){ 14 | return dispatch => { 15 | let apiEndpoint = 'vendors'; 16 | userService.get(apiEndpoint) 17 | .then((response)=>{ 18 | console.log(response); 19 | dispatch(changeVendorsList(response.data.data)); 20 | }).catch((err)=>{ 21 | console.log("Error"); 22 | console.log(err); 23 | }) 24 | }; 25 | } 26 | 27 | function createVendor(payload){ 28 | return dispatch => { 29 | let apiEndpoint = 'vendors/'; 30 | userService.post(apiEndpoint, payload) 31 | .then((response)=>{ 32 | dispatch(createUserInfo()); 33 | history.push('/vendor'); 34 | }) 35 | } 36 | } 37 | 38 | function getVendorById(id){ 39 | 40 | return dispatch => { 41 | let apiEndpoint = 'vendors/'+ id; 42 | userService.get(apiEndpoint) 43 | .then((response)=>{ 44 | dispatch(editVendorsDetails(response.data.data)); 45 | }) 46 | }; 47 | } 48 | 49 | function onChangeProps(props, event){ 50 | return dispatch =>{ 51 | dispatch(handleOnChangeProps(props, event.target.value)); 52 | } 53 | } 54 | 55 | function editVendorInfo(id, payload){ 56 | return dispatch => { 57 | let apiEndpoint = 'vendors/'+ id; 58 | userService.put(apiEndpoint, payload) 59 | .then((response)=>{ 60 | dispatch(updatedUserInfo()); 61 | history.push('/vendor'); 62 | }) 63 | } 64 | } 65 | 66 | function deleteVendorById(id){ 67 | return dispatch => { 68 | let apiEndpoint = 'vendors/'+ id; 69 | userService.deleteDetail(apiEndpoint) 70 | .then((response)=>{ 71 | dispatch(deleteVendorsDetails()); 72 | dispatch(vendorAction.getVendor()); 73 | }) 74 | }; 75 | } 76 | 77 | export function changeVendorsList(vendor){ 78 | return{ 79 | type: "FETECHED_ALL_VENDOR", 80 | vendor: vendor 81 | } 82 | } 83 | 84 | export function handleOnChangeProps(props, value){ 85 | return{ 86 | type: "HANDLE_ON_CHANGE", 87 | props: props, 88 | value: value 89 | } 90 | } 91 | 92 | export function editVendorsDetails(vendor){ 93 | return{ 94 | type: "VENDOR_DETAIL", 95 | id: vendor._id, 96 | name: vendor.name, 97 | mobile: vendor.mobile, 98 | phone_number: vendor.phone_number, 99 | address: vendor.address 100 | } 101 | } 102 | 103 | export function updatedUserInfo(){ 104 | return{ 105 | type: "USER_UPDATED" 106 | } 107 | } 108 | 109 | export function createUserInfo(){ 110 | return{ 111 | type: "USER_CREATED_SUCCESSFULLY" 112 | } 113 | } 114 | 115 | export function deleteVendorsDetails(){ 116 | return{ 117 | type: "DELETED_VENDOR_DETAILS" 118 | } 119 | } -------------------------------------------------------------------------------- /src/_components/nav.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from '@material-ui/core/styles'; 4 | import Drawer from '@material-ui/core/Drawer'; 5 | import List from '@material-ui/core/List'; 6 | import Divider from '@material-ui/core/Divider'; 7 | import ListItem from '@material-ui/core/ListItem'; 8 | import ListItemIcon from '@material-ui/core/ListItemIcon'; 9 | import ListItemText from '@material-ui/core/ListItemText'; 10 | import { userActions } from '../_actions'; 11 | import { connect } from 'react-redux'; 12 | import HomeIcon from '@material-ui/icons/Home'; 13 | import LogoutIcon from '@material-ui/icons/HighlightOff'; 14 | import VendorIcon from '@material-ui/icons/CardTravel'; 15 | 16 | 17 | const drawerWidth = 240; 18 | 19 | const styles = theme => ({ 20 | root: { 21 | flexGrow: 1, 22 | }, 23 | appFrame: { 24 | zIndex: 1, 25 | overflow: 'hidden', 26 | position: 'relative', 27 | display: 'flex', 28 | width: '100%', 29 | }, 30 | appBar: { 31 | width: `calc(100% - ${drawerWidth}px)`, 32 | }, 33 | 'appBar-left': { 34 | marginLeft: drawerWidth, 35 | }, 36 | 'appBar-right': { 37 | marginRight: drawerWidth, 38 | }, 39 | drawerPaper: { 40 | position: 'relative', 41 | width: drawerWidth, 42 | }, 43 | toolbar: theme.mixins.toolbar, 44 | content: { 45 | flexGrow: 1, 46 | backgroundColor: theme.palette.background.default, 47 | padding: theme.spacing.unit * 3, 48 | }, 49 | }); 50 | 51 | 52 | class Navigation extends React.Component { 53 | 54 | constructor(props){ 55 | super(props); 56 | this.state={ 57 | anchor: 'left', 58 | } 59 | } 60 | 61 | logout = event =>{ 62 | const { dispatch } = this.props; 63 | console.log(this.props); 64 | console.log(localStorage.getItem('auth')); 65 | dispatch(userActions.logout()); 66 | } 67 | 68 | render() { 69 | const { classes } = this.props; 70 | const { anchor } = this.state; 71 | 72 | return( 73 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | {this.logout()}}> 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | ); 105 | } 106 | } 107 | 108 | Navigation.propTypes = { 109 | classes: PropTypes.object.isRequired, 110 | }; 111 | 112 | const mapStateToProps = (state) =>{ 113 | const { loggingIn } = state.authentication; 114 | return { 115 | loggingIn 116 | }; 117 | } 118 | 119 | export default connect(mapStateToProps)(withStyles(styles)(Navigation)); -------------------------------------------------------------------------------- /src/login/login.component.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from '@material-ui/core/styles'; 4 | import Paper from '@material-ui/core/Paper'; 5 | import Grid from '@material-ui/core/Grid'; 6 | import Button from '@material-ui/core/Button'; 7 | import TextField from '@material-ui/core/TextField'; 8 | import { connect } from 'react-redux'; 9 | import { userActions } from '../_actions'; 10 | import { history } from '../_helpers'; 11 | import Typography from '@material-ui/core/Typography'; 12 | import { withRouter } from 'react-router-dom'; 13 | import './login.component.css' 14 | 15 | 16 | const styles = theme => ({ 17 | root: { 18 | display: 'flex', 19 | flexWrap: 'wrap', 20 | }, 21 | container: { 22 | display: 'flex', 23 | flexWrap: 'wrap', 24 | }, 25 | margin: { 26 | margin: theme.spacing.unit, 27 | }, 28 | withoutLabel: { 29 | marginTop: theme.spacing.unit * 3, 30 | }, 31 | textField: { 32 | marginLeft: theme.spacing.unit, 33 | marginRight: theme.spacing.unit, 34 | width: 200, 35 | }, 36 | 37 | paper: { 38 | padding: theme.spacing.unit * 2, 39 | textAlign: 'center', 40 | color: theme.palette.text.secondary, 41 | }, 42 | 43 | button: { 44 | margin: theme.spacing.unit, 45 | }, 46 | 47 | input: { 48 | display: 'none', 49 | }, 50 | }); 51 | 52 | 53 | class Login extends Component { 54 | 55 | constructor(props){ 56 | super(props); 57 | this.state = { 58 | username: '', 59 | password: '', 60 | showPassword: false, 61 | } 62 | } 63 | 64 | componentDidMount() { 65 | console.log(this.props); 66 | if(localStorage.getItem('auth')){ 67 | history.push('/home'); 68 | } 69 | } 70 | 71 | handleChange = prop => event => { 72 | this.setState({ [prop]: event.target.value }); 73 | }; 74 | 75 | login = event =>{ 76 | this.setState({ submitted: true }); 77 | const { username, password } = this.state; 78 | const { dispatch } = this.props; 79 | if (username && password) { 80 | dispatch(userActions.login(username, password)); 81 | } 82 | } 83 | 84 | render() { 85 | const { classes } = this.props; 86 | return ( 87 | 88 | 89 | 90 | 91 | 92 | 93 | {'Login'} 94 | 95 | 96 | 97 | 103 | 104 | 105 | 113 | 114 | 115 | {this.login()}}> 116 | Login 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | ); 126 | } 127 | } 128 | 129 | Login.propTypes = { 130 | classes: PropTypes.object.isRequired, 131 | }; 132 | 133 | const mapStateToProps = (state) =>{ 134 | const { loggingIn } = state.authentication; 135 | return { 136 | loggingIn 137 | }; 138 | } 139 | 140 | const connectedLoginPage = withRouter(connect(mapStateToProps, null, null, { 141 | pure: false 142 | })(withStyles(styles)(Login))); 143 | 144 | export { connectedLoginPage as Login }; -------------------------------------------------------------------------------- /src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | // In production, we register a service worker to serve assets from local cache. 2 | 3 | // This lets the app load faster on subsequent visits in production, and gives 4 | // it offline capabilities. However, it also means that developers (and users) 5 | // will only see deployed updates on the "N+1" visit to a page, since previously 6 | // cached resources are updated in the background. 7 | 8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. 9 | // This link also includes instructions on opting out of this behavior. 10 | 11 | const isLocalhost = Boolean( 12 | window.location.hostname === 'localhost' || 13 | // [::1] is the IPv6 localhost address. 14 | window.location.hostname === '[::1]' || 15 | // 127.0.0.1/8 is considered localhost for IPv4. 16 | window.location.hostname.match( 17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 18 | ) 19 | ); 20 | 21 | export default function register() { 22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 23 | // The URL constructor is available in all browsers that support SW. 24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location); 25 | if (publicUrl.origin !== window.location.origin) { 26 | // Our service worker won't work if PUBLIC_URL is on a different origin 27 | // from what our page is served on. This might happen if a CDN is used to 28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 29 | return; 30 | } 31 | 32 | window.addEventListener('load', () => { 33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 34 | 35 | if (isLocalhost) { 36 | // This is running on localhost. Lets check if a service worker still exists or not. 37 | checkValidServiceWorker(swUrl); 38 | 39 | // Add some additional logging to localhost, pointing developers to the 40 | // service worker/PWA documentation. 41 | navigator.serviceWorker.ready.then(() => { 42 | console.log( 43 | 'This web app is being served cache-first by a service ' + 44 | 'worker. To learn more, visit https://goo.gl/SC7cgQ' 45 | ); 46 | }); 47 | } else { 48 | // Is not local host. Just register service worker 49 | registerValidSW(swUrl); 50 | } 51 | }); 52 | } 53 | } 54 | 55 | function registerValidSW(swUrl) { 56 | navigator.serviceWorker 57 | .register(swUrl) 58 | .then(registration => { 59 | registration.onupdatefound = () => { 60 | const installingWorker = registration.installing; 61 | installingWorker.onstatechange = () => { 62 | if (installingWorker.state === 'installed') { 63 | if (navigator.serviceWorker.controller) { 64 | // At this point, the old content will have been purged and 65 | // the fresh content will have been added to the cache. 66 | // It's the perfect time to display a "New content is 67 | // available; please refresh." message in your web app. 68 | console.log('New content is available; please refresh.'); 69 | } else { 70 | // At this point, everything has been precached. 71 | // It's the perfect time to display a 72 | // "Content is cached for offline use." message. 73 | console.log('Content is cached for offline use.'); 74 | } 75 | } 76 | }; 77 | }; 78 | }) 79 | .catch(error => { 80 | console.error('Error during service worker registration:', error); 81 | }); 82 | } 83 | 84 | function checkValidServiceWorker(swUrl) { 85 | // Check if the service worker can be found. If it can't reload the page. 86 | fetch(swUrl) 87 | .then(response => { 88 | // Ensure service worker exists, and that we really are getting a JS file. 89 | if ( 90 | response.status === 404 || 91 | response.headers.get('content-type').indexOf('javascript') === -1 92 | ) { 93 | // No service worker found. Probably a different app. Reload the page. 94 | navigator.serviceWorker.ready.then(registration => { 95 | registration.unregister().then(() => { 96 | window.location.reload(); 97 | }); 98 | }); 99 | } else { 100 | // Service worker found. Proceed as normal. 101 | registerValidSW(swUrl); 102 | } 103 | }) 104 | .catch(() => { 105 | console.log( 106 | 'No internet connection found. App is running in offline mode.' 107 | ); 108 | }); 109 | } 110 | 111 | export function unregister() { 112 | if ('serviceWorker' in navigator) { 113 | navigator.serviceWorker.ready.then(registration => { 114 | registration.unregister(); 115 | }); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/vendors/vendor.component.js: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux'; 2 | import { vendorAction } from '../_actions'; 3 | import React, { Component } from 'react'; 4 | import AppBar from '../_components/appbar'; 5 | import PropTypes from 'prop-types'; 6 | import { withStyles } from '@material-ui/core/styles'; 7 | import Typography from '@material-ui/core/Typography'; 8 | import Nav from '../_components/nav'; 9 | import Table from '@material-ui/core/Table'; 10 | import TableBody from '@material-ui/core/TableBody'; 11 | import TableCell from '@material-ui/core/TableCell'; 12 | import TableHead from '@material-ui/core/TableHead'; 13 | import TableRow from '@material-ui/core/TableRow'; 14 | import Paper from '@material-ui/core/Paper'; 15 | import Grid from '@material-ui/core/Grid'; 16 | import Button from '@material-ui/core/Button'; 17 | import DeleteIcon from '@material-ui/icons/Delete'; 18 | import EditIcon from '@material-ui/icons/Edit'; 19 | import IconButton from '@material-ui/core/IconButton'; 20 | import { withRouter } from 'react-router-dom'; 21 | 22 | const drawerWidth = 240; 23 | 24 | 25 | const styles = theme => ({ 26 | root: { 27 | flexGrow: 1, 28 | }, 29 | appFrame: { 30 | zIndex: 1, 31 | overflow: 'hidden', 32 | position: 'relative', 33 | display: 'flex', 34 | width: '100%', 35 | }, 36 | appBar: { 37 | width: `calc(100% - ${drawerWidth}px)`, 38 | }, 39 | 'appBar-left': { 40 | marginLeft: drawerWidth, 41 | }, 42 | 'appBar-right': { 43 | marginRight: drawerWidth, 44 | }, 45 | drawerPaper: { 46 | position: 'relative', 47 | width: drawerWidth, 48 | }, 49 | toolbar: theme.mixins.toolbar, 50 | content: { 51 | flexGrow: 1, 52 | backgroundColor: theme.palette.background.default, 53 | padding: theme.spacing.unit * 3, 54 | }, 55 | 56 | paper: { 57 | position: 'absolute', 58 | width: theme.spacing.unit * 50, 59 | backgroundColor: theme.palette.background.paper, 60 | boxShadow: theme.shadows[5], 61 | padding: theme.spacing.unit * 4, 62 | }, 63 | }); 64 | 65 | 66 | class Vendor extends Component { 67 | 68 | componentDidMount() { 69 | const { dispatch } = this.props; 70 | dispatch(vendorAction.getVendor()); 71 | } 72 | 73 | handleChange = event => { 74 | this.setState({ 75 | anchor: event.target.value, 76 | }); 77 | }; 78 | 79 | 80 | handleClick = (event, id) => { 81 | console.log(id); 82 | const { dispatch } = this.props; 83 | dispatch(vendorAction.deleteVendorById(id)) 84 | }; 85 | 86 | render() { 87 | const { classes } = this.props; 88 | const { vendor } = this.props.vendor; 89 | 90 | return ( 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | {'Vendor'} 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | Add Vendor 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | Name 126 | Mobile 127 | Phone 128 | Address 129 | Action 130 | 131 | 132 | 133 | {vendor.map(n => { 134 | return ( 135 | 136 | 137 | {n.name} 138 | 139 | {n.mobile} 140 | {n.phone_number} 141 | {n.address} 142 | 143 | 144 | 145 | 146 | this.handleClick(event, n._id)}> 147 | 148 | 149 | 150 | 151 | ); 152 | })} 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | ); 161 | } 162 | } 163 | 164 | 165 | Vendor.propTypes = { 166 | classes: PropTypes.object.isRequired, 167 | }; 168 | 169 | const mapStateToProps = (state) =>{ 170 | return { 171 | vendor : state.vendor 172 | }; 173 | } 174 | 175 | const connectedVendorPage = withRouter(connect(mapStateToProps, null, null, { 176 | pure: false 177 | })(withStyles(styles)(Vendor))); 178 | 179 | export { connectedVendorPage as Vendor }; -------------------------------------------------------------------------------- /src/vendors/addvendor.component.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import AppBar from '../_components/appbar'; 3 | import PropTypes from 'prop-types'; 4 | import { withStyles } from '@material-ui/core/styles'; 5 | import Typography from '@material-ui/core/Typography'; 6 | import Nav from '../_components/nav'; 7 | import Paper from '@material-ui/core/Paper'; 8 | import Grid from '@material-ui/core/Grid'; 9 | import Button from '@material-ui/core/Button'; 10 | import TextField from '@material-ui/core/TextField'; 11 | import { connect } from 'react-redux'; 12 | import { vendorAction } from '../_actions'; 13 | import { withRouter } from 'react-router-dom'; 14 | 15 | 16 | const drawerWidth = 240; 17 | 18 | const styles = theme => ({ 19 | 20 | root: { 21 | flexGrow: 1, 22 | }, 23 | 24 | contentRoot: { 25 | ...theme.mixins.gutters(), 26 | paddingTop: theme.spacing.unit * 2, 27 | paddingBottom: theme.spacing.unit * 2, 28 | }, 29 | 30 | appFrame: { 31 | zIndex: 1, 32 | overflow: 'hidden', 33 | position: 'relative', 34 | display: 'flex', 35 | width: '100%', 36 | }, 37 | appBar: { 38 | width: `calc(100% - ${drawerWidth}px)`, 39 | }, 40 | 'appBar-left': { 41 | marginLeft: drawerWidth, 42 | }, 43 | 'appBar-right': { 44 | marginRight: drawerWidth, 45 | }, 46 | drawerPaper: { 47 | position: 'relative', 48 | width: drawerWidth, 49 | }, 50 | toolbar: theme.mixins.toolbar, 51 | content: { 52 | flexGrow: 1, 53 | backgroundColor: theme.palette.background.default, 54 | padding: theme.spacing.unit * 3, 55 | }, 56 | }); 57 | 58 | class AddVendor extends Component { 59 | 60 | handleChange = prop => event => { 61 | const { dispatch } = this.props; 62 | dispatch(vendorAction.onChangeProps(prop, event)); 63 | }; 64 | 65 | componentDidMount() { 66 | const { match : {params } } = this.props; 67 | 68 | if(params.id){ 69 | const { dispatch } = this.props; 70 | dispatch(vendorAction.getVendorById(params.id)); 71 | } 72 | } 73 | 74 | 75 | handleClick(event){ 76 | const { match : {params } } = this.props; 77 | const { dispatch } = this.props; 78 | 79 | let payload={ 80 | name: this.props.vendor.name, 81 | mobile: this.props.vendor.mobile, 82 | phone_number: this.props.vendor.phone_number, 83 | address: this.props.vendor.address, 84 | } 85 | 86 | if(params.id){ 87 | dispatch(vendorAction.editVendorInfo(params.id, payload)); 88 | }else{ 89 | dispatch(vendorAction.createVendor(payload)); 90 | } 91 | } 92 | 93 | 94 | render() { 95 | const { classes } = this.props; 96 | const { match : {params } } = this.props; 97 | console.log(this.props.vendor); 98 | 99 | 100 | function InsertText(props) { 101 | return {'Add New Vendor'}; 102 | } 103 | 104 | function EditText(props) { 105 | return {'Edit Vendor'}; 106 | } 107 | 108 | 109 | function SegHeader() { 110 | if(params.id){ 111 | return ; 112 | } 113 | return ; 114 | } 115 | 116 | return ( 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 150 | 151 | 152 | 160 | 161 | 162 | 170 | 171 | 172 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | Cancel 195 | 196 | 197 | 198 | this.handleClick(event)}> 199 | Save 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | ); 215 | } 216 | } 217 | 218 | //export default Home; 219 | 220 | AddVendor.propTypes = { 221 | classes: PropTypes.object.isRequired, 222 | }; 223 | 224 | 225 | //export default BoxCon 226 | const mapStateToProps = (state) =>{ 227 | return state; 228 | } 229 | 230 | 231 | const connectedAddVendorPage = withRouter(connect(mapStateToProps, null, null, { 232 | pure: false 233 | })(withStyles(styles)(AddVendor))); 234 | 235 | export { connectedAddVendorPage as AddVendor }; --------------------------------------------------------------------------------