├── .babelrc ├── .eslintrc.json ├── .github └── workflows │ └── linters.yml ├── .gitignore ├── .stylelintrc.json ├── LICENSE ├── README.md ├── murple_logo.png ├── package-lock.json ├── package.json ├── public ├── assets │ └── bg.jpg ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── App.css ├── App.jsx ├── assets └── bg.jpg ├── components ├── Buttons.css ├── Buttons.js ├── Calculator.css ├── Calculator.js ├── navBar.css ├── navBar.js ├── quote.css └── quote.js ├── index.css ├── index.js ├── logic ├── calculate.js └── operate.js └── routes ├── calcuatorPage.css ├── calculatorPage.js ├── homePage.css ├── homePage.js ├── quotePage.css └── quotePage.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-react" 4 | ], 5 | "plugins": ["@babel/plugin-syntax-jsx"] 6 | } -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "jest": true 6 | }, 7 | "parser": "@babel/eslint-parser", 8 | "parserOptions": { 9 | "ecmaFeatures": { 10 | "jsx": true 11 | }, 12 | "ecmaVersion": 2018, 13 | "sourceType": "module" 14 | }, 15 | "extends": ["airbnb", "plugin:react/recommended", "plugin:react-hooks/recommended"], 16 | "plugins": ["react"], 17 | "rules": { 18 | "react/jsx-filename-extension": ["warn", { "extensions": [".js", ".jsx"] }], 19 | "react/react-in-jsx-scope": "off", 20 | "import/no-unresolved": "off", 21 | "no-shadow": "off" 22 | }, 23 | "overrides": [ 24 | { 25 | // feel free to replace with your preferred file pattern - eg. 'src/**/*Slice.js' or 'redux/**/*Slice.js' 26 | "files": ["src/**/*Slice.js"], 27 | // avoid state param assignment 28 | "rules": { "no-param-reassign": ["error", { "props": false }] } 29 | } 30 | ], 31 | "ignorePatterns": [ 32 | "dist/", 33 | "build/" 34 | ] 35 | } -------------------------------------------------------------------------------- /.github/workflows/linters.yml: -------------------------------------------------------------------------------- 1 | name: Linters 2 | 3 | on: pull_request 4 | 5 | env: 6 | FORCE_COLOR: 1 7 | 8 | jobs: 9 | eslint: 10 | name: ESLint 11 | runs-on: ubuntu-22.04 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: "18.x" 17 | - name: Setup ESLint 18 | run: | 19 | npm install --save-dev eslint@7.x eslint-config-airbnb@18.x eslint-plugin-import@2.x eslint-plugin-jsx-a11y@6.x eslint-plugin-react@7.x eslint-plugin-react-hooks@4.x @babel/eslint-parser@7.x @babel/core@7.x @babel/plugin-syntax-jsx@7.x @babel/preset-env@7.x @babel/preset-react@7.x 20 | [ -f .eslintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.eslintrc.json 21 | [ -f .babelrc ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.babelrc 22 | - name: ESLint Report 23 | run: npx eslint "**/*.{js,jsx}" 24 | stylelint: 25 | name: Stylelint 26 | runs-on: ubuntu-22.04 27 | steps: 28 | - uses: actions/checkout@v3 29 | - uses: actions/setup-node@v3 30 | with: 31 | node-version: "18.x" 32 | - name: Setup Stylelint 33 | run: | 34 | npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x 35 | [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.stylelintrc.json 36 | - name: Stylelint Report 37 | run: npx stylelint "**/*.{css,scss}" 38 | nodechecker: 39 | name: node_modules checker 40 | runs-on: ubuntu-22.04 41 | steps: 42 | - uses: actions/checkout@v3 43 | - name: Check node_modules existence 44 | run: | 45 | if [ -d "node_modules/" ]; then echo -e "\e[1;31mThe node_modules/ folder was pushed to the repo. Please remove it from the GitHub repository and try again."; echo -e "\e[1;32mYou can set up a .gitignore file with this folder included on it to prevent this from happening in the future." && exit 1; fi -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-standard"], 3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"], 4 | "rules": { 5 | "at-rule-no-unknown": [ 6 | true, 7 | { 8 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"] 9 | } 10 | ], 11 | "scss/at-rule-no-unknown": [ 12 | true, 13 | { 14 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"] 15 | } 16 | ], 17 | "csstree/validator": true 18 | }, 19 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css", "**/*.js", "**/*.jsx"] 20 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021, Andres Zamorano Medina 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this Hello Microverse! and associated documentation files, to deal in the Hello Microverse! without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Hello Microverse!, and to permit persons to whom the Hello Microverse! is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Hello Microverse!. 6 | 7 | THE Hello Microverse! IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE Hello Microverse! OR THE USE OR OTHER DEALINGS IN THE Hello Microverse!. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | logo 5 |
6 | 7 |

Math Magicians project.

8 | 9 |
10 | 11 | 12 | 13 | # 📗 Table of Contents 14 | 15 | - [📖 About the Project](#about-project) 16 | - [🛠 Built With](#built-with) 17 | - [Tech Stack](#tech-stack) 18 | - [Key Features](#key-features) 19 | - [🚀 Live Demo](#live-demo) 20 | - [💻 Getting Started](#getting-started) 21 | - [Prerequisites](#prerequisites) 22 | - [Setup](#setup) 23 | - [Install](#install) 24 | - [Usage](#usage) 25 | - [Run tests](#run-tests) 26 | - [Deployment](#deployment) 27 | - [👥 Authors](#authors) 28 | - [🔭 Future Features](#future-features) 29 | - [🤝 Contributing](#contributing) 30 | - [⭐️ Show your support](#support) 31 | - [🙏 Acknowledgements](#acknowledgements) 32 | - [❓ FAQ (OPTIONAL)](#faq) 33 | - [📝 License](#license) 34 | 35 | 36 | 37 | # 📖 [Math Magicians] 38 | 39 | **[Math magicians]** is a website for all fans of mathematics. It is a Single Page App (SPA) 40 | 41 | ## 🛠 Built With 42 | 43 | ### Tech Stack 44 | 45 |
46 | Client 47 | 50 |
51 | 52 |
53 | Linters 54 | 57 |
58 | 59 | 60 | 61 | ### Key Features 62 | 63 | - **[Use of React.js]** 64 | - **[Use motivational quotes]** 65 | - **[Use of route to SPA]** 66 | 67 |

(back to top)

68 | 69 | 70 | 71 | 78 | 79 | 80 | 81 | ## 💻 Getting Started 82 | 83 | To get a local copy up and running, follow these steps. 84 | 85 | ### Prerequisites 86 | 87 | You need a updated browser 88 | 89 | ### Setup 90 | 91 | Clone this repository to your desired folder: 92 | 93 | sh 94 | cd my-folder 95 | git clone https://github.com/Dachrono/MathMagicians.git 96 | 97 | ### Install 98 | 99 | Install this project with: 100 | 101 | sh 102 | cd my-project 103 | npm init -y 104 | 105 | ### Usage 106 | 107 | To run the project, execute the following command: 108 | 109 | sh 110 | npm start 111 | 112 | ### Run tests 113 | 114 | To run tests, run the following command: 115 | 116 | sh 117 | npm test 118 | 119 | 122 | 123 |

(back to top)

124 | 125 | 126 | 127 | ## 👥 Authors 128 | 129 | 👤 **Andy Zam** 130 | 131 | - GitHub: [Andres Zamorano](https://github.com/Dachrono) 132 | - Twitter: [Andres Zamorano](https://twitter.com/Dachrono) 133 | - LinkedIn: [Andres Zamorano](https://www.linkedin.com/in/andres-zamorano-785b77a1/) 134 | 135 |

(back to top)

136 | 137 | 138 | 139 | ## 🔭 Future Features 140 | 141 | - [1] **[Create support pages]** 142 | - [2] **[Create calculator]** 143 | 144 |

(back to top)

145 | 146 | ## 🤝 Contributing 147 | 148 | Contributions, issues, and feature requests are welcome! 149 | 150 | Feel free to check the [issues page](https://github.com/Dachrono/MathMagicians/issues). 151 | 152 |

(back to top)

153 | 154 | 155 | 156 | ## ⭐️ Show your support 157 | 158 | If you like this project please feel fre to send me corrections for make it better I would feel glad to read your comments 159 | 160 |

(back to top)

161 | 162 | 163 | 164 | ## 🙏 Acknowledgments 165 | 166 | 167 | 168 |

(back to top)

169 | 170 | ## ❓ FAQ (OPTIONAL) 171 | 172 | 173 | - **[Can I use with a templeate your project?]** 174 | 175 | - [Of course I would feel honored] 176 | 177 | - **[Your project is free license?]** 178 | 179 | - [Yeah, you can use it completly] 180 | 181 |

(back to top)

182 | 183 | 184 | 185 | ## 📝 License 186 | 187 | this project is [MIT](./LICENSE) licensed. 188 | 189 |

(back to top)

-------------------------------------------------------------------------------- /murple_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dachrono/MathMagicians/51fa84b1b418d6b922e64f37ea88548f24ee483d/murple_logo.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "math", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "big.js": "^6.2.1", 10 | "prop-types": "^15.8.1", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-router-dom": "^6.14.1", 14 | "react-scripts": "5.0.1", 15 | "web-vitals": "^2.1.4" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test", 21 | "eject": "react-scripts eject" 22 | }, 23 | "eslintConfig": { 24 | "extends": [ 25 | "react-app", 26 | "react-app/jest" 27 | ] 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.2%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | }, 41 | "devDependencies": { 42 | "@babel/core": "^7.22.5", 43 | "@babel/eslint-parser": "^7.22.5", 44 | "@babel/plugin-syntax-jsx": "^7.22.5", 45 | "@babel/preset-react": "^7.22.5", 46 | "eslint": "^7.32.0", 47 | "eslint-config-airbnb": "^18.2.1", 48 | "eslint-plugin-import": "^2.27.5", 49 | "eslint-plugin-jsx-a11y": "^6.7.1", 50 | "eslint-plugin-react": "^7.32.2", 51 | "eslint-plugin-react-hooks": "^4.6.0", 52 | "stylelint": "^13.13.1", 53 | "stylelint-config-standard": "^21.0.0", 54 | "stylelint-csstree-validator": "^1.9.0", 55 | "stylelint-scss": "^3.21.0" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /public/assets/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dachrono/MathMagicians/51fa84b1b418d6b922e64f37ea88548f24ee483d/public/assets/bg.jpg -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dachrono/MathMagicians/51fa84b1b418d6b922e64f37ea88548f24ee483d/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dachrono/MathMagicians/51fa84b1b418d6b922e64f37ea88548f24ee483d/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dachrono/MathMagicians/51fa84b1b418d6b922e64f37ea88548f24ee483d/public/logo512.png -------------------------------------------------------------------------------- /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 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: center; 5 | align-items: center; 6 | background-color: #fff; 7 | } 8 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import Calculator from './components/Calculator'; 3 | import Quote from './components/quote'; 4 | 5 | function App() { 6 | return ( 7 |
8 | 9 | 10 |
11 | ); 12 | } 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /src/assets/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dachrono/MathMagicians/51fa84b1b418d6b922e64f37ea88548f24ee483d/src/assets/bg.jpg -------------------------------------------------------------------------------- /src/components/Buttons.css: -------------------------------------------------------------------------------- 1 | .panel { 2 | display: grid; 3 | grid-template-columns: 1fr 1fr 1fr 1fr; 4 | grid-template-rows: 50px 50px 50px 50px 50px; 5 | } 6 | 7 | .btn { 8 | all: initial; 9 | cursor: pointer; 10 | display: flex; 11 | align-items: center; 12 | justify-content: center; 13 | background-color: #dcdcdc; 14 | border: 0.5px solid #808080; 15 | } 16 | 17 | #div, 18 | #mul, 19 | #sum, 20 | #res, 21 | #equal { 22 | background-color: orange; 23 | } 24 | 25 | #zero { 26 | grid-column: span 2; 27 | } 28 | -------------------------------------------------------------------------------- /src/components/Buttons.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import './Buttons.css'; 3 | 4 | function Buttons({ handleClick }) { 5 | return ( 6 | <> 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | ); 30 | } 31 | 32 | Buttons.propTypes = { 33 | handleClick: PropTypes.func.isRequired, 34 | }; 35 | 36 | export default Buttons; 37 | -------------------------------------------------------------------------------- /src/components/Calculator.css: -------------------------------------------------------------------------------- 1 | .calc { 2 | width: 50%; 3 | margin: 15px 0; 4 | display: flex; 5 | flex-direction: column; 6 | background-color: #808080; 7 | } 8 | 9 | .result { 10 | margin: 5px 0; 11 | padding: 10px 5px; 12 | display: flex; 13 | justify-content: flex-end; 14 | color: #fff; 15 | font-size: 30px; 16 | background-color: #808080; 17 | } 18 | -------------------------------------------------------------------------------- /src/components/Calculator.js: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import './Calculator.css'; 3 | import Buttons from './Buttons'; 4 | import calculate from '../logic/calculate'; 5 | 6 | function Calculator() { 7 | const [calcRes, setOper] = useState({}); 8 | const handleClick = (butName) => { 9 | const result = calculate(calcRes, butName); 10 | setOper(result); 11 | }; 12 | 13 | return ( 14 |
15 |
16 | 17 | { (JSON.stringify(calcRes) === '{}') ? '0' : null } 18 | {calcRes.total || ''} 19 | {calcRes.operation || ''} 20 | {calcRes.next || ''} 21 | 22 | 23 |
24 | 25 |
26 | ); 27 | } 28 | 29 | export default Calculator; 30 | -------------------------------------------------------------------------------- /src/components/navBar.css: -------------------------------------------------------------------------------- 1 | .NavBar { 2 | width: 100%; 3 | display: flex; 4 | justify-content: space-between; 5 | } 6 | 7 | .navTitle { 8 | margin: 0; 9 | padding: 0 0 0 20px; 10 | } 11 | 12 | .navItems { 13 | margin: 0; 14 | padding: 0 20px 0 0; 15 | list-style: none; 16 | display: flex; 17 | align-items: center; 18 | gap: 10px; 19 | } 20 | -------------------------------------------------------------------------------- /src/components/navBar.js: -------------------------------------------------------------------------------- 1 | import './navBar.css'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | function NavBar() { 5 | return ( 6 | <> 7 |
8 |

Math Magicians

9 | 16 |
17 | 18 | ); 19 | } 20 | 21 | export default NavBar; 22 | -------------------------------------------------------------------------------- /src/components/quote.css: -------------------------------------------------------------------------------- 1 | .quote { 2 | width: 75%; 3 | margin: 15px 0; 4 | display: flex; 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /src/components/quote.js: -------------------------------------------------------------------------------- 1 | import './quote.css'; 2 | import { useEffect, useState } from 'react'; 3 | 4 | function Quote() { 5 | const [quote, setQuote] = useState({}); 6 | const [isLoaded, setIsLoaded] = useState(true); 7 | const [error, setError] = useState(false); 8 | 9 | const getQuote = async () => { 10 | const header = { 11 | 'X-Api-Key': 'Vm6ia/wNgoTh9/qxQLj/Gg==BwWcWYV2d97bnWwv', 12 | 'Content-type': 'application/json', 13 | }; 14 | 15 | try { 16 | const response = await fetch('https://api.api-ninjas.com/v1/quotes?category=fear', { headers: header }); 17 | const data = await response.json(); 18 | setQuote(data); 19 | setIsLoaded(false); 20 | } catch { 21 | setError(true); 22 | setIsLoaded(false); 23 | } 24 | }; 25 | 26 | useEffect(() => { 27 | getQuote(); 28 | }, []); 29 | 30 | if (isLoaded) { 31 | return
Loading...
; 32 | } 33 | 34 | if (error) { 35 | return
Error
; 36 | } 37 | 38 | return ( 39 |
40 |

41 | {quote[0]?.quote} 42 | {' - - '} 43 | {quote[0]?.author} 44 | {' - - '} 45 |

46 |
47 | ); 48 | } 49 | 50 | export default Quote; 51 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | background-image: url('./assets/bg.jpg'); 5 | font-family: 6 | -apple-system, 7 | BlinkMacSystemFont, 8 | 'Segoe UI', 9 | 'Roboto', 10 | 'Oxygen', 11 | 'Ubuntu', 12 | 'Cantarell', 13 | 'Fira Sans', 14 | 'Droid Sans', 15 | 'Helvetica Neue', 16 | sans-serif; 17 | -webkit-font-smoothing: antialiased; 18 | -moz-osx-font-smoothing: grayscale; 19 | } 20 | 21 | code { 22 | font-family: 23 | source-code-pro, 24 | Menlo, 25 | Monaco, 26 | Consolas, 27 | 'Courier New', 28 | monospace; 29 | } 30 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import { createBrowserRouter, RouterProvider } from 'react-router-dom'; 4 | import './index.css'; 5 | import HomePage from './routes/homePage'; 6 | import CalculatorPage from './routes/calculatorPage'; 7 | import QuotePage from './routes/quotePage'; 8 | 9 | const router = createBrowserRouter([ 10 | { 11 | path: '/', 12 | element: , 13 | errorElement:
404
, 14 | }, 15 | { 16 | path: '/calculator', 17 | element: , 18 | }, 19 | { 20 | path: '/quote', 21 | element: , 22 | }, 23 | ]); 24 | 25 | const root = ReactDOM.createRoot(document.getElementById('root')); 26 | root.render( 27 | 28 | 29 | , 30 | ); 31 | -------------------------------------------------------------------------------- /src/logic/calculate.js: -------------------------------------------------------------------------------- 1 | import operate from './operate'; 2 | 3 | function isNumber(item) { 4 | return !!item.match(/[0-9]+/); 5 | } 6 | 7 | /** 8 | * Given a button name and a calculator data object, return an updated 9 | * calculator data object. 10 | * 11 | * Calculator data object contains: 12 | * total:s the running total 13 | * next:String the next number to be operated on with the total 14 | * operation:String +, -, etc. 15 | */ 16 | export default function calculate(obj, buttonName) { 17 | if (buttonName === 'AC') { 18 | return { 19 | 20 | }; 21 | } 22 | 23 | if (isNumber(buttonName)) { 24 | if (buttonName === '0' && obj.next === '0') { 25 | return {}; 26 | } 27 | // If there is an operation, update next 28 | if (obj.operation) { 29 | if (obj.next && obj.next !== '0') { 30 | return { ...obj, next: obj.next + buttonName }; 31 | } 32 | return { ...obj, next: buttonName }; 33 | } 34 | // If there is no operation, update next and clear the value 35 | if (obj.next && obj.next !== '0') { 36 | return { 37 | next: obj.next + buttonName, 38 | total: null, 39 | }; 40 | } 41 | return { 42 | next: buttonName, 43 | total: null, 44 | }; 45 | } 46 | 47 | if (buttonName === '.') { 48 | if (obj.next) { 49 | if (obj.next.includes('.')) { 50 | return { ...obj }; 51 | } 52 | return { ...obj, next: `${obj.next}.` }; 53 | } 54 | if (obj.operation) { 55 | return { ...obj, next: '0.' }; 56 | } 57 | if (obj.total) { 58 | if (obj.total.includes('.')) { 59 | return {}; 60 | } 61 | return { ...obj, next: `${obj.total}.` }; 62 | } 63 | return { ...obj, next: '0.' }; 64 | } 65 | 66 | if (buttonName === '=') { 67 | if (obj.next && obj.operation) { 68 | return { 69 | total: operate(obj.total, obj.next, obj.operation), 70 | next: null, 71 | operation: null, 72 | }; 73 | } 74 | // '=' with no operation, nothing to do 75 | return {}; 76 | } 77 | 78 | if (buttonName === '+/-') { 79 | if (obj.next) { 80 | return { ...obj, next: (-1 * parseFloat(obj.next)).toString() }; 81 | } 82 | if (obj.total) { 83 | return { ...obj, total: (-1 * parseFloat(obj.total)).toString() }; 84 | } 85 | return {}; 86 | } 87 | 88 | // Button must be an operation 89 | 90 | // When the user presses an operation button without having entered 91 | // a number first, do nothing. 92 | // if (!obj.next && !obj.total) { 93 | // return {}; 94 | // } 95 | 96 | // User pressed an operation after pressing '=' 97 | if (!obj.next && obj.total && !obj.operation) { 98 | return { ...obj, operation: buttonName }; 99 | } 100 | 101 | // User pressed an operation button and there is an existing operation 102 | if (obj.operation) { 103 | if (obj.total && !obj.next) { 104 | return { ...obj, operation: buttonName }; 105 | } 106 | 107 | if (!obj.total) { 108 | return { total: 0, operation: buttonName }; 109 | } 110 | 111 | return { 112 | total: operate(obj.total, obj.next, obj.operation), 113 | next: null, 114 | operation: buttonName, 115 | }; 116 | } 117 | 118 | // no operation yet, but the user typed one 119 | 120 | // The user hasn't typed a number yet, just save the operation 121 | if (!obj.next) { 122 | return { operation: buttonName }; 123 | } 124 | 125 | // save the operation and shift 'next' into 'total' 126 | return { 127 | total: obj.next, 128 | next: null, 129 | operation: buttonName, 130 | }; 131 | } 132 | -------------------------------------------------------------------------------- /src/logic/operate.js: -------------------------------------------------------------------------------- 1 | import Big from 'big.js'; 2 | 3 | export default function operate(numberOne, numberTwo, operation) { 4 | const one = Big(numberOne); 5 | const two = Big(numberTwo); 6 | if (operation === '+') { 7 | return one.plus(two).toString(); 8 | } 9 | if (operation === '-') { 10 | return one.minus(two).toString(); 11 | } 12 | if (operation === 'x') { 13 | return one.times(two).toString(); 14 | } 15 | if (operation === '÷') { 16 | try { 17 | return one.div(two).toString(); 18 | } catch (err) { 19 | return "Can't divide by 0."; 20 | } 21 | } 22 | if (operation === '%') { 23 | try { 24 | return one.mod(two).toString(); 25 | } catch (err) { 26 | return "Can't find modulo as can't divide by 0."; 27 | } 28 | } 29 | throw Error(`Unknown operation '${operation}'`); 30 | } 31 | -------------------------------------------------------------------------------- /src/routes/calcuatorPage.css: -------------------------------------------------------------------------------- 1 | .containerCalculator { 2 | height: 100vh; 3 | background-color: #ffffffe6; 4 | } 5 | 6 | .itemsCalc { 7 | padding: 0 20px; 8 | display: flex; 9 | justify-content: space-between; 10 | gap: 50px; 11 | } 12 | -------------------------------------------------------------------------------- /src/routes/calculatorPage.js: -------------------------------------------------------------------------------- 1 | import './calcuatorPage.css'; 2 | import NavBar from '../components/navBar'; 3 | import Calculator from '../components/Calculator'; 4 | 5 | function CalculatorPage() { 6 | return ( 7 |
8 | 9 |
10 |

Lets do some math!

11 | 12 |
13 |
14 | ); 15 | } 16 | 17 | export default CalculatorPage; 18 | -------------------------------------------------------------------------------- /src/routes/homePage.css: -------------------------------------------------------------------------------- 1 | .containerHome { 2 | height: 100vh; 3 | background-color: #ffffffe6; 4 | } 5 | 6 | .titleHome { 7 | padding: 20px; 8 | } 9 | 10 | .pharHome { 11 | padding: 20px; 12 | text-align: justify; 13 | } 14 | -------------------------------------------------------------------------------- /src/routes/homePage.js: -------------------------------------------------------------------------------- 1 | import './homePage.css'; 2 | import NavBar from '../components/navBar'; 3 | 4 | function HomePage() { 5 | return ( 6 |
7 | 8 |

Welcome to our page

9 |

10 | Lorem ipsum dolor sit amet consectetur, adipisicing elit. 11 | Inventore, porro provident dignissimos 12 | incidunt delectus sequi iste minus rem exercitationem 13 | debitis, laudantium molestias modi deleniti? 14 | Inventore eum qui quidem necessitatibus cum? 15 | Lorem ipsum dolor sit amet consectetur, adipisicing elit. 16 | Inventore, porro provident dignissimos 17 | incidunt delectus sequi iste minus rem exercitationem 18 | debitis, laudantium molestias modi deleniti? 19 | Inventore eum qui quidem necessitatibus cum? 20 |
21 |
22 | Lorem ipsum dolor sit amet consectetur, adipisicing elit. 23 | Inventore, porro provident dignissimos 24 | incidunt delectus sequi iste minus rem exercitationem 25 | debitis, laudantium molestias modi deleniti? 26 | Inventore eum qui quidem necessitatibus cum? 27 | Lorem ipsum dolor sit amet consectetur, adipisicing elit. 28 | Inventore, porro provident dignissimos 29 | incidunt delectus sequi iste minus rem exercitationem 30 | debitis, laudantium molestias modi deleniti? 31 | Inventore eum qui quidem necessitatibus cum? 32 |

33 |
34 | ); 35 | } 36 | 37 | export default HomePage; 38 | -------------------------------------------------------------------------------- /src/routes/quotePage.css: -------------------------------------------------------------------------------- 1 | .containerQuote { 2 | height: 100vh; 3 | background-color: #ffffffe6; 4 | } 5 | 6 | .itemsQuote { 7 | padding: 50px 20px; 8 | display: flex; 9 | justify-content: center; 10 | gap: 50px; 11 | } 12 | -------------------------------------------------------------------------------- /src/routes/quotePage.js: -------------------------------------------------------------------------------- 1 | import './quotePage.css'; 2 | import NavBar from '../components/navBar'; 3 | import Quote from '../components/quote'; 4 | 5 | function QuotePage() { 6 | return ( 7 |
8 | 9 |
10 | 11 |
12 |
13 | ); 14 | } 15 | 16 | export default QuotePage; 17 | --------------------------------------------------------------------------------