├── README.md ├── client ├── components │ ├── NoPage.jsx │ ├── ProfilePic.jsx │ ├── ProfileUpdate.jsx │ ├── AddItem.jsx │ ├── LoginSignup.jsx │ ├── Navbar.jsx │ ├── NavBarLoggedOut.jsx │ ├── NavBarLoggedIn.jsx │ ├── Login.jsx │ ├── Inventory.jsx │ ├── SignUp.jsx │ └── InventoryDisplay.jsx ├── containers │ ├── AccountPageContainer.jsx │ ├── InventoryPageContainer.jsx │ └── LoginSignupContainer.jsx ├── index.html ├── index.js └── stylesheets │ ├── Inventory.scss │ ├── NavBar.scss │ └── Login.scss ├── dist └── index.html ├── server ├── models │ └── eventoryModel.js ├── routes │ ├── items.js │ └── accounts.js ├── server.js └── controllers │ ├── itemsController.js │ └── accountsController.js ├── package.json └── webpack.config.js /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to our e-Ventory -------------------------------------------------------------------------------- /client/components/NoPage.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const NoPage = () => { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | }; 10 | 11 | export default NoPage; -------------------------------------------------------------------------------- /client/components/ProfilePic.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const ProfilePic = () => { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | }; 10 | 11 | export default ProfilePic; -------------------------------------------------------------------------------- /client/components/ProfileUpdate.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const ProfileUpdate = () => { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | }; 10 | 11 | export default ProfileUpdate; -------------------------------------------------------------------------------- /client/containers/AccountPageContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ProfileUpdate from '../components/ProfileUpdate.jsx'; 3 | import ProfilePic from '../components/ProfilePic.jsx'; 4 | 5 | const AccountPageContainer = (props) => { 6 | return ( 7 |
8 |

hey yall

9 |
10 | ); 11 | }; 12 | 13 | export default AccountPageContainer; -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React App 7 | 8 | 9 | 10 |
11 | 12 | -------------------------------------------------------------------------------- /client/components/AddItem.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const AddItem = () => { 4 | // return ( 5 | //
6 | //
7 | // 8 | //
9 | //
10 | // 11 | //
12 | //
13 | // ); 14 | }; 15 | 16 | // export default AddItem; -------------------------------------------------------------------------------- /client/containers/InventoryPageContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // import AddItem from '../components/AddItem.jsx'; 3 | import InventoryDisplay from '../components/InventoryDisplay.jsx'; 4 | 5 | 6 | const InventoryPageContainer = (props) => { 7 | return ( 8 |
9 |

Inventory

10 | {/* */} 11 | 12 |
13 | ); 14 | }; 15 | 16 | export default InventoryPageContainer; -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React App 7 | 8 | 9 | 12 | 13 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /server/models/eventoryModel.js: -------------------------------------------------------------------------------- 1 | const connectionString = 'postgres://rngolnjc:n65esgAAoHqJ7jMSeJAYlw_w77qcdeUf@kashin.db.elephantsql.com/rngolnjc'; 2 | 3 | const { Client } = require('pg') 4 | const client = new Client(connectionString) 5 | 6 | client.connect( (err) => { 7 | if(err) { 8 | return console.error('could not connect to postgres', err); 9 | } 10 | }); 11 | 12 | module.exports = { 13 | query: (text, params, callback) => { 14 | console.log('exected, query', text); 15 | return client.query(text, params, callback); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /server/routes/items.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | router = express.Router(); 3 | const itemsController = require('../controllers/itemsController'); 4 | 5 | router.get('/:id',itemsController.getAllItems, (req,res) => { 6 | 7 | // request body sends the item information 8 | // console.log('RECIEVED!', res.locals.items) 9 | res.status(200).json({items: res.locals.items}); 10 | 11 | }) 12 | 13 | router.patch('/',itemsController.updateItem, (req,res) => { 14 | 15 | // request body sends the item to indicate which item to update 16 | 17 | // res.status(200); 18 | res.status(200).json({item: res.locals.updatedItem}); 19 | 20 | }) 21 | 22 | router.post('/',itemsController.createItem, (req,res) => { 23 | 24 | // request body sends the item information, then inserted into db table 25 | 26 | res.status(200).json({item: res.locals.createdItem}); 27 | 28 | }) 29 | 30 | router.delete('/:itemId', itemsController.deleteItem, (req, res) => { 31 | 32 | res.status(200).json({message: 'item deleted'}); 33 | 34 | }) 35 | 36 | 37 | module.exports = router; -------------------------------------------------------------------------------- /client/components/LoginSignup.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../stylesheets/Login.scss'; 3 | import Login from "./Login.jsx"; 4 | import SignUp from "./SignUp.jsx"; 5 | import { useState } from 'react'; 6 | 7 | 8 | //add onclick to a anchor tag () 9 | 10 | const LoginSignup = (props) => { 11 | 12 | const [isShow, setIsShow] = React.useState(true); 13 | const handleClick = () => {setIsShow(s => !s)}; 14 | 15 | if (isShow){ 16 | return ( 17 |
18 | 19 |
20 | 21 |
22 | Not a member? Sign-Up here! 23 |
24 | ) 25 | } else { 26 | return ( 27 |
28 | 29 |
30 | 31 |
32 | Already a member? Log-In here! 33 |
34 | ) 35 | }; 36 | }; 37 | 38 | export default LoginSignup; 39 | -------------------------------------------------------------------------------- /client/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; 4 | import Navbar from "./components/Navbar.jsx" 5 | import LoginSignupContainer from './containers/LoginSignupContainer.jsx'; 6 | import AccountPageContainer from './containers/AccountPageContainer.jsx'; 7 | import InventoryPageContainer from './containers/InventoryPageContainer.jsx'; 8 | import NoPage from './components/NoPage.jsx'; 9 | 10 | export default function App() { 11 | //use state hook 12 | const [user, setUser] = useState({}); 13 | console.log('user', user); 14 | 15 | 16 | return ( 17 | 18 | 19 | 20 | } /> 21 | } /> 22 | } /> 23 | } /> 24 | 25 | 26 | ) 27 | } 28 | ReactDOM.render( 29 | , 30 | document.getElementById('root') 31 | ); -------------------------------------------------------------------------------- /client/components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Outlet, Link } from "react-router-dom"; 3 | 4 | import NavBarLoggedIn from '../components/NavBarLoggedIn.jsx' 5 | import NavBarLoggedOut from '../components/NavBarLoggedOut.jsx' 6 | import { useState } from 'react'; 7 | 8 | import '../stylesheets/NavBar.scss'; 9 | 10 | /* 11 | Navigation Bar Displayed at the top of every page 12 | 13 | Will contain on not logged in page: 14 | Logo, 15 | Links: 16 | About Company, 17 | 18 | will contain on logged in age: 19 | Logo, 20 | Links: 21 | Account 22 | Inventory 23 | Profile Icon 24 | */ 25 | 26 | const Navbar = (props) => { 27 | 28 | const [isShow, setIsShow] = React.useState(true); 29 | const handleClick = () => {setIsShow(s => !s)}; 30 | 31 | 32 | //for future engineers - if you type in a fake account you will get an error and this needs to be fixed. xoxo gossip girl 33 | if (props.user.name === undefined){ 34 | return ( 35 |
36 | 37 |
38 | ) 39 | } else { 40 | return ( 41 |
42 | 43 |
44 | ) 45 | }; 46 | }; 47 | 48 | 49 | export default Navbar; -------------------------------------------------------------------------------- /client/components/NavBarLoggedOut.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Outlet, Link } from "react-router-dom"; 3 | import '../stylesheets/NavBar.scss'; 4 | 5 | import AccountPageContainer from '../containers/AccountPageContainer.jsx'; 6 | import InventoryPageContainer from '../containers/InventoryPageContainer.jsx'; 7 | import LoginSignupContainer from '../containers/LoginSignupContainer.jsx'; 8 | 9 | 10 | /* 11 | Navigation Bar Displayed at the top of every page 12 | 13 | Will contain on not logged in page: 14 | Logo, 15 | Links: 16 | About Company, 17 | 18 | will contain on logged in age: 19 | Logo, 20 | Links: 21 | Account 22 | Inventory 23 | Profile Icon 24 | */ 25 | 26 | const NavbarLoggedOut = () => { 27 | return ( 28 |
29 | 30 |

eVentory

31 | {/*

Inventory Made Easy

*/} 32 | About Us 33 | Packages 34 |
35 | ); 36 | }; 37 | 38 | export default NavbarLoggedOut; -------------------------------------------------------------------------------- /client/containers/LoginSignupContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | //import Login from '../components/Login.jsx'; 3 | //import SignUp from '../components/SignUp.jsx'; 4 | import LoginSignup from "../components/LoginSignup.jsx" 5 | import '../stylesheets/Login.scss'; 6 | 7 | //Page that returns the login and signup components 8 | 9 | const LoginSignupContainer = (props) => { 10 | return ( 11 |
12 | 13 | 14 |
15 |

Welcome

16 |
17 | 18 |
19 | 20 |
21 |
22 | Terms & Conditions / FAQ 23 |
24 | 25 |
26 | ); 27 | }; 28 | 29 | export default LoginSignupContainer; -------------------------------------------------------------------------------- /client/components/NavBarLoggedIn.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Outlet, Link } from "react-router-dom"; 3 | import '../stylesheets/NavBar.scss'; 4 | 5 | 6 | import AccountPageContainer from '../containers/AccountPageContainer.jsx'; 7 | import InventoryPageContainer from '../containers/InventoryPageContainer.jsx'; 8 | import LoginSignupContainer from '../containers/LoginSignupContainer.jsx'; 9 | 10 | 11 | /* 12 | Navigation Bar Displayed at the top of every page 13 | 14 | Will contain on not logged in page: 15 | Logo, 16 | Links: 17 | About Company, 18 | 19 | will contain on logged in age: 20 | Logo, 21 | Links: 22 | Account 23 | Inventory 24 | Profile Icon 25 | */ 26 | 27 | const NavBarLoggedIn = () => { 28 | return ( 29 |
30 | 31 |

eVentory

32 | {/* About Us 33 | Packages */} 34 | Account 35 | Inventory 36 |
37 | ) 38 | }; 39 | 40 | export default NavBarLoggedIn -------------------------------------------------------------------------------- /client/stylesheets/Inventory.scss: -------------------------------------------------------------------------------- 1 | .inventory-container{ 2 | display: grid; 3 | padding: 20px; 4 | align-items: center; 5 | grid-template-columns: [first] 60px repeat(4, 150px) repeat(2, 80px); 6 | } 7 | 8 | .inventory-labels { 9 | display: grid; 10 | padding: 20px; 11 | align-items: center; 12 | grid-template-columns: [first] 60px repeat(4, 150px) repeat(2, 100px); 13 | } 14 | .scroll { 15 | background-color: #c7e4eb; 16 | width: 900px; 17 | height: 500px; 18 | overflow-x: hidden; 19 | overflow-y: auto; 20 | text-align: center; 21 | border-radius: 10px; 22 | 23 | } 24 | 25 | 26 | ::-webkit-scrollbar { 27 | width: 20px; 28 | } 29 | 30 | 31 | ::-webkit-scrollbar-track { 32 | box-shadow: inset 0 0 5px grey; 33 | border-radius: 10px; 34 | } 35 | 36 | ::-webkit-scrollbar-thumb { 37 | background: #c7d6eb; 38 | border-radius: 10px; 39 | border-color: black 40 | } 41 | 42 | .id-column { 43 | width: 60px; 44 | text-align: center; 45 | } 46 | 47 | .quantity-column { 48 | width: 100px; 49 | text-align: center; 50 | } 51 | .other-column { 52 | width: 150px; 53 | text-align: center; 54 | border-bottom: 2px; 55 | } 56 | 57 | .update-delete-buttons { 58 | height: 20px; 59 | margin: 10px; 60 | border-radius: 5px; 61 | background-color: #c7d6eb; 62 | border-color: #c7ebe4; 63 | color: #968b93; 64 | 65 | 66 | } 67 | 68 | .all-inventory { 69 | display: grid; 70 | grid-template-columns: 1fr; 71 | justify-items: center; 72 | } -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const PORT_NUMBER = 3000; 4 | const path = require('path'); 5 | const cors = require('cors'); 6 | 7 | 8 | /** 9 | * require routers 10 | */ 11 | 12 | const accountsRouter = require('./routes/accounts.js'); 13 | const itemsRouter = require('./routes/items.js'); 14 | 15 | // handle parsing request body 16 | // json object 17 | app.use(express.json()); 18 | 19 | //use cors() on all requests 20 | app.use(cors()); 21 | 22 | /** 23 | * send static files to all requests with path '/' 24 | */ 25 | // send static files 26 | app.use('/', express.static(path.resolve(__dirname, '../dist/'))); 27 | 28 | //send index.html all all requests with path / 29 | app.get('/', (req, res) => { 30 | return res.status(200).sendFile(path.join(__dirname, '../dist/index.html')); 31 | }) 32 | 33 | /** 34 | * ROUTES 35 | */ 36 | 37 | // send to user router on path /accounts/ 38 | app.use('/accounts/',accountsRouter); 39 | // send to user router on path /items/ 40 | app.use('/items/',itemsRouter); 41 | 42 | 43 | // global error handler 44 | app.use((err, req, res, next) => { 45 | const defaultErr = { 46 | log: 'Express error handler caught unknown middleware error', 47 | status: 500, 48 | message: { err: 'An error occurred' }, 49 | }; 50 | 51 | const errorObj = Object.assign({}, defaultErr, err); 52 | console.log(errorObj.log); 53 | return res.status(errorObj.status).json(errorObj.message); 54 | }); 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | app.listen(PORT_NUMBER, () => { 77 | console.log(`listening on port ${PORT_NUMBER}`) 78 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "e-ventory-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "webpack.config.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "webpack", 9 | "dev": "webpack serve & nodemon server/server.js", 10 | "start": "nodemon server/server.js" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/e-Ventory/e-Ventory-App.git" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/e-Ventory/e-Ventory-App/issues" 21 | }, 22 | "homepage": "https://github.com/e-Ventory/e-Ventory-App#readme", 23 | "dependencies": { 24 | "cors": "^2.8.5", 25 | "css-loader": "^6.7.1", 26 | "express": "^4.17.3", 27 | "file-loader": "^6.2.0", 28 | "loader": "^2.1.1", 29 | "nodemon": "^2.0.15", 30 | "pg": "^8.7.3", 31 | "react": "^17.0.2", 32 | "react-dom": "^17.0.2", 33 | "react-hook-form": "^7.28.1", 34 | "react-router": "^6.2.2", 35 | "react-router-dom": "^6.2.2", 36 | "reactjs-popup": "^2.0.5", 37 | "regenerator-runtime": "^0.13.9", 38 | "style": "^0.0.3", 39 | "style-loader": "^3.3.1", 40 | "styled-components": "^5.3.3" 41 | }, 42 | "devDependencies": { 43 | "@babel/core": "^7.17.8", 44 | "@babel/preset-env": "^7.16.11", 45 | "@babel/preset-react": "^7.16.7", 46 | "babel-loader": "^8.2.3", 47 | "html-webpack-plugin": "^5.5.0", 48 | "sass": "^1.49.9", 49 | "sass-loader": "^12.6.0", 50 | "url-loader": "^4.1.1", 51 | "webpack": "^5.70.0", 52 | "webpack-cli": "^4.9.2", 53 | "webpack-dev-server": "^4.7.4" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /server/routes/accounts.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | router = express.Router(); 3 | const accountsController = require('../controllers/accountsController'); 4 | 5 | 6 | 7 | // handle get requests to the root path with a param - get a single account (NOT CURRENTLY USED IN FRONT END) 8 | router.get('/:name', accountsController.getAnAccount, (req,res) => { 9 | res.status(200).json({account: res.locals.account}) 10 | }); 11 | // handle get requests to the root path - gets all accounts information (USED WHEN SIGNING UP) 12 | router.get('/', accountsController.getAllAccounts, (req,res) => { 13 | res.contentType('application/json').status(200).json({accounts: res.locals.accounts}); 14 | }); 15 | // handle post requests to the signup path - Creates an Account (USED WHEN SIGNING UP) 16 | router.post('/signup', accountsController.createAccount, (req,res) => { 17 | res.contentType('application/json').status(200).json({message: res.locals.message}); 18 | }); 19 | // handle post requests to the path login - Logs in an account (USED WHEN LOGGING IN) 20 | router.post('/login/', accountsController.login, (req, res) => { 21 | res.contentType('application/json').status(200).json({account: res.locals.account}); 22 | }) 23 | // handle patch requests to the rooth path with a param(NOT CURRENTLY USED, SHOULD BE USED WHEN CHANGING PASSWORD) 24 | router.patch('/:name', accountsController.changePassword, (req, res) => { 25 | res.contentType('application/json').status(200).json({message: res.locals.message}); 26 | }) 27 | // handle delete requests to the root path with a param 28 | router.delete('/:name', accountsController.deleteAccount, (req, res) => { 29 | res.contentType('application/json').status(200).json({message: res.locals.message}); 30 | }) 31 | 32 | 33 | 34 | module.exports = router; -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | module.exports = { 6 | entry: ["regenerator-runtime/runtime.js", path.join(__dirname, './client/index.js')], 7 | output: { 8 | path: path.resolve(__dirname, 'dist'), 9 | filename: 'bundle.js' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.(js|jsx)$/, 15 | exclude: /node_modules/, 16 | use: { 17 | loader: "babel-loader", 18 | options: { 19 | presets: ['@babel/preset-env', '@babel/preset-react'] 20 | } 21 | } 22 | }, 23 | { 24 | test: /\.s[ac]ss$/i, 25 | use: [ "style-loader", "css-loader", "sass-loader"] 26 | }, 27 | { 28 | test: /\.(png|jp(e*)g|svg|gif)$/, 29 | use: ['file-loader', 'url-loader'], 30 | }, 31 | { 32 | test: /\.svg$/, 33 | use: ['@svgr/webpack'], 34 | } 35 | ] 36 | }, 37 | mode: 'development', 38 | devServer: { 39 | headers: { 40 | 'Access-Control-Allow-Origin': '*', 41 | "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS", 42 | "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization" 43 | }, 44 | proxy: { // proxy URLs to backend development server 45 | '/accounts/**': { 46 | target: 'http://localhost:3000/', 47 | secure: false, 48 | changeOrigin: true 49 | }, 50 | '/items/**': { 51 | target: 'http://localhost:3000/', 52 | secure: false, 53 | changeOrigin: true 54 | }, 55 | }, 56 | static: { 57 | directory: path.resolve(__dirname, '/client'),// boolean | string | array | object, static file location 58 | publicPath: '/dist' 59 | }, 60 | compress: true, // enable gzip compression 61 | historyApiFallback: true, // true for index.html upon 404, object for multiple paths 62 | hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin 63 | https: false, // true for self-signed, object for cert authority 64 | port: 8080, 65 | host: 'localhost' 66 | // ... 67 | }, 68 | plugins: [ new HtmlWebpackPlugin( { template: path.join(__dirname, './client/index.html')})], 69 | } -------------------------------------------------------------------------------- /client/components/Login.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../stylesheets/Login.scss'; 3 | import { useState } from 'react'; 4 | import { useForm } from "react-hook-form"; 5 | import { Link, } from 'react-router-dom'; 6 | //Login component 7 | 8 | 9 | //let options = { 10 | // method: 'POST', 11 | // headers: { 12 | // 'Content-Type': 'application/json;charset=utf-8' 13 | // }, 14 | // body: JSON.stringify(data) 15 | // } 16 | 17 | const Login = (props) => { 18 | // useForm hook returns an object containing a few properties. 19 | //register method helps register an input field into react hook form so that it is available for validation. 20 | //handleSubmit can handle two functions as arguments. first function passed as an arg will be onvoked along with registered field values when the form validation is successfull. 21 | const {register, handleSubmit} = useForm(); 22 | //const [data, setData] = useState("") 23 | 24 | return ( 25 |
26 |

Please sign in

27 |
{ 28 | //fetch request to server w/ email & password for login 29 | fetch('/accounts/login', { 30 | headers: { 31 | 'Accept' : 'application/json', 32 | 'Content-Type': 'application/json' 33 | }, 34 | method: 'POST', 35 | body: JSON.stringify(data) 36 | }) 37 | .then(response => response.json()) 38 | .then(data => { 39 | props.setUser(data.account); 40 | }) 41 | .catch(err => { 42 | console.log('were getting an error',err); 43 | alert('Wrong username/password'); 44 | props.setUser({user: {name: undefined}}); 45 | return; 46 | }); 47 | 48 | // create a post request then in the body send username and password 49 | // setData(JSON.stringify(data)) 50 | })}> 51 |
52 | 53 | {/* {renderErrorMessage("Please enter username")} */} 54 |
55 |
56 | 57 | {/* {renderErrorMessage("Please enter password")} */} 58 |
59 | 60 |
61 | 62 |
63 | ); 64 | }; 65 | 66 | export default Login; -------------------------------------------------------------------------------- /client/stylesheets/NavBar.scss: -------------------------------------------------------------------------------- 1 | 2 | //nav bar styling 3 | 4 | //logged in nav bar 5 | .LoggedIn { 6 | display: flex; 7 | flex-direction: row; 8 | margin-left: auto; 9 | margin-right: auto; 10 | align-items: center; 11 | // border: 5px #28afd8d2; 12 | background: #28afd8d2; 13 | border-radius: 5px; 14 | 15 | } 16 | 17 | //logged out nav bar 18 | .LoggedOut { 19 | display: flex; 20 | flex-direction: row; 21 | //margin-left: auto; 22 | //margin-right: auto; 23 | align-items: center; 24 | border: 5px solid #28afd8d2; 25 | background: #28afd8d2; 26 | border-radius: 10px; 27 | } 28 | 29 | //logo image 30 | .logo { 31 | max-width: 6%; 32 | max-height: auto; 33 | } 34 | 35 | //company name styling 36 | .brand { 37 | font-family: 'Roboto', sans-serif; 38 | font-style: normal; 39 | font-size: 50px; 40 | color: rgb(250, 250, 250); 41 | padding-left: 1%; 42 | } 43 | 44 | .subHeader { 45 | font-family: 'Roboto', sans-serif; 46 | font-style: normal; 47 | font-size: 20px; 48 | color: rgb(250, 250, 250); 49 | padding-left: 1%; 50 | } 51 | 52 | //about us link 53 | .deadLink1 { 54 | display: flex; 55 | font-family: 'Roboto', sans-serif; 56 | font-style: normal; 57 | font-size: 25px; 58 | color: rgb(250, 250, 250); 59 | padding-left: 1%; 60 | //align-self: right; 61 | //text-align: right; 62 | float: right; 63 | position: absolute; 64 | right: 25px; 65 | 66 | } 67 | 68 | // packages link 69 | .deadLink2 { 70 | display: flex; 71 | font-family: 'Roboto', sans-serif; 72 | font-style: normal; 73 | font-size: 25px; 74 | color: rgb(250, 250, 250); 75 | padding-left: 1%; 76 | //align-self: right; 77 | //text-align: right; 78 | float: right; 79 | position: absolute; 80 | right: 150px; 81 | 82 | } 83 | 84 | #inventoryLink { 85 | display: flex; 86 | font-family: 'Roboto', sans-serif; 87 | font-style: normal; 88 | font-size: 25px; 89 | color: rgb(250, 250, 250); 90 | padding-left: 1%; 91 | //align-self: right; 92 | //text-align: right; 93 | float: right; 94 | position: absolute; 95 | right: 150px; 96 | } 97 | 98 | #accountLink { 99 | display: flex; 100 | font-family: 'Roboto', sans-serif; 101 | font-style: normal; 102 | font-size: 25px; 103 | color: rgb(250, 250, 250); 104 | padding-left: 1%; 105 | //align-self: right; 106 | //text-align: right; 107 | float: right; 108 | position: absolute; 109 | right: 25px; 110 | } -------------------------------------------------------------------------------- /client/components/Inventory.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Popup from 'reactjs-popup' 3 | 4 | // change state and have if statement for what is displayed 5 | const Inventory = (props) => { 6 | return ( 7 | // displays all values shown in columns for each inventory item 8 |
9 |

{props.invInfo.id}

10 |

{props.invInfo.name.toUpperCase()}

11 |

{props.invInfo.quantity}

12 |

{props.invInfo.category.toUpperCase()}

13 |

{props.invInfo.location.toUpperCase()}

14 | {/* popup for add items, no info is required. only add info you want changed */} 15 | Update}> 16 |
props.updatedItem(e)} > 17 | 18 |
19 | 20 |
21 |
22 | 23 |
24 |
25 | 26 |
27 |
28 | 29 |
30 |
31 | 32 |
33 |
34 | 35 |
36 |
37 |
38 | {/* delete button */} 39 |
props.deletedItem(e)}> 40 | 41 | 42 |
43 |
44 | ); 45 | }; 46 | 47 | export default Inventory; 48 | 49 | {/*

{props.inv[props.id].id}

50 |

{props.inv[props.id].name}

51 |

{props.inv[props.id].quantity}

52 |

{props.inv[props.id].category}

53 |

{props.inv[props.id].location}

*/} -------------------------------------------------------------------------------- /server/controllers/itemsController.js: -------------------------------------------------------------------------------- 1 | const itemsController = {}; 2 | const client = require('../models/eventoryModel'); 3 | 4 | itemsController.getAllItems = async (req , res, next ) => { 5 | // right now this just grabs all items, do we want to make sure we only grab items from 6 | // a particular user???? 7 | const { id } = req.params; 8 | 9 | try { 10 | const dbRes = await client.query('SELECT * FROM items WHERE items.account_id = $1', [id]); 11 | // console.log(dbRes.rows); 12 | res.locals.items = [...dbRes.rows]; 13 | console.log('GETTING TO THE GET ALL USERS MIDDLEWARE'); 14 | return next(); 15 | } 16 | catch (err) { 17 | return next({ 18 | log: 'Error Express - itemsController.getAllUsers', 19 | status: 500, 20 | message: {err} 21 | }) 22 | } 23 | 24 | } 25 | 26 | itemsController.updateItem = async (req , res, next ) => { 27 | 28 | const { id } = req.body.items; 29 | 30 | try { 31 | // Line 31 - 47 is to update only field that were filled in 32 | // copy item 33 | const updateItemInfo = {...req.body.items}; 34 | // check item for null values 35 | const newUpdatedItem = {}; 36 | for (const property in updateItemInfo) { 37 | if (updateItemInfo[property]) { 38 | newUpdatedItem[property] = updateItemInfo[property]; 39 | } 40 | } 41 | // grab old item 42 | const dbItemRes = await client.query('SELECT * FROM items WHERE items.id = $1', [id]); 43 | 44 | // spread new info into old item 45 | const newObject = { ...dbItemRes.rows[0], ...newUpdatedItem }; 46 | 47 | const { name, info, quantity, category, location } = newObject; 48 | 49 | const dbRes = await client.query( 50 | "UPDATE items SET name = $1, info = $2, quantity = $3, category = $4, location = $5 WHERE id = $6;" 51 | , [name, info, quantity, category, location, id]); 52 | console.log(dbRes.command); 53 | res.locals.updatedItem = { id, name, info, quantity, category, location}; 54 | return next(); 55 | } 56 | catch (err) { 57 | return next({ 58 | log: 'Error Express - itemsController.updateItem', 59 | status: 500, 60 | message: {err} 61 | }) 62 | } 63 | 64 | } 65 | 66 | // Create an inventory item on the database 67 | itemsController.createItem = async (req , res, next ) => { 68 | 69 | // Grabs Query info from the request body 70 | const { name, info, quantity, category, location, account_id } = req.body.items; 71 | 72 | console.log(req.body.items); 73 | 74 | try { 75 | const dbRes = await client.query('INSERT INTO items (name, info, quantity, category, location, account_id) VALUES ($1, $2, $3, $4, $5, $6)', [name, info, quantity, category, location, account_id]); 76 | console.log(dbRes); 77 | res.locals.createdItem = { name, info, quantity, category, location, account_id }; 78 | return next(); 79 | } 80 | catch (err) { 81 | return next({ 82 | log: {err}, 83 | status: 500, 84 | message: {err} 85 | }) 86 | } 87 | 88 | } 89 | 90 | itemsController.deleteItem = async (req , res, next ) => { 91 | 92 | const item_id = req.params.itemId; 93 | 94 | try { 95 | const dbRes = await client.query('DELETE FROM items WHERE ID = $1', [item_id]); 96 | // console.log(dbRes); 97 | return next(); 98 | } 99 | catch (err) { 100 | return next({ 101 | log: 'Error Express - itemsController.deleteItem', 102 | status: 500, 103 | message: {err} 104 | }) 105 | } 106 | 107 | } 108 | 109 | module.exports = itemsController; -------------------------------------------------------------------------------- /client/components/SignUp.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../stylesheets/Login.scss'; 3 | import { useState } from 'react'; 4 | import { useForm } from "react-hook-form"; 5 | import { useEffect } from 'react' 6 | 7 | const SignUp = (props) => { 8 | 9 | const { register, handleSubmit } = useForm(); 10 | //const [data, setData] = useState(""); 11 | let userList = []; 12 | 13 | 14 | useEffect(() => { 15 | // fetch the data for all accounts 16 | fetch('/accounts/', { 17 | headers: { 18 | 'Accept' : 'application/json', 19 | 'Content-Type': 'application/json' 20 | }, 21 | method: 'GET', 22 | }) 23 | .then(response => response.json()) 24 | .then(data => { 25 | userList = data.accounts; 26 | console.log(data.accounts) 27 | }) 28 | .catch(err => { 29 | console.log('were getting an error',err); 30 | }); 31 | },[]) 32 | 33 | // const signUpRequest = (data) => { 34 | // useEffect(() => { 35 | // //check to see if name exist in DB already. 36 | // // if it does don't submit (message: user already exists) 37 | // //else send to inventory page 38 | // }) 39 | // } 40 | 41 | 42 | 43 | 44 | return ( 45 |
46 |

Please sign up

47 |
{ 48 | let isValid = true; 49 | console.log('userList', userList); 50 | for (let i = 0; i < userList.length; i++) { 51 | if (userList[i].name === data.name || userList[i].email === data.email) { 52 | alert("Username/email already exists"); 53 | isValid = false; 54 | return; 55 | } 56 | } 57 | if(isValid){ 58 | fetch('/accounts/signup', { 59 | headers: { 60 | 'Accept' : 'application/json', 61 | 'Content-Type': 'application/json' 62 | }, 63 | method: 'POST', 64 | body: JSON.stringify(data) 65 | }) 66 | .then(response => response.json()) 67 | .then(resData => { 68 | console.log("67 console.log ", resData.message) 69 | console.log('data', data); 70 | console.log('props', props); 71 | props.setUser(data); 72 | }) 73 | .catch(err => { 74 | console.log('were getting an error', err); 75 | }); 76 | } 77 | })}> 78 |
79 | 80 | {/* {renderErrorMessage("Please enter username")} */} 81 |
82 |
83 | 84 | {/* {renderErrorMessage("Please enter password")} */} 85 |
86 |
87 | 88 | {/* {renderErrorMessage("Please enter password")} */} 89 |
90 |
91 | 97 | {/* {renderErrorMessage("Please enter password")} */} 98 | 99 | 100 |
101 |
102 |
103 | ); 104 | }; 105 | 106 | export default SignUp; -------------------------------------------------------------------------------- /client/stylesheets/Login.scss: -------------------------------------------------------------------------------- 1 | //display :none 2 | //have container toggle between display block and display none 3 | 4 | //Login/Signup compnent 5 | 6 | // .LSPage { 7 | // display: grid; 8 | // grid-auto-columns: 50px; 9 | // } 10 | 11 | .LoginSignupBox { 12 | display: flex; 13 | flex-direction: column; 14 | margin-left: auto; 15 | margin-right: auto; 16 | border-radius: 5%; 17 | background-color: rgb(240, 241, 231); 18 | 19 | border-style: outset; 20 | 21 | width: 250px; 22 | height: 360px; 23 | //justify-content: center; 24 | align-items: center; 25 | border: 3px solid rgb(240, 241, 231); 26 | background-color: #28afd8d2; 27 | border-radius: 20px; 28 | box-sizing: border-box; 29 | height: 500px; 30 | padding: 20px; 31 | width: 320px; 32 | margin-top: 20px; 33 | }; 34 | 35 | //welcome Header 36 | .welcome { 37 | color: #eee; 38 | font-family: sans-serif; 39 | font-size: 36px; 40 | font-weight: 600; 41 | margin-top: 30px; 42 | } 43 | 44 | //sign in / sign up header 45 | .SI { 46 | color: #eee; 47 | font-family: sans-serif; 48 | font-size: 19px; 49 | font-weight: 600; 50 | margin-top: 70px; 51 | text-align: center; 52 | } 53 | 54 | // login email input box 55 | #username { 56 | background-color: #303245; 57 | border-radius: 12px; 58 | border: 0; 59 | box-sizing: border-box; 60 | color: #eee; 61 | font-size: 15px; 62 | height:100%; 63 | outline: 0; 64 | padding: 5px 20px 5px; 65 | width: 100%; 66 | margin-top: 5%; 67 | 68 | 69 | } 70 | // login password input box 71 | #PW { 72 | background-color: #303245; 73 | border-radius: 12px; 74 | border: 0; 75 | box-sizing: border-box; 76 | color: #eee; 77 | font-size: 15px; 78 | height:100%; 79 | outline: 0; 80 | padding: 5px 20px 5px 20px; 81 | width: 100%; 82 | margin-top: 5%; 83 | margin-bottom: 50%; 84 | //width: auto; 85 | } 86 | 87 | // signup name box 88 | #namesignup { 89 | background-color: #303245; 90 | border-radius: 12px; 91 | border: 0; 92 | box-sizing: border-box; 93 | color: #eee; 94 | font-size: 15px; 95 | height:100%; 96 | outline: 0; 97 | padding: 5px 20px 5px; 98 | width: 100%; 99 | margin-top: 2%; 100 | } 101 | 102 | // email signup box 103 | #emailsignup { 104 | background-color: #303245; 105 | border-radius: 12px; 106 | border: 0; 107 | box-sizing: border-box; 108 | color: #eee; 109 | font-size: 15px; 110 | height:100%; 111 | outline: 0; 112 | padding: 5px 20px 5px; 113 | width: 100%; 114 | margin-top: 2%; 115 | } 116 | 117 | // signup password signup box 118 | #pwsignup { 119 | background-color: #303245; 120 | border-radius: 12px; 121 | border: 0; 122 | box-sizing: border-box; 123 | color: #eee; 124 | font-size: 15px; 125 | height:100%; 126 | outline: 0; 127 | padding: 5px 20px 5px; 128 | width: 100%; 129 | margin-top: 2%; 130 | } 131 | 132 | // signup category drop down 133 | #dropdownlogin { 134 | background-color: #303245; 135 | border-radius: 12px; 136 | border: 0; 137 | box-sizing: border-box; 138 | color: #eee; 139 | font-size: 15px; 140 | height:100%; 141 | outline: 0; 142 | padding: 5px 20px 5px; 143 | width: 100%; 144 | margin-top: 2%; 145 | margin-bottom: 25%; 146 | } 147 | 148 | // submit button style 149 | .submitbutton { 150 | background-image: linear-gradient(-180deg, #37AEE2 0%, #1E96C8 100%); 151 | border-radius: .5rem; 152 | box-sizing: border-box; 153 | color: #FFFFFF; 154 | display: flex; 155 | font-size: 16px; 156 | justify-content: center; 157 | padding: 1rem 1.75rem; 158 | text-decoration: none; 159 | width: 100%; 160 | border: 0; 161 | //margin-top: 40%; 162 | margin-bottom: 5%; 163 | 164 | 165 | 166 | .button-43:hover { 167 | background-image: linear-gradient(-180deg, #1D95C9 0%, #17759C 100%); 168 | } 169 | 170 | 171 | } 172 | 173 | 174 | // terms and conditions link 175 | .Terms { 176 | display: grid; 177 | justify-content: center; 178 | align-items: center; 179 | margin-left: auto; 180 | margin-right: auto; 181 | max-height: 10%; 182 | position: right; 183 | 184 | } 185 | 186 | #loginArt1 { 187 | max-width: 35%; 188 | max-height: auto; 189 | position: absolute; 190 | margin-top: auto; 191 | margin-bottom: auto; 192 | margin-top: 80px; 193 | } 194 | 195 | #loginArt2 { 196 | display: flex; 197 | max-width: 30%; 198 | max-height: auto; 199 | position: absolute; 200 | margin-top: 63px; 201 | margin-left: 820px; 202 | align-items: center; 203 | } 204 | -------------------------------------------------------------------------------- /client/components/InventoryDisplay.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import Inventory from './Inventory.jsx'; 3 | import Popup from 'reactjs-popup'; 4 | //import AddItem from './AddItem.jsx'; 5 | import '../stylesheets/Inventory.scss'; 6 | import { useForm } from 'react-hook-form'; 7 | import 'regenerator-runtime/runtime'; 8 | 9 | const InventoryDisplay = (props) => { 10 | 11 | // state for inventory 12 | const [ inv, setInv ] = useState([]); 13 | 14 | 15 | const [ userId, setUserId ] = useState([props.user.id]) 16 | // function to add item 17 | const addedItem = (e) => { 18 | e.preventDefault(); 19 | const body = { 20 | items: { 21 | account_id: e.target[0].value, 22 | name: e.target[1].value, 23 | quantity: e.target[2].value, 24 | info: e.target[3].value, 25 | category: e.target[4].value, 26 | location: e.target[5].value, 27 | } 28 | } 29 | const url = 'http://localhost:3000/items/'; 30 | fetch(url, { 31 | method: 'POST', 32 | headers: { 33 | 'Content-Type': 'application/json' 34 | }, 35 | body: JSON.stringify(body), 36 | }) 37 | .then(() => inventoryGet()); 38 | } 39 | 40 | // function to get the user ID 41 | // function to delete item 42 | const deletedItem = (e) => { 43 | e.preventDefault(); 44 | const url = 'http://localhost:3000/items/'.concat(e.target[0].value); 45 | fetch(url, { 46 | method: 'DELETE', 47 | headers: { 48 | 'Content-Type': 'application/json' 49 | }, 50 | }) 51 | .then(() => inventoryGet()); 52 | } 53 | 54 | // function that runs to update item 55 | const updatedItem = (e) => { 56 | e.preventDefault(); 57 | 58 | // grab all relevant info from the synthetic event when updat button is pressed 59 | const body = { 60 | items: { 61 | id: e.target[0].value, 62 | name: e.target[1].value, 63 | quantity: e.target[2].value, 64 | info: e.target[3].value, 65 | category: e.target[4].value, 66 | location: e.target[5].value, 67 | } 68 | } 69 | // Patch request to update an item 70 | const url = 'http://localhost:3000/items/'; 71 | fetch(url, { 72 | method: 'PATCH', 73 | headers: { 74 | 'Content-Type': 'application/json' 75 | }, 76 | body: JSON.stringify(body), 77 | }) 78 | .then(() => inventoryGet()); 79 | } 80 | 81 | // function to get current users inventory 82 | const inventoryGet = () => { 83 | let invData; 84 | const url = 'http://localhost:3000/items/'.concat(props.user.id); 85 | 86 | fetch(url, { 87 | method: 'GET', 88 | headers: { 89 | 'Content-Type': 'application/json' 90 | } 91 | }) 92 | .then((data) => data.json()) 93 | .then((data) => invData = data.items) 94 | .then((data) => { 95 | const invClass = []; 96 | // make an inventory component for each item received in the get request 97 | invData.sort((a, b) => b.id - a.id) 98 | invData.forEach((el, index) => { 99 | invClass.push() 100 | }) 101 | setInv(invClass); 102 | }); 103 | } 104 | // get inventory on first render 105 | useEffect(() => { 106 | inventoryGet(); 107 | }, []); 108 | 109 | 110 | return ( 111 |
112 |
113 |

ID

114 |

NAME

115 |

QUANTITY

116 |

CATEGORY

117 |

LOCATION

118 |
119 | 120 | {/* whole div needs to be added per item in inventory array */} 121 |
122 | {inv} 123 |
124 |
125 | Add Item} position="right center"> 126 |
addedItem(e)} > 127 |
128 | 129 |
130 |
131 | 132 |
133 |
134 | 135 |
136 |
137 | 138 |
139 |
140 | 141 |
142 |
143 | 144 |
145 |
146 | 147 |
148 |
149 |
150 |
151 |
152 | 153 | ); 154 | }; 155 | 156 | export default InventoryDisplay; -------------------------------------------------------------------------------- /server/controllers/accountsController.js: -------------------------------------------------------------------------------- 1 | const accountsController = {}; 2 | const client = require('../models/eventoryModel'); 3 | 4 | /* 5 | * Middleware to get all Accounts 6 | */ 7 | accountsController.getAllAccounts = async (req , res, next ) => { 8 | try { 9 | // query the database for all accounts in accounts 10 | const dbRes = await client.query('SELECT * FROM accounts'); 11 | // store the result of the query into res.locals.accounts 12 | res.locals.accounts = dbRes.rows 13 | // return next 14 | return next(); 15 | } 16 | catch (err) { 17 | // if there is an err, return the errorObj to the global error handler 18 | return next({ 19 | log: 'Error Express - usersController.getAllUsers', 20 | status: 500, 21 | message: {err} 22 | }) 23 | } 24 | } 25 | /* 26 | * Middleware to get a single account 27 | */ 28 | accountsController.getAnAccount = async (req , res, next ) => { 29 | // get the name from req.params 30 | const { name } = req.params; 31 | try { 32 | // create an object with the query text, and the values to insert into the query 33 | const query = { 34 | text:'SELECT * FROM accounts WHERE accounts.name = $1', 35 | values: [id], 36 | } 37 | // query the database for all accounts in accounts 38 | const dbRes = await client.query(query); 39 | // store the result of the query into res.locals.accounts 40 | res.locals.account = dbRes.rows[0] 41 | // return next 42 | return next(); 43 | } 44 | catch (err) { 45 | // if there is an err, return the errorObj to the global error handler 46 | return next({ 47 | log: 'Error Express - accountsController.getAnAccount', 48 | status: 500, 49 | message: {err}, 50 | }) 51 | } 52 | } 53 | /* 54 | * Middleware to create an account 55 | */ 56 | accountsController.createAccount = async (req , res, next ) => { 57 | 58 | // get the name, email, password, type from the req.body 59 | const {name, email, password, type} = req.body; 60 | try { 61 | // create an object with the query text, and the values to insert into the query 62 | const query = { 63 | text:'INSERT INTO accounts (name, email, password, type) VALUES ($1, $2, $3, $4)', 64 | values: [name, email, password, type], 65 | } 66 | // query the database for all accounts in accounts 67 | await client.query(query); 68 | // store the result of the query into res.locals.accounts 69 | res.locals.message = `Account ${name} has been created` 70 | // return next 71 | return next(); 72 | } 73 | catch (err) { 74 | // if there is an err, return the errorObj to the global error handler 75 | return next({ 76 | log: 'Error Express - accountsController.createAccount', 77 | status: 500, 78 | message: {err}, 79 | }) 80 | } 81 | } 82 | 83 | /** 84 | * Middleware to login 85 | */ 86 | accountsController.login = async (req, res, next) => { 87 | // get the username and password from the req body 88 | const {username, password} = req.body; 89 | // get the account information from the database 90 | try { 91 | // select all users with the username 92 | const query = { 93 | text:'SELECT * from accounts WHERE name = $1', 94 | values: [username], 95 | } 96 | // query the database, assign the result in dbRes 97 | const dbRes = await client.query(query); 98 | //check if the account password matches the req body password 99 | if (dbRes.rows[0].password === password) { 100 | // assign res.locals.account the account information 101 | res.locals.account = dbRes.rows[0]; 102 | // go to the next middleware 103 | next(); 104 | } else { 105 | // if the passwords dont match return an error 106 | return next({ 107 | log: 'Error Express - accountsController.login, password does not match', 108 | status: 500, 109 | message: {err: "Password does not match"}, 110 | }) 111 | } 112 | }catch(err) { 113 | // if there is an err, return the errorObj to the global error handler 114 | // if it errs here, the account does not exist 115 | return next({ 116 | log: 'Error Express - accountsController.login', 117 | status: 500, 118 | message: {err: "Account does not exist"}, 119 | }) 120 | } 121 | } 122 | /** 123 | * Middleware to change password 124 | */ 125 | accountsController.changePassword = async (req , res, next ) => { 126 | // get the name from params 127 | const { name } = req.params; 128 | // get the new password from the body 129 | const { password } = req.body; 130 | try { 131 | // update the password where the account name is equal to name 132 | const query = { 133 | text:'UPDATE accounts SET password = $2 WHERE accounts.name = $1', 134 | values: [name, password] 135 | } 136 | await client.query(query); 137 | // assign res.locals.message a string stating the password has been updated 138 | res.locals.message = "Password has been updated"; 139 | // go to the next middleware 140 | next(); 141 | } 142 | catch (err) { 143 | // if there is an err, return the errorObj to the global error handler 144 | return next({ 145 | log: 'Error Express - accountsController.changePassword', 146 | status: 500, 147 | message: {err}, 148 | }) 149 | } 150 | } 151 | /** 152 | * Middleware to delete an account 153 | */ 154 | accountsController.deleteAccount = async (req , res, next ) => { 155 | // get the name from params 156 | const { name } = req.params; 157 | try { 158 | // update the password where the account name is equal to name 159 | const query = { 160 | text:'DELETE FROM accounts WHERE accounts.name = $1', 161 | values: [name] 162 | } 163 | await client.query(query); 164 | // assign res.locals.message a string stating the password has been updated 165 | res.locals.message = "Account has been deleted"; 166 | // go to the next middleware 167 | next(); 168 | } 169 | catch (err) { 170 | // if there is an err, return the errorObj to the global error handler 171 | return next({ 172 | log: 'Error Express - accountsController.deleteAccount', 173 | status: 500, 174 | message: {err}, 175 | }) 176 | } 177 | } 178 | 179 | 180 | 181 | module.exports = accountsController; --------------------------------------------------------------------------------