├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo.png ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── App.js ├── App.test.js ├── assets ├── images │ └── dummy.png └── styles │ └── App.css ├── components └── Button.js ├── index.css ├── index.js ├── logo.svg ├── serviceWorker.js ├── setupTests.js └── views └── AppView.js /.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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Simple React Calculator 2 | A Calculator Using React JS - https://maniruzzamanakash.github.io/react-calculator/ 3 | 4 | ## Demo Look 5 | 6 | ##### Live Link: https://maniruzzamanakash.github.io/react-calculator/ 7 | 8 | ![A Calculator Using React JS][calculator-screenshot] 9 | 10 | [calculator-screenshot]: https://i.ibb.co/qrGc5vM/demo-look.png "A Calculator Using React JS" 11 | 12 | 13 | ## Live Test of React js Simple Calculator 14 | https://maniruzzamanakash.github.io/react-calculator 15 | 16 | ## Demo Look In Operation 17 | 18 | ![A Calculator Using React JS][calculator-screenshot2] 19 | 20 | [calculator-screenshot2]: https://i.ibb.co/ysCCRkX/demo-look-result.png "A Calculator Using React JS" 21 | 22 | 23 | ## Start With This Calculator 24 | 25 | 1) First Clone this project: 26 | 27 | ### `git clone https://github.com/ManiruzzamanAkash/react-calculator.git` 28 | 29 | 2) Install node modules: 30 | 31 | ### `npm install` 32 | 33 | 3) Run this project in browser 34 | 35 | ### `npm start` 36 | 37 | 4) Build And Run this project in browser 38 | 39 | ### `npm run build` 40 | 41 | To Get More Help to start with React Go - [Create React App](https://github.com/facebook/create-react-app). 42 | 43 | 44 | ## Learn More 45 | 46 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 47 | 48 | To learn React, check out the [React documentation](https://reactjs.org/). 49 | 50 | ### Code Splitting 51 | 52 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting 53 | 54 | ### Analyzing the Bundle Size 55 | 56 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size 57 | 58 | ### Making a Progressive Web App 59 | 60 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app 61 | 62 | ### Advanced Configuration 63 | 64 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration 65 | 66 | ### Deployment 67 | 68 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment 69 | 70 | ### `npm run build` fails to minify 71 | 72 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify 73 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "calc", 3 | "homepage": "http://maniruzzamanakash.github.io/react-calculator", 4 | "version": "0.1.0", 5 | "private": true, 6 | "dependencies": { 7 | "@testing-library/jest-dom": "^4.2.4", 8 | "@testing-library/react": "^9.4.0", 9 | "@testing-library/user-event": "^7.2.1", 10 | "bootstrap": "^4.4.1", 11 | "expr-eval": "^2.0.2", 12 | "font-awesome": "^4.7.0", 13 | "jquery": "^3.4.1", 14 | "react": "^16.12.0", 15 | "react-dom": "^16.12.0", 16 | "react-scripts": "3.4.0" 17 | }, 18 | "scripts": { 19 | "start": "react-scripts start", 20 | "build": "react-scripts build", 21 | "test": "react-scripts test", 22 | "eject": "react-scripts eject", 23 | "predeploy": "npm run build", 24 | "deploy": "gh-pages -d build" 25 | }, 26 | "eslintConfig": { 27 | "extends": "react-app" 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 | "gh-pages": "^2.2.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManiruzzamanAkash/react-calculator/bed0798b2f2093635cae279831d6bc18cb7d7284/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 25 | Simple Calculator | AJ Calculator - React js 26 | 27 | 28 | 29 | 30 |
31 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManiruzzamanAkash/react-calculator/bed0798b2f2093635cae279831d6bc18cb7d7284/public/logo.png -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManiruzzamanAkash/react-calculator/bed0798b2f2093635cae279831d6bc18cb7d7284/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManiruzzamanAkash/react-calculator/bed0798b2f2093635cae279831d6bc18cb7d7284/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Simple Calculator", 3 | "name": "Simple Calculator | React JS", 4 | "icons": [{ 5 | "src": "favicon.ico", 6 | "sizes": "64x64 32x32 24x24 16x16", 7 | "type": "image/x-icon" 8 | }, 9 | { 10 | "src": "logo192.png", 11 | "type": "image/png", 12 | "sizes": "192x192" 13 | }, 14 | { 15 | "src": "logo512.png", 16 | "type": "image/png", 17 | "sizes": "512x512" 18 | } 19 | ], 20 | "start_url": ".", 21 | "display": "standalone", 22 | "theme_color": "#000000", 23 | "background_color": "#ffffff" 24 | } -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AppView from './views/AppView'; 3 | 4 | function App () { 5 | return ( 6 | 7 | 8 | 9 | ); 10 | } 11 | 12 | export default App; -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /src/assets/images/dummy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManiruzzamanAkash/react-calculator/bed0798b2f2093635cae279831d6bc18cb7d7284/src/assets/images/dummy.png -------------------------------------------------------------------------------- /src/assets/styles/App.css: -------------------------------------------------------------------------------- 1 | /** Body **/ 2 | 3 | body { 4 | background: #FFF; 5 | } 6 | 7 | a { 8 | color: #748eb3; 9 | transition: .3s; 10 | } 11 | 12 | .row { 13 | display: flex; 14 | flex-wrap: wrap; 15 | margin-right: 0px!important; 16 | } 17 | 18 | span.app-title { 19 | font-size: 35px; 20 | font-family: fantasy; 21 | letter-spacing: 5px; 22 | color: #748eb3; 23 | } 24 | 25 | .app-header { 26 | text-align: center; 27 | margin-top: 10px; 28 | color: black; 29 | letter-spacing: 4px; 30 | } 31 | 32 | 33 | /** Body **/ 34 | 35 | .calculatorArea { 36 | margin: 50px 30px 0px 30px; 37 | padding: 10px 0px 30px 10px; 38 | background: #282828; 39 | } 40 | 41 | .btn { 42 | border-radius: 10px; 43 | box-shadow: 3px 4px 25px 0px #414141; 44 | transition: .3s; 45 | } 46 | 47 | .btn:hover { 48 | border-radius: 10px; 49 | box-shadow: 2px 4px 7px -4px #fff; 50 | } 51 | 52 | .text-bold { 53 | font-weight: bold; 54 | } 55 | 56 | 57 | /** Header **/ 58 | 59 | .resultArea { 60 | background: #E6E6E6; 61 | height: 80px; 62 | font-weight: bold; 63 | color: #282828; 64 | text-align: right; 65 | padding-right: 40px; 66 | padding-top: 12px; 67 | white-space: normal; 68 | word-wrap: break-word; 69 | } 70 | 71 | .resultArea-md { 72 | font-size: 35px; 73 | } 74 | 75 | .resultArea-sm { 76 | font-size: 25px; 77 | } 78 | 79 | .resultArea-xsm { 80 | font-size: 16px; 81 | } 82 | 83 | .resultArea-xxsm { 84 | font-size: 10px; 85 | } 86 | 87 | 88 | /** Header **/ 89 | 90 | 91 | /*** BODY ***/ 92 | 93 | .calculator-body-part { 94 | height: auto; 95 | min-height: 200px; 96 | margin-top: 20px; 97 | } 98 | 99 | .top-button { 100 | background: #B082A9; 101 | border: 1px solid #B082A9; 102 | width: 19%; 103 | margin: 0px 0px 0px 10px; 104 | } 105 | 106 | .top-button:hover { 107 | background: #9A6F92; 108 | border: 1px solid #9A6F92; 109 | } 110 | 111 | .btn-mem { 112 | background: #8FBE8A; 113 | border: 1px solid #8FBE8A; 114 | width: 19%; 115 | margin: 0px 0px 0px 10px; 116 | } 117 | 118 | .btn-mem:hover { 119 | background: #6E9B6D; 120 | border: 1px solid #6E9B6D; 121 | } 122 | 123 | .btn-digit-operation { 124 | width: 15%; 125 | margin: 0px 0px 0px 10px; 126 | } 127 | 128 | .btn-digit { 129 | background: #758FB5; 130 | border: 1px solid #758FB5; 131 | } 132 | 133 | .btn-digit:hover { 134 | background: #85A2C9; 135 | border: 1px solid #85A2C9; 136 | } 137 | 138 | .btn-operation { 139 | background: #979797; 140 | border: 1px solid #979797; 141 | } 142 | 143 | .btn-operation:hover { 144 | background: #858585; 145 | border: 1px solid #858585; 146 | } 147 | 148 | .btn-equal { 149 | background: #BF6F69; 150 | border: 1px solid #BF6F69; 151 | } 152 | 153 | .btn-equal:hover { 154 | background: #AD655C; 155 | border: 1px solid #AD655C; 156 | } 157 | 158 | 159 | /*** BODY ***/ 160 | 161 | @media (min-width: 768px) { 162 | .col-md-5 { 163 | flex: 5 0 51.666667%; 164 | max-width: 50.666667%; 165 | } 166 | } 167 | 168 | p.copy-right { 169 | color: #969696!important; 170 | margin-right: 27px; 171 | } -------------------------------------------------------------------------------- /src/components/Button.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | function Button (props) { 4 | return ( 5 | 8 | ); 9 | } 10 | 11 | export default Button; -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' } 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /src/views/AppView.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import 'bootstrap/dist/css/bootstrap.min.css'; 3 | import 'font-awesome/css/font-awesome.min.css' 4 | import '../assets/styles/App.css'; 5 | import Button from '../components/Button'; 6 | 7 | var Parser = require('expr-eval').Parser; 8 | 9 | class AppView extends React.Component { 10 | 11 | state = { 12 | fullText: '0', 13 | resultText: '', 14 | isResultClicked : false, 15 | isResultInvalid: false 16 | } 17 | 18 | // undoClick = () => { 19 | // console.log('undo something'); 20 | // } 21 | 22 | /** 23 | * digitClick 24 | * @param { integer } digit 25 | * @return { void } Click to digit and adds to full text 26 | */ 27 | digitClick = (digit) => { 28 | 29 | if(this.state.isResultClicked){ 30 | this.setState({ fullText : digit.toString(), resultText : '', isResultClicked: false}); 31 | }else{ 32 | let { fullText } = this.state; 33 | 34 | // If fullText is 0, then clear it 35 | if(fullText === "0."){ 36 | // fullText = ""; 37 | }else if(parseFloat(fullText) === 0){ 38 | fullText = ""; 39 | } 40 | 41 | fullText = fullText + digit.toString(); 42 | this.setState({ fullText }); 43 | } 44 | } 45 | 46 | operationClick = (operationSign) =>{ 47 | let { fullText, resultText } = this.state; 48 | console.log('resultText', resultText) 49 | if(resultText.length > 0){ 50 | this.setState({ 51 | fullText : resultText+operationSign, 52 | isResultClicked: false 53 | }); 54 | this.setState({ 55 | resultText : '', 56 | }); 57 | }else{ 58 | fullText = fullText + operationSign; 59 | this.setState({ fullText }); 60 | } 61 | } 62 | 63 | /** 64 | * dotClick 65 | * @return { void } Handle Dot click 66 | */ 67 | dotClick = () => { 68 | if(this.state.isResultClicked){ 69 | this.setState({ fullText : "0.", resultText : '', isResultClicked: false}); 70 | }else{ 71 | let { fullText } = this.state; 72 | fullText = fullText + "."; 73 | this.setState({ fullText }); 74 | } 75 | } 76 | 77 | 78 | /** 79 | * functionalButtonClick 80 | * @return { void } Handle multiple events 81 | */ 82 | functionalButtonClick = (key) => { 83 | let { fullText, resultText } = this.state; 84 | 85 | switch (key) { 86 | case "AC": 87 | this.setState({ fullText : "0", resultText : "" }); 88 | break; 89 | 90 | case "C": 91 | this.setState({ resultText : "" }); 92 | // Delete one by one character from fullText 93 | 94 | if(fullText.length > 0 ){ 95 | let newFullText = fullText.slice(0, -1); 96 | if(newFullText == ""){ 97 | newFullText = "0"; 98 | } 99 | this.setState({ fullText : newFullText }); 100 | } 101 | 102 | break; 103 | 104 | case "CUT_FIRST": 105 | this.setState({ resultText : "" }); 106 | 107 | // Delete one by one character from fullText 108 | if(fullText.length > 0 ){ 109 | let newFullText = fullText.substring(1); 110 | if(newFullText == ""){ 111 | newFullText = "0"; 112 | } 113 | this.setState({ fullText : newFullText }); 114 | } 115 | 116 | break; 117 | 118 | case "MC": 119 | // Clear Memory 120 | localStorage.setItem('CALC_M', "0"); 121 | break; 122 | 123 | case "MR": 124 | // MR = Memory Recall uses the number in memory, acts as if you had keyed in that number yourself 125 | let memValue = localStorage.getItem('CALC_M') || "0"; 126 | let newFullText = memValue; 127 | this.setState({ fullText : newFullText, resultText: '' }); 128 | break; 129 | 130 | 131 | case "M+": 132 | // Memory Add takes the number on the display, adds it to the memory, and puts the result into memory 133 | let getMemoryValue = parseFloat(localStorage.getItem('CALC_M') || "0"); 134 | let totalResult = parseFloat(resultText.length > 0 ? resultText : "0") + getMemoryValue; 135 | localStorage.setItem('CALC_M', totalResult.toString()); 136 | break; 137 | 138 | case "M-": 139 | // Memory Minus takes the number on the display, minus it to the memory, and puts the result into memory 140 | let memValue2 = parseFloat(localStorage.getItem('CALC_M') || "0"); 141 | let totalResult2 = parseFloat(resultText.length > 0 ? resultText : "0") - memValue2; 142 | localStorage.setItem('CALC_M', totalResult2.toString()); 143 | break; 144 | 145 | case "1/x": 146 | // Get Values in FullText and 1/parse(FullText) 147 | try { 148 | let fullTextNew = "(1/("+fullText+"))"; 149 | let finalResult = this.parseCalculate(fullTextNew); 150 | this.setState({ fullText: fullTextNew, resultText : finalResult.toString() }); 151 | } catch (error) { 152 | this.setState({ fullText: "", resultText : "" }); 153 | } 154 | break; 155 | 156 | case "x^2": 157 | try { 158 | let fullTextNew = "("+fullText+")^2"; 159 | let finalResult = this.parseCalculate(fullTextNew); 160 | this.setState({ fullText: fullTextNew, resultText : finalResult.toString() }); 161 | } catch (error) { 162 | this.setState({ fullText: "", resultText : "" }); 163 | } 164 | break; 165 | 166 | case "+-": 167 | try { 168 | let fullTextNew = "-("+fullText+")"; 169 | // let finalResult = this.parseCalculate(fullTextNew); 170 | this.setState({ fullText: fullTextNew, resultText : "" }); 171 | } catch (error) { 172 | this.setState({ fullText: "", resultText : "" }); 173 | } 174 | break; 175 | 176 | case "SQ_ROOT": 177 | try { 178 | let finalResult = this.parseCalculate(fullText); 179 | finalResult = Math.sqrt(finalResult); 180 | let fullTextNew = "√("+fullText+")"; 181 | this.setState({ fullText: fullTextNew, resultText : finalResult.toString(), isResultInvalid : false }); 182 | } catch (error) { 183 | this.setState({ fullText: "", resultText : "invalid", isResultInvalid : true }); 184 | } 185 | break; 186 | 187 | default: 188 | break; 189 | } 190 | } 191 | 192 | /** 193 | * equalClick 194 | * @return { void } Handle Equal click 195 | */ 196 | equalClick = () => { 197 | try { 198 | let finalResult = this.parseCalculate(this.state.fullText); 199 | this.setState({ resultText: finalResult.toString(), isResultClicked : true, isResultInvalid : false }); 200 | } catch (error) { 201 | console.log('error', error) 202 | let resultText = "invalid"; 203 | this.setState({ resultText, isResultClicked : true, isResultInvalid : true }); 204 | } 205 | 206 | } 207 | 208 | 209 | /** 210 | * parseCalculate 211 | * @param { string } the full text for calculation 212 | * @return { float } Final parsed result 213 | */ 214 | parseCalculate = (fullText) => { 215 | let finalResult = 0; 216 | finalResult = Parser.evaluate(fullText); 217 | return finalResult; 218 | } 219 | 220 | /** 221 | * checkKeyboardEvent 222 | * @return { function } Check and make action if any keyboard is pressed 223 | */ 224 | checkKeyboardEvent = (event) => { 225 | if(event.key === "0" || event.key === "1" || event.key === "2" || event.key === "3" || event.key === "4" || event.key === "5" || event.key === "6" || event.key === "7" || event.key === "8" || event.key === "9") { 226 | this.digitClick(parseInt(event.key)); 227 | }else if(event.key === "+" || event.key === "-" || event.key === "*" || event.key === "/") { 228 | return this.operationClick(event.key) 229 | }else if(event.key === "="){ 230 | this.equalClick(); 231 | }else if(event.key === "Backspace"){ 232 | this.functionalButtonClick("C"); 233 | }else if(event.key === "Enter"){ 234 | this.equalClick(); 235 | } 236 | } 237 | 238 | // Handle Key board event 239 | componentDidMount(){ 240 | document.addEventListener("keydown", this.checkKeyboardEvent, false); 241 | localStorage.setItem('CALC_M', localStorage.getItem('CALC_M') || "0"); 242 | } 243 | 244 | // Remove Handle Key board event 245 | componentWillUnmount(){ 246 | document.removeEventListener("keydown", this.checkKeyboardEvent, false); 247 | } 248 | 249 | 250 | /** 251 | * printResultTextCSS 252 | * @return { string } css of result span 253 | */ 254 | printResultTextCSS = () => { 255 | let css = "resultArea "; 256 | let { fullText, resultText } = this.state; 257 | let totalLength = fullText.length + resultText.length; 258 | if(totalLength >= 0 && totalLength <= 18){ 259 | css = css + "resultArea-md"; 260 | }else if(totalLength > 18 && totalLength <= 35){ 261 | css = css + "resultArea-sm"; 262 | }else if(totalLength > 35 && totalLength <= 55){ 263 | css = css + "resultArea-xsm"; 264 | }else{ 265 | css = css + "resultArea-xxsm"; 266 | } 267 | return css; 268 | } 269 | 270 | render() { 271 | const { fullText, resultText, isResultInvalid } = this.state; 272 | return ( 273 |
274 |
275 |
276 | 277 |
278 | AJ Calculator 279 | React js 280 |
281 | 282 |
283 |
284 | 285 |
286 |
287 | { fullText } 288 | 289 | { isResultInvalid && resultText.length > 0 && 290 | 291 | { ' = ' + resultText } 292 | 293 | } 294 | 295 | { !isResultInvalid && resultText.length > 0 && 296 | 297 | { ' = '+ resultText } 298 | 299 | } 300 |
301 |
302 | 303 |
304 |
305 |
311 | 312 |
313 |
318 | 319 | 320 |
321 |
327 | 328 |
329 |
335 | 336 |
337 |
343 | 344 |
345 |
351 | 352 |
353 | 354 |
355 |
356 | 357 |

358 | © 2020, Maniruzzaman Akash 359 |

360 |
361 |
362 |
363 | ); 364 | } 365 | } 366 | 367 | export default AppView; 368 | --------------------------------------------------------------------------------