├── .prettierrc ├── .travis.yml ├── src ├── components │ ├── Session │ │ ├── context.js │ │ ├── index.js │ │ ├── withAuthentication.js │ │ └── withAuthorization.js │ ├── Firebase │ │ ├── index.js │ │ ├── context.js │ │ └── firebase.js │ ├── Cards │ │ ├── index.js │ │ ├── tableCard.js │ │ ├── menuItemCard.js │ │ ├── clientMenuItemCard.js │ │ └── orderCard.js │ ├── Modals │ │ ├── index.js │ │ ├── MobileModal.js │ │ ├── MenuDemoModal.js │ │ ├── TableQRModal.js │ │ ├── DashboardDemoModal.js │ │ └── style.css │ ├── PasswordChange │ │ ├── passwordChangeView.js │ │ └── index.js │ ├── Account │ │ ├── style.css │ │ ├── accountView.js │ │ └── index.js │ ├── Home │ │ ├── index.js │ │ ├── homeView.js │ │ └── style.css │ ├── PasswordForget │ │ ├── style.css │ │ └── index.js │ ├── App │ │ └── index.js │ ├── Navigation │ │ ├── style.css │ │ └── index.js │ ├── SignOut │ │ └── index.js │ ├── Menu │ │ ├── orderConfirmScreen.js │ │ ├── menuView.js │ │ ├── style.css │ │ └── index.js │ ├── Dashboard │ │ ├── dashboardView.js │ │ └── index.js │ ├── SignUp │ │ ├── style.css │ │ └── index.js │ ├── SignIn │ │ ├── style.css │ │ └── index.js │ ├── TablesManager │ │ ├── style.css │ │ ├── tablesManagerView.js │ │ ├── tablesSideboard.js │ │ └── index.js │ ├── MenuManager │ │ ├── menuManagerView.js │ │ ├── style.css │ │ ├── menuSideboard.js │ │ └── index.js │ └── OrdersManager │ │ ├── ordersManagerView.js │ │ ├── ordersSideboard.js │ │ ├── style.css │ │ └── index.js ├── constants │ ├── routes.js │ └── demoData.js ├── index.js ├── store.js ├── index.css └── serviceWorker.js ├── public ├── manifest.json └── index.html ├── .gitignore ├── package.json ├── LICENSE └── README.md /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "singleQuote": true, 5 | "printWidth": 70 6 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - stable 5 | 6 | install: 7 | - npm install 8 | 9 | script: 10 | - npm test -------------------------------------------------------------------------------- /src/components/Session/context.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const AuthUserContext = React.createContext(null); 4 | 5 | export default AuthUserContext; 6 | -------------------------------------------------------------------------------- /src/components/Firebase/index.js: -------------------------------------------------------------------------------- 1 | import FirebaseContext, { withFirebase } from './context'; 2 | import Firebase from './firebase'; 3 | 4 | export default Firebase; 5 | 6 | export { FirebaseContext, withFirebase }; 7 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "DashTabs", 3 | "name": "DashTabs", 4 | "icons": [], 5 | "start_url": "./index.html", 6 | "display": "standalone", 7 | "theme_color": "#000000", 8 | "background_color": "#ffffff" 9 | } 10 | -------------------------------------------------------------------------------- /src/components/Session/index.js: -------------------------------------------------------------------------------- 1 | import AuthUserContext from './context'; 2 | import withAuthorization from './withAuthorization'; 3 | import withAuthentication from './withAuthentication'; 4 | 5 | export { AuthUserContext, withAuthentication, withAuthorization }; 6 | -------------------------------------------------------------------------------- /src/components/Cards/index.js: -------------------------------------------------------------------------------- 1 | import OrderCard from './orderCard'; 2 | import TableCard from './tableCard'; 3 | import MenuItemCard from './menuItemCard'; 4 | import ClientMenuItemCard from './clientMenuItemCard'; 5 | 6 | export { MenuItemCard, OrderCard, TableCard, ClientMenuItemCard }; -------------------------------------------------------------------------------- /src/constants/routes.js: -------------------------------------------------------------------------------- 1 | export const SIGN_UP = '/signup'; 2 | export const SIGN_IN = '/signin'; 3 | export const HOME = '/'; 4 | export const ACCOUNT = '/account'; 5 | export const DASHBOARD = '/dashboard'; 6 | export const PASSWORD_FORGET = '/pw-forget'; 7 | export const MENU = '/menu'; -------------------------------------------------------------------------------- /src/components/Firebase/context.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const FirebaseContext = React.createContext(null); 4 | 5 | export const withFirebase = Component => props => ( 6 | 7 | {firebase => } 8 | 9 | ); 10 | 11 | export default FirebaseContext; 12 | -------------------------------------------------------------------------------- /src/components/Modals/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | import '../../index.css'; 4 | 5 | export default class Modal extends Component { 6 | render() { 7 | let showHideClassName = this.props.show ? "modal display-block" : "modal display-none"; 8 | return ( 9 |
10 | {this.props.children} 11 |
12 | ) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.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 15 | .env.development 16 | .env.production 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | DashTabs 9 | 10 | 11 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/components/Cards/tableCard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const TableCard = ({ 4 | idx, 5 | table, 6 | editTable, 7 | isSelected, 8 | }) => { 9 | return ( 10 |
editTable(idx)} 13 | id={isSelected && "cardSelected"} 14 | > 15 |

16 | #{table.number} 17 |

18 |

19 | {table.description} 20 |

21 |
22 | ); 23 | }; 24 | 25 | export default TableCard; -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import './index.css'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | import App from './components/App'; 8 | import Firebase, { FirebaseContext } from './components/Firebase'; 9 | 10 | ReactDOM.render( 11 | 12 | 13 | , 14 | document.getElementById('root'), 15 | ); 16 | 17 | // If you want your app to work offline and load faster, you can change 18 | // unregister() to register() below. Note this comes with some pitfalls. 19 | // Learn more about service workers: http://bit.ly/CRA-PWA 20 | serviceWorker.unregister(); 21 | -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | import React, { useReducer, createContext } from "react"; 2 | 3 | const initialState = { view: "orders", sideboardOpen: false }; 4 | 5 | function reducer (state, action) { 6 | switch(action.type) { 7 | case 'TOGGLE_VIEW': 8 | return { ...state, view: action.payload }; 9 | case 'TOGGLE_SIDEBOARD': 10 | return { ...state, sideboardOpen: action.payload }; 11 | default: 12 | return { ...state }; 13 | } 14 | }; 15 | 16 | export function StoreProvider (props) { 17 | const [state, dispatch] = useReducer(reducer, initialState) 18 | const value = { state, dispatch } 19 | return {props.children} 20 | } 21 | 22 | export const Store = createContext(); -------------------------------------------------------------------------------- /src/components/Cards/menuItemCard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const MenuItemCard = ({ 4 | el, 5 | idx, 6 | editItem, 7 | isSelected, 8 | editItemType, 9 | }) => { 10 | return ( 11 |
editItem(el, editItemType, idx)} 15 | > 16 |

17 | {el.name} 18 |

19 |
20 |
21 |

22 | Price 23 |

24 |

25 | ${el.price} 26 |

27 |
28 |

29 | {el.available ? "Available" : "Not Available"} 30 |

31 |
32 |
33 | ); 34 | }; 35 | 36 | export default MenuItemCard; -------------------------------------------------------------------------------- /src/components/Modals/MobileModal.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { withRouter } from 'react-router-dom'; 3 | 4 | import * as ROUTES from '../../constants/routes'; 5 | 6 | const MobileModal = (props) => ( 7 |
8 |
9 |
10 |

11 | The dashboard is currently not optimized for mobile usage. 12 |

13 |

14 | Please switch to a desktop computer to get the best experience. 15 |

16 |
17 |
18 |
19 |
props.history.push(ROUTES.HOME)} 21 | className="btn" 22 | > 23 | GO BACK 24 |
25 |
26 |
27 | ) 28 | 29 | export default withRouter(MobileModal); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dashtabs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@fortawesome/fontawesome-svg-core": "^6.4.0", 7 | "@fortawesome/free-solid-svg-icons": "^6.4.0", 8 | "@fortawesome/react-fontawesome": "^0.2.0", 9 | "firebase": "^9.19.1", 10 | "print-js": "^1.6.0", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-recompose": "^0.33.0", 14 | "react-router-dom": "^5.3.4", 15 | "react-scripts": "^5.0.1" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test --env=jsdom --passWithNoTests", 21 | "eject": "react-scripts eject" 22 | }, 23 | "browserslist": [ 24 | ">0.2%", 25 | "not dead", 26 | "not ie <= 11", 27 | "not op_mini all" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /src/components/PasswordChange/passwordChangeView.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const PasswordChangeView = ({ 4 | error, 5 | onSubmit, 6 | onChange, 7 | isInvalid, 8 | passwordOne, 9 | passwordTwo, 10 | }) => ( 11 |
12 |

UPDATE PASSWORD

13 |
14 | 21 | 28 |
onSubmit(e)} 31 | > 32 | RESET 33 |
34 |
35 | {error &&

{error.message}

} 36 |
37 | ); 38 | 39 | export default PasswordChangeView; -------------------------------------------------------------------------------- /src/components/Account/style.css: -------------------------------------------------------------------------------- 1 | .accountView { 2 | height: 100vh; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .accountView > .accountForm { 8 | width: auto; 9 | height: 100%; 10 | display: flex; 11 | align-self: center; 12 | margin-left: 6.8rem; 13 | padding-top: 5.3rem; 14 | flex-direction: column; 15 | } 16 | 17 | .accountForm h3 { 18 | font-size: 0.8rem; 19 | margin-bottom: 0.4rem; 20 | } 21 | 22 | .accountForm > div:first-of-type > h3:last-of-type { 23 | font-weight: 500; 24 | } 25 | 26 | .accountForm input { 27 | width: auto; 28 | border: none; 29 | height: 1.8rem; 30 | font-size: 0.9rem; 31 | margin-right: 1rem; 32 | border-radius: .3rem; 33 | padding: 1rem 0.7rem; 34 | background: #F5F5F7; 35 | } 36 | 37 | .accountForm > div { 38 | display: flex; 39 | margin-bottom: 2rem; 40 | flex-direction: column; 41 | } 42 | 43 | .accountForm > div > div { 44 | display: flex; 45 | padding-top: 0.5rem; 46 | align-items: center; 47 | border-top: 1px dashed black; 48 | } 49 | 50 | .accountForm .btn { 51 | width: 5rem; 52 | } -------------------------------------------------------------------------------- /src/components/Home/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import HomeView from './homeView'; 4 | import { withFirebase } from '../Firebase'; 5 | import * as ROUTES from '../../constants/routes'; 6 | import * as DEMODATA from '../../constants/demoData'; 7 | 8 | const HomePage = (props) => { 9 | const launchDemo = () => { 10 | props.firebase.doSignOut(); 11 | props.firebase.doSignInAnonymously() 12 | .then(() => { 13 | let currentUid = props.firebase.getCurrentUserUid(); 14 | props.firebase.userOrders(currentUid).set(DEMODATA.ORDERS); 15 | props.firebase.userMenu(currentUid).set(DEMODATA.MENU); 16 | props.firebase.user(currentUid).set(DEMODATA.USER); 17 | props.firebase.demoCleanupDb(); 18 | let clientMenuUrl = `${window.location.href}menu/${currentUid}/takeout`; 19 | props.history.push(ROUTES.DASHBOARD); 20 | window.open(clientMenuUrl, "_blank"); 21 | }); 22 | }; 23 | return 24 | }; 25 | 26 | export default withFirebase(HomePage); -------------------------------------------------------------------------------- /src/components/Session/withAuthentication.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import AuthUserContext from './context'; 4 | import { withFirebase } from '../Firebase'; 5 | 6 | const withAuthentication = Component => { 7 | class WithAuthentication extends React.Component { 8 | constructor(props) { 9 | super(props); 10 | this.state = { 11 | authUser: null, 12 | }; 13 | } 14 | 15 | componentDidMount() { 16 | this.listener = this.props.firebase.onAuthUserListener( 17 | authUser => { 18 | this.setState({ authUser }); 19 | }, 20 | () => { 21 | this.setState({ authUser: null }); 22 | }, 23 | ); 24 | } 25 | 26 | componentWillUnmount() { 27 | this.listener(); 28 | } 29 | 30 | render() { 31 | return ( 32 | 33 | 34 | 35 | ); 36 | } 37 | } 38 | 39 | return withFirebase(WithAuthentication); 40 | }; 41 | 42 | export default withAuthentication; 43 | -------------------------------------------------------------------------------- /src/components/Modals/MenuDemoModal.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import '../../index.css'; 4 | import './style.css'; 5 | 6 | export default class MenuDemoModal extends Component { 7 | render() { 8 | return ( 9 |
10 |
11 |

READY TO ORDER?

12 |

Keep this tab open and switch to the previous opened tab to get an overview of the functions. When you are ready, switch back here.

13 |

14 | Users will see the menu of your restaurant through this screen. From here, they can add items, change quantities and place their order. 15 |

16 |

17 | Try resizing the window to mobile size or better yet, head to the dashboard on the other tab and scan a QR code from your own cellphone. 18 |

19 |
20 |
21 |
this.props.toggleModal()} 23 | className="btn" 24 | > 25 | GOT IT! 26 |
27 |
28 |
29 | ) 30 | } 31 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Pablo Gastelum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/Account/accountView.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import PasswordChangeForm from '../PasswordChange'; 4 | import './style.css'; 5 | 6 | const AccountView = ({ authUser, newBusinessName, setNewBusinessName, updateBusinessName }) => ( 7 |
8 |
9 |

ACCOUNT

10 |
11 |
12 |
13 |

LOGGED IN AS

14 |

{authUser.email}

15 |
16 | 17 |
18 |

CHANGE BUSINESS NAME

19 |
20 | setNewBusinessName(e.target.value)} 24 | /> 25 |
updateBusinessName(newBusinessName)} 28 | > 29 | SAVE 30 |
31 |
32 |
33 |
34 |
35 | ); 36 | 37 | export default AccountView; -------------------------------------------------------------------------------- /src/components/Account/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { compose } from 'react-recompose'; 3 | 4 | import { withFirebase } from '../Firebase'; 5 | import { AuthUserContext, withAuthorization } from '../Session'; 6 | import AccountView from './accountView'; 7 | 8 | const AccountPage = (props) => { 9 | const [newBusinessName, setNewBusinessName] = useState(''); 10 | 11 | useEffect(() => { 12 | props.firebase.user(props.firebase.getCurrentUserUid()).once('value', snapshot => { 13 | setNewBusinessName(snapshot.val().businessName); 14 | }); 15 | }, []); 16 | 17 | const updateBusinessName = (businessName) => { 18 | props.firebase.userBusinessName(props.firebase.getCurrentUserUid()).set(businessName); 19 | } 20 | 21 | return ( 22 | 23 | {authUser => ( 24 | 30 | )} 31 | 32 | ) 33 | }; 34 | 35 | const condition = authUser => !!authUser; 36 | 37 | export default compose( 38 | withAuthorization(condition), 39 | withFirebase, 40 | )(AccountPage); -------------------------------------------------------------------------------- /src/components/PasswordForget/style.css: -------------------------------------------------------------------------------- 1 | .passwordForget { 2 | height: 100vh; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .passwordForget > div:last-of-type { 8 | width: 13rem; 9 | height: 100%; 10 | display: flex; 11 | align-self: center; 12 | margin-top: 5.4rem; 13 | align-items: center; 14 | margin-left: 6.8rem; 15 | padding-top: 5.3rem; 16 | flex-direction: column; 17 | } 18 | 19 | .passwordForget > div:last-of-type > div:first-of-type { 20 | font-weight: 500; 21 | font-size: 0.9rem; 22 | text-align: center; 23 | margin-bottom: 2rem; 24 | } 25 | 26 | .passwordForget input { 27 | width: 12rem; 28 | border: none; 29 | height: 1.8rem; 30 | font-size: 0.9rem; 31 | margin-bottom: 1rem; 32 | border-radius: .3rem; 33 | padding: 1rem 0.7rem; 34 | background: #F5F5F7; 35 | } 36 | 37 | .passwordForget .btn { 38 | width: 8rem; 39 | } 40 | 41 | .passwordForget p { 42 | font-size: 0.9rem; 43 | font-weight: 500; 44 | text-align: center; 45 | margin-top: 1rem; 46 | } 47 | 48 | @media screen and (max-width: 480px) { 49 | .passwordForget > div:last-of-type { 50 | justify-content: center; 51 | margin-top: 0; 52 | margin-left: 0; 53 | padding-top: 0; 54 | } 55 | 56 | .passwordForget > div:last-of-type > div:first-of-type { 57 | margin-bottom: 4rem; 58 | } 59 | } -------------------------------------------------------------------------------- /src/components/App/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter as Router, Route } from 'react-router-dom'; 3 | import { StoreProvider } from '../../store'; 4 | 5 | import Menu from '../Menu'; 6 | import HomePage from '../Home'; 7 | import SignUpPage from '../SignUp'; 8 | import SignInPage from '../SignIn'; 9 | import AccountPage from '../Account'; 10 | import Dashboard from '../Dashboard'; 11 | import Navigation from '../Navigation'; 12 | import { withAuthentication } from '../Session'; 13 | import * as ROUTES from '../../constants/routes'; 14 | import PasswordForgetPage from '../PasswordForget'; 15 | 16 | const App = () => ( 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 | ); 32 | 33 | export default withAuthentication(App); -------------------------------------------------------------------------------- /src/components/Navigation/style.css: -------------------------------------------------------------------------------- 1 | .navBar { 2 | left: 0; 3 | height: 100%; 4 | display: flex; 5 | width: 6.8rem; 6 | color: white; 7 | position: fixed; 8 | font-weight: bold; 9 | font-size: 0.7rem; 10 | background: black; 11 | flex-direction: column; 12 | justify-content: space-between; 13 | } 14 | 15 | .navLinks { 16 | display: flex; 17 | padding-bottom: 1rem; 18 | padding-left: 1rem; 19 | flex-direction: column; 20 | justify-content: space-around; 21 | } 22 | 23 | .navLinks > * { 24 | margin-bottom: 0.5rem; 25 | } 26 | 27 | #navDash { 28 | border-bottom: 1px dashed white; 29 | width: 100%; 30 | margin-left: 0.6rem; 31 | } 32 | 33 | .navBar #logo { 34 | padding: 0; 35 | height: 5.5rem; 36 | display: flex; 37 | flex-direction: column; 38 | background: none; 39 | align-items: center; 40 | justify-content: space-evenly; 41 | padding: 1rem 0; 42 | font-size: 0.85rem; 43 | } 44 | 45 | .navBar .dashboardLinks { 46 | background: none; 47 | } 48 | 49 | .dashboardLinks div { 50 | display: flex; 51 | align-items: center; 52 | } 53 | 54 | #inactiveLink { 55 | opacity: 0.3; 56 | } 57 | 58 | #inactiveLink:hover { 59 | opacity: 1; 60 | } 61 | 62 | .bottomNav { 63 | border-top: 1px dashed white; 64 | padding-top: 1.5rem; 65 | } 66 | 67 | @media screen and (max-width: 480px) { 68 | .navBar { 69 | display: none; 70 | } 71 | } -------------------------------------------------------------------------------- /src/components/PasswordChange/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { withFirebase } from '../Firebase'; 4 | import PasswordChangeView from './passwordChangeView'; 5 | 6 | const INITIAL_STATE = { 7 | passwordOne: '', 8 | passwordTwo: '', 9 | error: null, 10 | }; 11 | 12 | class PasswordChangeForm extends Component { 13 | constructor(props) { 14 | super(props); 15 | this.state = { ...INITIAL_STATE }; 16 | } 17 | 18 | onSubmit = event => { 19 | const { passwordOne } = this.state; 20 | this.props.firebase 21 | .doPasswordUpdate(passwordOne) 22 | .then(() => { 23 | this.setState({ ...INITIAL_STATE }); 24 | }) 25 | .catch(error => { 26 | this.setState({ error }); 27 | }); 28 | 29 | event.preventDefault(); 30 | }; 31 | 32 | onChange = event => { 33 | this.setState({ [event.target.name]: event.target.value }); 34 | }; 35 | 36 | render() { 37 | const { passwordOne, passwordTwo, error } = this.state; 38 | const isInvalid = 39 | passwordOne !== passwordTwo || passwordOne === ''; 40 | 41 | return ( 42 | 50 | ); 51 | } 52 | } 53 | 54 | export default withFirebase(PasswordChangeForm); 55 | -------------------------------------------------------------------------------- /src/components/SignOut/index.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | 3 | import { Store } from '../../store'; 4 | import { withFirebase } from '../Firebase'; 5 | import * as ROUTES from '../../constants/routes'; 6 | 7 | const SignOutButton = ({ firebase, userIsAnonymous, history }) => { 8 | const { dispatch } = useContext(Store); 9 | const toggleView = view => dispatch({ type: 'TOGGLE_VIEW', payload: view }); 10 | 11 | const stopWatchingDbChanges = () => { 12 | firebase.users().off(); 13 | firebase.userOrders().off(); 14 | firebase.userMenu().off(); 15 | return Promise.resolve(); 16 | }; 17 | 18 | const deleteAnonDb = (uid) => { 19 | firebase.user(uid).remove(); 20 | firebase.userMenu(uid).remove(); 21 | firebase.userOrders(uid).remove(); 22 | return Promise.resolve(); 23 | } 24 | 25 | const handleLogout = async () => { 26 | toggleView('orders'); 27 | if(userIsAnonymous) { 28 | let anonUid = firebase.getCurrentUserUid(); 29 | stopWatchingDbChanges() 30 | .then(() => { 31 | deleteAnonDb(anonUid); 32 | }) 33 | .then(() => { 34 | history.push(ROUTES.HOME); 35 | firebase.doSignOut(); 36 | }); 37 | } else { 38 | firebase.doSignOut(); 39 | } 40 | } 41 | 42 | return ( 43 |
handleLogout()}> 44 | SIGN OUT 45 |
46 | ) 47 | }; 48 | 49 | export default withFirebase(SignOutButton); 50 | -------------------------------------------------------------------------------- /src/components/Menu/orderConfirmScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import './style.css'; 4 | 5 | const OrderConfirmScreen = ({ 6 | order, 7 | getItemCost, 8 | handleFormInput, 9 | orderDrinksIsEmpty, 10 | orderDishesIsEmpty, 11 | toggleConfirmScreen 12 | }) => ( 13 |
14 | {!orderDrinksIsEmpty && ( 15 |
16 |

Drinks

17 | {order.items.drinks.map((item, idx) => 18 |
19 |
{item.name}
20 |
21 |
x {item.qty}
22 |
${getItemCost(item.name, "drinks")} ea.
23 |
24 |
25 | )} 26 |
27 | )} 28 | {!orderDishesIsEmpty && ( 29 |
30 |

Dishes

31 | {order.items.dishes.map((item, idx) => 32 |
33 |
{item.name}
34 |
35 |
x {item.qty}
36 |
${getItemCost(item.name, "dishes")} ea.
37 |
38 |
39 | )} 40 |
41 | )} 42 |
43 |

Extra instructions or request

44 |