app completed

This commit is contained in:
Mitanshu 2022-03-12 21:20:28 +05:30
parent 674bedb6a3
commit bb9326edf9
10 changed files with 448 additions and 6 deletions

46
package-lock.json generated
View File

@ -3768,6 +3768,11 @@
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
},
"complex.js": {
"version": "2.0.15",
"resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.0.15.tgz",
"integrity": "sha512-gDBvQU8IG139ZBQTSo2qvDFP+lANMGluM779csXOr6ny1NUtA3wkUnCFjlDNH/moAVfXtvClYt6G0zarFbtz5w=="
},
"compressible": {
"version": "2.0.18",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
@ -4627,6 +4632,11 @@
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"escape-latex": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz",
"integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw=="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@ -6337,6 +6347,11 @@
}
}
},
"javascript-natural-sort": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
"integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k="
},
"jest": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz",
@ -7834,6 +7849,22 @@
"tmpl": "1.0.5"
}
},
"mathjs": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/mathjs/-/mathjs-10.4.0.tgz",
"integrity": "sha512-2zVrKvORwxeWbewweD5NDxkTgAMvqkwmMljHUPhDPJtX4sGJEL6ugFXQN597rhH9RGtnMxNzz/+hPGIr9UEWrg==",
"requires": {
"@babel/runtime": "^7.17.2",
"complex.js": "^2.0.15",
"decimal.js": "^10.3.1",
"escape-latex": "^1.2.0",
"fraction.js": "^4.2.0",
"javascript-natural-sort": "^0.7.1",
"seedrandom": "^3.0.5",
"tiny-emitter": "^2.1.0",
"typed-function": "^2.0.0"
}
},
"mdn-data": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
@ -9897,6 +9928,11 @@
"ajv-keywords": "^3.5.2"
}
},
"seedrandom": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
},
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@ -10593,6 +10629,11 @@
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
},
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
@ -10707,6 +10748,11 @@
"mime-types": "~2.1.24"
}
},
"typed-function": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/typed-function/-/typed-function-2.1.0.tgz",
"integrity": "sha512-bctQIOqx2iVbWGDGPWwIm18QScpu2XRmkC19D8rQGFsjKSgteq/o1hTZvIG/wuDq8fanpBDrLkLq+aEN/6y5XQ=="
},
"typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",

View File

@ -6,6 +6,7 @@
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.4",
"@testing-library/user-event": "^13.5.0",
"mathjs": "^10.4.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",

View File

@ -1,3 +0,0 @@
.App {
text-align: center;
}

View File

@ -1,7 +1,10 @@
import "./App.css";
import Calculator from "./components/Calculator";
function App() {
return <></>;
return (
<>
<Calculator />
</>
);
}
export default App;

90
src/components/Buttons.js Normal file
View File

@ -0,0 +1,90 @@
import React from "react";
import "./styles/Buttons.css";
// import CALCULATOR_BUTTONS from "./CalculatorButtons";
const Buttons = ({
inputHandler,
clearInput,
backspace,
changePlusMinus,
calculateAns,
}) => {
return (
<div className="show-btn">
<button className="btn exp" onClick={inputHandler}>
^
</button>
<button className="btn exp" onClick={inputHandler}>
(
</button>
<button className="btn exp" onClick={inputHandler}>
)
</button>
<button className="btn exp" onClick={inputHandler}>
</button>
<button className="btn clr" onClick={clearInput}>
AC
</button>
<button className="btn clr" onClick={backspace}>
</button>
<button className="btn exp" onClick={inputHandler}>
%
</button>
<button className="btn exp" onClick={inputHandler}>
÷
</button>
<button className="btn" onClick={inputHandler}>
7
</button>
<button className="btn" onClick={inputHandler}>
8
</button>
<button className="btn" onClick={inputHandler}>
9
</button>
<button className="btn exp" onClick={inputHandler}>
x
</button>
<button className="btn" onClick={inputHandler}>
4
</button>
<button className="btn" onClick={inputHandler}>
5
</button>
<button className="btn" onClick={inputHandler}>
6
</button>
<button className="btn exp" onClick={inputHandler}>
-
</button>
<button className="btn" onClick={inputHandler}>
1
</button>
<button className="btn" onClick={inputHandler}>
2
</button>
<button className="btn" onClick={inputHandler}>
3
</button>
<button className="btn exp" onClick={inputHandler}>
+
</button>
<button className="btn exp" onClick={changePlusMinus}>
±
</button>
<button className="btn" onClick={inputHandler}>
0
</button>
<button className="btn exp" onClick={inputHandler}>
.
</button>
<button className="btn exp" onClick={calculateAns}>
=
</button>
</div>
);
};
export default Buttons;

View File

@ -0,0 +1,144 @@
import React, { useState } from "react";
import Display from "./Display";
import Buttons from "./Buttons";
import "./styles/Calculator.css";
import { evaluate, round } from "mathjs";
function Calculator() {
const [input, setInput] = useState("");
const [answer, setAnswer] = useState("");
//input
const inputHandler = (event) => {
if (answer === "Invalid Input!!") return;
let val = event.target.innerText;
let str = input + val;
if (str.length > 14) return;
if (answer !== "") {
setInput(answer + val);
setAnswer("");
} else setInput(str);
// setInput(str);
};
//Clear screen
const clearInput = () => {
setInput("");
setAnswer("");
};
// check brackets are balanced or not
const checkBracketBalanced = (expr) => {
let stack = [];
for (let i = 0; i < expr.length; i++) {
let x = expr[i];
if (x === "(") {
stack.push(x);
continue;
}
if (x === ")") {
if (stack.length === 0) return false;
else stack.pop();
}
}
return stack.length === 0;
};
// calculate final answer
const calculateAns = () => {
if (input === "") return;
let result = 0;
let finalexpression = input;
// finalexpression = input.replaceAll("^", "**"); //for eval()
finalexpression = finalexpression.replaceAll("x", "*");
finalexpression = finalexpression.replaceAll("÷", "/");
// evaluate square root
let noSqrt = input.match(/√[0-9]+/gi);
if (noSqrt !== null) {
let evalSqrt = input;
for (let i = 0; i < noSqrt.length; i++) {
evalSqrt = evalSqrt.replace(
noSqrt[i],
`sqrt(${noSqrt[i].substring(1)})`
);
}
finalexpression = evalSqrt;
}
try {
// check brackets are balanced or not
if (!checkBracketBalanced(finalexpression)) {
const errorMessage = { message: "Brackets are not balanced!" };
throw errorMessage;
}
result = evaluate(finalexpression); //mathjs
} catch (error) {
result =
error.message === "Brackets are not balanced!"
? "Brackets are not balanced!"
: "Invalid Input!!"; //error.message;
}
isNaN(result) ? setAnswer(result) : setAnswer(round(result, 3));
};
// remove last character
const backspace = () => {
if (answer !== "") {
setInput(answer.toString().slice(0, -1));
setAnswer("");
} else setInput((prev) => prev.slice(0, -1));
};
// change prefix of expression
const changePlusMinus = () => {
//need to change for answer
if (answer === "Invalid Input!!") return;
else if (answer !== "") {
if (input.charAt(0) === "-") {
let plus = "+";
setInput(plus.concat(answer.slice(1, answer.length)));
} else if (input.charAt(0) === "+") {
let minus = "-";
setInput(minus.concat(answer.slice(1, answer.length)));
} else {
let minus = "-";
setInput(minus.concat(answer));
}
setAnswer("");
} else {
if (input.charAt(0) === "-") {
let plus = "+";
setInput((prev) => plus.concat(prev.slice(1, prev.length)));
} else if (input.charAt(0) === "+") {
let minus = "-";
setInput((prev) => minus.concat(prev.slice(1, prev.length)));
} else {
let minus = "-";
setInput((prev) => minus.concat(prev));
}
}
};
return (
<>
<div className="container">
<div className="main">
<Display input={input} setInput={setInput} answer={answer} />
<Buttons
inputHandler={inputHandler}
clearInput={clearInput}
backspace={backspace}
changePlusMinus={changePlusMinus}
calculateAns={calculateAns}
/>
</div>
</div>
</>
);
}
export default Calculator;

56
src/components/Display.js Normal file
View File

@ -0,0 +1,56 @@
import React from "react";
import "./styles/Display.css";
const Display = ({ input, setInput, answer }) => {
// const onChangeTagInput = (e) => {
// // setInputVal(e.target.value.replace(/^[0-9 ()+-]+$/, "a"));
// // if(e.target.value === "1")
// setInput(e.target.value);
// // console.log(e.target.value.test(/^[0-9 ()+-]+$/));
// // console.log(e.target.value);
// };
return (
<>
<div className="display">
{answer === "" ? (
<>
<input
type="text"
name="input"
className="input"
style={{ padding: "29px" }}
value={input}
placeholder="0"
// onChange={onChangeTagInput}
maxLength={12}
disabled
/>
</>
) : (
<>
<input
type="text"
name="input"
className="value"
value={input}
placeholder="0"
// onChange={onChangeTagInput}
maxLength={12}
disabled
/>
<input
type="text"
name="value"
className="input"
value={answer}
disabled
/>
</>
)}
</div>
</>
);
};
export default Display;

View File

@ -0,0 +1,39 @@
.show-btn {
display: grid;
grid-template-columns: auto auto auto auto;
background-color: white;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.btn {
width: 80px;
height: 80px;
margin: 6px auto;
font-size: 24px;
font-weight: 500;
cursor: pointer;
border-radius: 50%;
background: none;
border: 0px;
}
.btn:hover {
background-color: #6dd5ed;
color: white;
transition: background-color 0.3s ease;
}
.btn:active {
background-color: #48b1bf;
color: white;
transition: background-color 0.3s ease;
}
.clr {
color: #d66d75;
}
.exp {
color: #06beb6;
}

View File

@ -0,0 +1,22 @@
.container {
background-color: gainsboro;
min-height: 100vh;
min-width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.main {
border: 0px;
box-shadow: 0px 0px 3px 0.5px #c4e0e5;
border-radius: 10px;
max-width: 400px;
}
@media (max-width: 600px) {
.main {
width: 100%;
height: 100%;
}
}

View File

@ -0,0 +1,44 @@
.display {
display: flex;
flex-direction: column;
padding: 10px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
padding-bottom: 20px;
background: linear-gradient(90deg, #06beb6, #48b1bf 100%);
}
.expression {
padding: 5px;
margin-bottom: 10px;
height: 50px;
}
.input,
.value {
padding: 10px;
text-align: right;
background-color: transparent;
color: white;
border: 0px;
letter-spacing: 1.5px;
}
.input {
font-size: 35px;
}
.value {
font-size: 15px;
}
.input::placeholder,
.value::placeholder {
color: white;
}
.input:focus-visible,
.value:focus-visible {
outline-style: none;
outline-width: 0px;
}