├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── src ├── components │ ├── __test__ │ │ ├── Home.test.js │ │ ├── Quote.test.js │ │ ├── Calculator.test.js │ │ ├── calculate.test.js │ │ ├── Navbar.test.js │ │ ├── operate.test.js │ │ └── __snapshots__ │ │ │ ├── Quote.test.js.snap │ │ │ ├── Navbar.test.js.snap │ │ │ ├── Calculator.test.js.snap │ │ │ └── Home.test.js.snap │ ├── Navbar.js │ ├── Quote.js │ ├── Home.js │ └── Calculator.js ├── index.js ├── App.js ├── logic │ ├── operate.js │ └── calculate.js └── index.css ├── .gitignore ├── package.json ├── README.md └── .github └── workflows └── linters.yml /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IbrohimRasulov/math-magicians/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IbrohimRasulov/math-magicians/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IbrohimRasulov/math-magicians/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/components/__test__/Home.test.js: -------------------------------------------------------------------------------- 1 | import renderer from 'react-test-renderer'; 2 | import Home from '../Home'; 3 | 4 | test('Render Home component', () => { 5 | const tree = renderer.create(); 6 | expect(tree).toMatchSnapshot(); 7 | }); 8 | -------------------------------------------------------------------------------- /src/components/__test__/Quote.test.js: -------------------------------------------------------------------------------- 1 | import renderer from 'react-test-renderer'; 2 | import Quote from '../Quote'; 3 | 4 | test('Render Quote component', () => { 5 | const tree = renderer.create(); 6 | expect(tree).toMatchSnapshot(); 7 | }); 8 | -------------------------------------------------------------------------------- /src/components/__test__/Calculator.test.js: -------------------------------------------------------------------------------- 1 | import renderer from 'react-test-renderer'; 2 | import Calculator from '../Calculator'; 3 | 4 | test('Render Calculator component', () => { 5 | const tree = renderer.create(); 6 | expect(tree).toMatchSnapshot(); 7 | }); 8 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root'), 11 | ); 12 | -------------------------------------------------------------------------------- /src/components/__test__/calculate.test.js: -------------------------------------------------------------------------------- 1 | import calculate from '../../logic/calculate'; 2 | 3 | it('Updates state correctly', () => { 4 | const myInitialObj = { 5 | total: 0, 6 | next: null, 7 | operation: null, 8 | }; 9 | // eslint-disable-next-line 10 | expect(calculate(myInitialObj, '4')).toEqual({ 'next': '4', 'total': null }); 11 | }); 12 | -------------------------------------------------------------------------------- /src/components/__test__/Navbar.test.js: -------------------------------------------------------------------------------- 1 | import renderer from 'react-test-renderer'; 2 | import { BrowserRouter as Router } from 'react-router-dom'; 3 | import Navbar from '../Navbar'; 4 | 5 | test('Render Navbar component', () => { 6 | const tree = renderer.create( 7 | 8 | 9 | , 10 | ); 11 | expect(tree).toMatchSnapshot(); 12 | }); 13 | -------------------------------------------------------------------------------- /src/components/Navbar.js: -------------------------------------------------------------------------------- 1 | import { Link } from 'react-router-dom'; 2 | 3 | const Navbar = () => ( 4 | 14 | ); 15 | 16 | export default Navbar; 17 | -------------------------------------------------------------------------------- /.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 | 25 | # linters 26 | .babelrc 27 | .eslintrc.json 28 | .stylelintrc.json 29 | -------------------------------------------------------------------------------- /src/components/__test__/operate.test.js: -------------------------------------------------------------------------------- 1 | import operate from '../../logic/operate'; 2 | 3 | it('Performs mathematical operations', () => { 4 | expect(operate(3, 2, '-')).toEqual('1'); 5 | expect(operate(8, 4, '%')).toEqual('0'); 6 | expect(operate(1, 5, '-')).toEqual('-4'); 7 | expect(operate(11, 9, 'x')).toEqual('99'); 8 | expect(operate(5, 0, '÷')).toEqual('Can\'t divide by 0.'); 9 | expect(operate(8, 1, '÷')).toEqual('8'); 10 | expect(operate(5, 0, '%')).toEqual('Can\'t find modulo as cannot be divided by 0.'); 11 | }); 12 | -------------------------------------------------------------------------------- /src/components/Quote.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | const Quote = () => ( 3 |
4 |
5 | Quotes 6 |

7 | Dear Math, please grow up and solve your own problems. I’m tired of solving them for you. 8 | — Anonymous 9 |

10 |

11 | If people do not believe that mathematics is simple, it is only because they do not realize how complicated life is. 12 | — John von Neumann 13 |

14 |
15 |
16 | ); 17 | 18 | export default Quote; 19 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; 3 | import Calculator from './components/Calculator'; 4 | import Navbar from './components/Navbar'; 5 | import Home from './components/Home'; 6 | import Quote from './components/Quote'; 7 | 8 | function App() { 9 | return ( 10 | 11 |
12 | 13 |
14 | 15 | } /> 16 | } /> 17 | } /> 18 | 19 |
20 |
21 |
22 | ); 23 | } 24 | 25 | export default App; 26 | -------------------------------------------------------------------------------- /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 cannot be divided by 0."; 27 | } 28 | } 29 | throw Error(`Unknown operation '${operation}'`); 30 | } 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "math-magicians", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.2", 7 | "@testing-library/user-event": "^13.5.0", 8 | "big.js": "^6.1.1", 9 | "react": "^17.0.2", 10 | "react-dom": "^17.0.2", 11 | "react-router-dom": "^6.2.1", 12 | "react-scripts": "5.0.0", 13 | "uuid": "^8.3.2", 14 | "web-vitals": "^2.1.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "browserslist": { 23 | "production": [ 24 | ">0.2%", 25 | "not dead", 26 | "not op_mini all" 27 | ], 28 | "development": [ 29 | "last 1 chrome version", 30 | "last 1 firefox version", 31 | "last 1 safari version" 32 | ] 33 | }, 34 | "devDependencies": { 35 | "@testing-library/react": "^12.1.3", 36 | "eslint": "^8.9.0", 37 | "eslint-config-airbnb": "^19.0.4", 38 | "eslint-plugin-react-hooks": "^4.3.0", 39 | "jest": "^27.5.1", 40 | "react-test-renderer": "^17.0.2" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://img.shields.io/badge/Microverse-blueviolet) 2 | 3 | # Math Magicians 4 | 5 | > "Math magicians" is a website for all fans of mathematics. It is a Single Page App (SPA) that allows users to make simple calculations and read a random math-related quote. By building this application, I learned how to use React. 6 | 7 | https://user-images.githubusercontent.com/78875455/154599179-8e67c6db-4aff-44ba-8b19-0715174b2949.mp4 8 | 9 | ## Built With 10 | 11 | - HTML 12 | - CSS 13 | - JavaScript 14 | - React, JSX 15 | 16 | ## Live Demo 17 | 18 | [live demo with Heroku](https://math-magicians-with-heroku.herokuapp.com/)
19 | [live demo with Netlify](https://621420604df7e5bdb5083bf0--goofy-archimedes-6db81d.netlify.app/) 20 | 21 | ## Authors 22 | 23 | 👤 **Ibrohim Rasulov** 24 | 25 | - GitHub: [@IbrohimRasulov](https://github.com/IbrohimRasulov) 26 | - Twitter: [@IbrohimRasu1ov](https://twitter.com/IbrohimRasu1ov) 27 | - LinkedIn: [LinkedIn](https://www.linkedin.com/in/ibrohim-rasulov-a88352209/) 28 | 29 | ## 🤝 Contributing 30 | 31 | Contributions, issues, and feature requests are welcome! 32 | 33 | Feel free to check the issues page. 34 | 35 | ## Show your support 36 | 37 | Give a ⭐️ if you like this project! 38 | 39 | ## 📝 License 40 | 41 | Copyright 2022, Ibrohim Rasulov 42 | -------------------------------------------------------------------------------- /src/components/__test__/__snapshots__/Quote.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Render Home component 1`] = ` 4 |
7 |
8 | 9 | Quotes 10 | 11 |

12 | Dear Math, please grow up and solve your own problems. I’m tired of solving them for you. 13 | 14 | — Anonymous 15 | 16 |

17 |

18 | If people do not believe that mathematics is simple, it is only because they do not realize how complicated life is. 19 | 20 | — John von Neumann 21 | 22 |

23 |
24 |
25 | `; 26 | 27 | exports[`Render Quote component 1`] = ` 28 |
31 |
32 | 33 | Quotes 34 | 35 |

36 | Dear Math, please grow up and solve your own problems. I’m tired of solving them for you. 37 | 38 | — Anonymous 39 | 40 |

41 |

42 | If people do not believe that mathematics is simple, it is only because they do not realize how complicated life is. 43 | 44 | — John von Neumann 45 | 46 |

47 |
48 |
49 | `; 50 | -------------------------------------------------------------------------------- /.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-18.04 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: "12.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 . 24 | stylelint: 25 | name: Stylelint 26 | runs-on: ubuntu-18.04 27 | steps: 28 | - uses: actions/checkout@v2 29 | - uses: actions/setup-node@v1 30 | with: 31 | node-version: "12.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 | -------------------------------------------------------------------------------- /src/components/Home.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | const Home = () => ( 3 |
4 |

Welcome to our page!

5 |

Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid qui ipsum eius laborum, adipisci earum velit possimus magnam doloribus atque eaque aperiam inventore. Nobis laudantium rerum excepturi error dignissimos in amet autem veniam, eos aperiam modi nostrum sapiente? Quisquam illo atque accusantium sapiente temporibus, vero, porro sunt hic ratione, quasi magni nobis recusandae assumenda expedita cupiditate blanditiis cumque veritatis iusto optio nemo minus! Maiores corporis illo reiciendis quis assumenda doloremque.

6 |

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ratione placeat laudantium molestiae suscipit alias exercitationem quia saepe et sed aliquid quasi ipsa ab quae rerum molestias deleniti aspernatur ipsum, minima aliquam soluta nisi quis doloribus consectetur sunt! Nisi nesciunt, assumenda mollitia iste eveniet asperiores et quia debitis illum consequatur amet? Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor, pariatur? Nesciunt, aperiam accusamus dignissimos repudiandae officiis obcaecati minus voluptatum, eveniet doloribus illo animi fuga ipsa! Suscipit repudiandae magni aliquam quidem? Lorem ipsum dolor sit amet consectetur adipisicing elit. Id impedit cum quos iusto a sequi iure doloribus veritatis, corrupti dolorum. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tenetur deleniti a quis quos eligendi nostrum incidunt aliquid laudantium, quibusdam voluptate. Voluptatem voluptates iure sapiente quod quisquam! Magni eos ex reiciendis.

7 |
8 | ); 9 | 10 | export default Home; 11 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/components/__test__/__snapshots__/Navbar.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Render Home component 1`] = ` 4 |
7 |

8 | Welcome to our page! 9 |

10 |

11 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid qui ipsum eius laborum, adipisci earum velit possimus magnam doloribus atque eaque aperiam inventore. Nobis laudantium rerum excepturi error dignissimos in amet autem veniam, eos aperiam modi nostrum sapiente? Quisquam illo atque accusantium sapiente temporibus, vero, porro sunt hic ratione, quasi magni nobis recusandae assumenda expedita cupiditate blanditiis cumque veritatis iusto optio nemo minus! Maiores corporis illo reiciendis quis assumenda doloremque. 12 |

13 |

14 | Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ratione placeat laudantium molestiae suscipit alias exercitationem quia saepe et sed aliquid quasi ipsa ab quae rerum molestias deleniti aspernatur ipsum, minima aliquam soluta nisi quis doloribus consectetur sunt! Nisi nesciunt, assumenda mollitia iste eveniet asperiores et quia debitis illum consequatur amet? Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor, pariatur? Nesciunt, aperiam accusamus dignissimos repudiandae officiis obcaecati minus voluptatum, eveniet doloribus illo animi fuga ipsa! Suscipit repudiandae magni aliquam quidem? Lorem ipsum dolor sit amet consectetur adipisicing elit. Id impedit cum quos iusto a sequi iure doloribus veritatis, corrupti dolorum. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tenetur deleniti a quis quos eligendi nostrum incidunt aliquid laudantium, quibusdam voluptate. Voluptatem voluptates iure sapiente quod quisquam! Magni eos ex reiciendis. 15 |

16 |
17 | `; 18 | 19 | exports[`Render Navbar component 1`] = ` 20 | 55 | `; 56 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&display=swap'); 2 | 3 | * { 4 | font-family: "Quicksand"; /* stylelint-disable-line font-family-no-missing-generic-family-keyword */ 5 | } 6 | 7 | .App { 8 | margin: 20px 40px; 9 | } 10 | 11 | .content { 12 | padding-top: 40px; 13 | } 14 | 15 | .content h2 { 16 | font-size: 1.7rem; 17 | margin-bottom: 30px; 18 | } 19 | 20 | /*! Calculator */ 21 | 22 | .calculator-grid { 23 | width: 320px; 24 | height: 300px; 25 | margin: 80px; 26 | display: grid; 27 | grid-template-columns: repeat(4, 1fr); 28 | grid-template-rows: repeat(6, 1fr); 29 | float: right; 30 | } 31 | 32 | .calculator-title { 33 | width: 50%; 34 | display: inline-block; 35 | } 36 | 37 | .calculator-title p { 38 | font-size: 1.2rem; 39 | line-height: 1.7; 40 | padding-top: 20px; 41 | } 42 | 43 | .output-box { 44 | background-color: #858694; 45 | grid-column: span 4; 46 | } 47 | 48 | .output-value { 49 | float: right; 50 | color: #fff; 51 | font-size: 1.5rem; 52 | line-height: 50px; 53 | padding: 0 5px; 54 | font-family: "Quicksand"; /* stylelint-disable-line font-family-no-missing-generic-family-keyword */ 55 | } 56 | 57 | .button-17 { 58 | grid-column: span 2; 59 | } 60 | 61 | .right-buttons { 62 | background-color: #f5913e; 63 | } 64 | 65 | .top-buttons { 66 | background-color: #99e599; 67 | } 68 | 69 | .central-buttons { 70 | background-color: #dddada; 71 | } 72 | 73 | .calculator-grid button { 74 | border: 1px solid #ccc; 75 | font-size: 0.9rem; 76 | cursor: pointer; 77 | outline: none; 78 | } 79 | 80 | .calculator-grid button:hover { 81 | opacity: 0.7; 82 | } 83 | 84 | /*! Navbar */ 85 | 86 | .navbar { 87 | display: flex; 88 | justify-content: space-between; 89 | align-items: center; 90 | border-bottom: 1px solid #c0c3c4; 91 | padding-bottom: 20px; 92 | } 93 | 94 | .navbar h1 { 95 | font-size: 3rem; 96 | margin: 0; 97 | } 98 | 99 | .links a { 100 | text-decoration: none; 101 | color: blue; 102 | font-size: 1.2rem; 103 | } 104 | 105 | .links a:hover { 106 | color: #f1356d; 107 | cursor: pointer; 108 | } 109 | 110 | .links span { 111 | padding: 0 10px; 112 | } 113 | 114 | /*! Home */ 115 | 116 | .home p { 117 | font-size: 1.2rem; 118 | padding-top: 20px; 119 | } 120 | 121 | /*! Quote */ 122 | 123 | .quote { 124 | width: 80%; 125 | margin: 80px auto; 126 | } 127 | 128 | .quote fieldset { 129 | padding: 0 25px; 130 | border-radius: 20px; 131 | } 132 | 133 | .quote legend { 134 | font-size: 2rem; 135 | font-weight: bolder; 136 | } 137 | 138 | .quote p { 139 | font-size: 1.4rem; 140 | padding: 20px 0; 141 | } 142 | 143 | .quote span { 144 | display: block; 145 | float: right; 146 | padding: 20px 0; 147 | font-weight: 510; 148 | } 149 | -------------------------------------------------------------------------------- /src/components/Calculator.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable max-len */ 2 | import React, { useState } from 'react'; 3 | import calculate from '../logic/calculate'; 4 | 5 | const Calculator = () => { 6 | const [state, setState] = useState({ 7 | total: 0, 8 | next: null, 9 | operation: null, 10 | }); 11 | 12 | const btnOnClick = (e) => { 13 | setState(calculate(state, e.target.textContent)); 14 | }; 15 | 16 | return ( 17 |
18 |
19 |

Let's do some math!

20 |

Using a calculator can be extremely helpful but only if you know its particular conventions. While there are different types out there many of the features are the same. Look for the number pad and the four basic operations, multiplication × addition + subtraction - and division ÷. To perform a calculation, make the necessary keystrokes and then hit =. For example, key 4 ÷ 2 =. The calculator should show the answer we expect, 2. Try some small calculations, like 2 + 3 and 4 × 5.

21 |
22 |
23 |
24 | 25 | {state.total} 26 | {state.operation} 27 | {state.next} 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 |
51 | ); 52 | }; 53 | 54 | export default Calculator; 55 | -------------------------------------------------------------------------------- /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 | total: 0, 20 | next: null, 21 | operation: null, 22 | }; 23 | } 24 | 25 | if (isNumber(buttonName)) { 26 | if (buttonName === '0' && obj.next === '0') { 27 | return {}; 28 | } 29 | // If there is an operation, update next 30 | if (obj.operation) { 31 | if (obj.next) { 32 | return { ...obj, next: obj.next + buttonName }; 33 | } 34 | return { ...obj, next: buttonName }; 35 | } 36 | // If there is no operation, update next and clear the value 37 | if (obj.next) { 38 | return { 39 | next: obj.next + buttonName, 40 | total: null, 41 | }; 42 | } 43 | return { 44 | next: buttonName, 45 | total: null, 46 | }; 47 | } 48 | 49 | if (buttonName === '.') { 50 | if (obj.next) { 51 | if (obj.next.includes('.')) { 52 | return { ...obj }; 53 | } 54 | return { ...obj, next: `${obj.next}.` }; 55 | } 56 | if (obj.operation) { 57 | return { next: '0.' }; 58 | } 59 | if (obj.total) { 60 | if (obj.total.includes('.')) { 61 | return {}; 62 | } 63 | return { total: `${obj.total}.` }; 64 | } 65 | return { total: '0.' }; 66 | } 67 | 68 | if (buttonName === '=') { 69 | if (obj.next && obj.operation) { 70 | return { 71 | total: operate(obj.total, obj.next, obj.operation), 72 | next: null, 73 | operation: null, 74 | }; 75 | } 76 | // '=' with no operation, nothing to do 77 | return {}; 78 | } 79 | 80 | if (buttonName === '+/-') { 81 | if (obj.next) { 82 | return { ...obj, next: (-1 * parseFloat(obj.next)).toString() }; 83 | } 84 | if (obj.total) { 85 | return { ...obj, total: (-1 * parseFloat(obj.total)).toString() }; 86 | } 87 | return {}; 88 | } 89 | 90 | // Button must be an operation 91 | 92 | // When the user presses an operation button without having entered 93 | // a number first, do nothing. 94 | // if (!obj.next && !obj.total) { 95 | // return {}; 96 | // } 97 | 98 | // User pressed an operation after pressing '=' 99 | if (!obj.next && obj.total && !obj.operation) { 100 | return { ...obj, operation: buttonName }; 101 | } 102 | 103 | // User pressed an operation button and there is an existing operation 104 | if (obj.operation) { 105 | if (obj.total && !obj.next) { 106 | return { ...obj, operation: buttonName }; 107 | } 108 | 109 | return { 110 | total: operate(obj.total, obj.next, obj.operation), 111 | next: null, 112 | operation: buttonName, 113 | }; 114 | } 115 | 116 | // no operation yet, but the user typed one 117 | 118 | // The user hasn't typed a number yet, just save the operation 119 | if (!obj.next) { 120 | return { operation: buttonName }; 121 | } 122 | 123 | // save the operation and shift 'next' into 'total' 124 | return { 125 | total: obj.next, 126 | next: null, 127 | operation: buttonName, 128 | }; 129 | } 130 | -------------------------------------------------------------------------------- /src/components/__test__/__snapshots__/Calculator.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Render Calculator component 1`] = ` 4 |
7 |
10 |

11 | Let's do some math! 12 |

13 |

14 | Using a calculator can be extremely helpful but only if you know its particular conventions. While there are different types out there many of the features are the same. Look for the number pad and the four basic operations, multiplication × addition + subtraction - and division ÷. To perform a calculation, make the necessary keystrokes and then hit =. For example, key 4 ÷ 2 =. The calculator should show the answer we expect, 2. Try some small calculations, like 2 + 3 and 4 × 5. 15 |

16 |
17 |
20 |
23 | 26 | 0 27 | 28 |
29 | 36 | 43 | 50 | 57 | 64 | 71 | 78 | 85 | 92 | 99 | 106 | 113 | 120 | 127 | 134 | 141 | 148 | 155 | 162 |
163 |
164 | `; 165 | -------------------------------------------------------------------------------- /src/components/__test__/__snapshots__/Home.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Render Home component 1`] = ` 4 |
7 |

8 | Welcome to our page! 9 |

10 |

11 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid qui ipsum eius laborum, adipisci earum velit possimus magnam doloribus atque eaque aperiam inventore. Nobis laudantium rerum excepturi error dignissimos in amet autem veniam, eos aperiam modi nostrum sapiente? Quisquam illo atque accusantium sapiente temporibus, vero, porro sunt hic ratione, quasi magni nobis recusandae assumenda expedita cupiditate blanditiis cumque veritatis iusto optio nemo minus! Maiores corporis illo reiciendis quis assumenda doloremque. 12 |

13 |

14 | Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ratione placeat laudantium molestiae suscipit alias exercitationem quia saepe et sed aliquid quasi ipsa ab quae rerum molestias deleniti aspernatur ipsum, minima aliquam soluta nisi quis doloribus consectetur sunt! Nisi nesciunt, assumenda mollitia iste eveniet asperiores et quia debitis illum consequatur amet? Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor, pariatur? Nesciunt, aperiam accusamus dignissimos repudiandae officiis obcaecati minus voluptatum, eveniet doloribus illo animi fuga ipsa! Suscipit repudiandae magni aliquam quidem? Lorem ipsum dolor sit amet consectetur adipisicing elit. Id impedit cum quos iusto a sequi iure doloribus veritatis, corrupti dolorum. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tenetur deleniti a quis quos eligendi nostrum incidunt aliquid laudantium, quibusdam voluptate. Voluptatem voluptates iure sapiente quod quisquam! Magni eos ex reiciendis. 15 |

16 |
17 | `; 18 | 19 | exports[`Render component 1`] = ` 20 |
23 |

24 | Welcome to our page! 25 |

26 |

27 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid qui ipsum eius laborum, adipisci earum velit possimus magnam doloribus atque eaque aperiam inventore. Nobis laudantium rerum excepturi error dignissimos in amet autem veniam, eos aperiam modi nostrum sapiente? Quisquam illo atque accusantium sapiente temporibus, vero, porro sunt hic ratione, quasi magni nobis recusandae assumenda expedita cupiditate blanditiis cumque veritatis iusto optio nemo minus! Maiores corporis illo reiciendis quis assumenda doloremque. 28 |

29 |

30 | Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ratione placeat laudantium molestiae suscipit alias exercitationem quia saepe et sed aliquid quasi ipsa ab quae rerum molestias deleniti aspernatur ipsum, minima aliquam soluta nisi quis doloribus consectetur sunt! Nisi nesciunt, assumenda mollitia iste eveniet asperiores et quia debitis illum consequatur amet? Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor, pariatur? Nesciunt, aperiam accusamus dignissimos repudiandae officiis obcaecati minus voluptatum, eveniet doloribus illo animi fuga ipsa! Suscipit repudiandae magni aliquam quidem? Lorem ipsum dolor sit amet consectetur adipisicing elit. Id impedit cum quos iusto a sequi iure doloribus veritatis, corrupti dolorum. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tenetur deleniti a quis quos eligendi nostrum incidunt aliquid laudantium, quibusdam voluptate. Voluptatem voluptates iure sapiente quod quisquam! Magni eos ex reiciendis. 31 |

32 |
33 | `; 34 | 35 | exports[`Render components 1`] = ` 36 |
39 |

40 | Welcome to our page! 41 |

42 |

43 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid qui ipsum eius laborum, adipisci earum velit possimus magnam doloribus atque eaque aperiam inventore. Nobis laudantium rerum excepturi error dignissimos in amet autem veniam, eos aperiam modi nostrum sapiente? Quisquam illo atque accusantium sapiente temporibus, vero, porro sunt hic ratione, quasi magni nobis recusandae assumenda expedita cupiditate blanditiis cumque veritatis iusto optio nemo minus! Maiores corporis illo reiciendis quis assumenda doloremque. 44 |

45 |

46 | Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ratione placeat laudantium molestiae suscipit alias exercitationem quia saepe et sed aliquid quasi ipsa ab quae rerum molestias deleniti aspernatur ipsum, minima aliquam soluta nisi quis doloribus consectetur sunt! Nisi nesciunt, assumenda mollitia iste eveniet asperiores et quia debitis illum consequatur amet? Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor, pariatur? Nesciunt, aperiam accusamus dignissimos repudiandae officiis obcaecati minus voluptatum, eveniet doloribus illo animi fuga ipsa! Suscipit repudiandae magni aliquam quidem? Lorem ipsum dolor sit amet consectetur adipisicing elit. Id impedit cum quos iusto a sequi iure doloribus veritatis, corrupti dolorum. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tenetur deleniti a quis quos eligendi nostrum incidunt aliquid laudantium, quibusdam voluptate. Voluptatem voluptates iure sapiente quod quisquam! Magni eos ex reiciendis. 47 |

48 |
49 | `; 50 | --------------------------------------------------------------------------------