From f89f79d2a55698bd063e749b0edbb2268eaba585 Mon Sep 17 00:00:00 2001 From: Janudi Date: Fri, 2 May 2025 22:57:56 +0530 Subject: [PATCH 1/2] feat: add subtraction, multiplication, and division functionality to calculator --- calculator-api/index.js | 38 +++++++++++----- calculator-api/util.js | 19 +++++--- ui-calculator/index.html | 2 +- ui-calculator/src/App.css | 84 +++++++++++++++++++++++----------- ui-calculator/src/App.jsx | 94 ++++++++++++++++++++++++--------------- 5 files changed, 157 insertions(+), 80 deletions(-) diff --git a/calculator-api/index.js b/calculator-api/index.js index b09e6d6..7c4b129 100644 --- a/calculator-api/index.js +++ b/calculator-api/index.js @@ -1,21 +1,37 @@ -// express web server implementation - -// import express import express from 'express'; import calculator from './util.js'; const app = express(); -// use json middleware app.use(express.json()); -app.post("/api/add", async (req,res) => { - // Implement the api logic here - const { val1, val2 } = req.body; - const result = calculator.add(val1, val2); - res.send({ result }); +app.post("/api/calculate", async (req, res) => { + const { val1, val2, operation } = req.body; + + if (val1 == null || val2 == null || !operation) { + return res.status(400).send({ error: "Invalid input" }); + } + + let result; + switch (operation) { + case 'add': + result = calculator.add(val1, val2); + break; + case 'subtract': + result = calculator.subtract(val1, val2); + break; + case 'multiply': + result = calculator.multiply(val1, val2); + break; + case 'divide': + result = calculator.divide(val1, val2); + break; + default: + return res.status(400).send({ error: 'Unknown operation' }); + } + + res.send({ result }); }); app.listen(3000, () => { - console.log("API has started on port 3000"); + console.log("API has started on port 3000"); }); - \ No newline at end of file diff --git a/calculator-api/util.js b/calculator-api/util.js index 309839c..57e4531 100644 --- a/calculator-api/util.js +++ b/calculator-api/util.js @@ -1,7 +1,12 @@ -const calculator ={ - add: (val1, val2) => (val1 != undefined && val2 != undefined) ? val1 + val2 : 0, - subtract: (val1, val2) => (val1 != undefined && val2 != undefined) ? val1 - val2 : 0, - multiply: (val1, val2) => (val1 != undefined && val2 != undefined) ? val1 * val2 : 0, -} - -export default calculator; \ No newline at end of file +const calculator = { + add: (val1, val2) => val1 + val2, + subtract: (val1, val2) => val1 - val2, + multiply: (val1, val2) => val1 * val2, + divide: (val1, val2) => { + if (val2 === 0) return "Cannot divide by zero"; + return val1 / val2; + } + }; + + export default calculator; + \ No newline at end of file diff --git a/ui-calculator/index.html b/ui-calculator/index.html index 0c589ec..ec61f6e 100644 --- a/ui-calculator/index.html +++ b/ui-calculator/index.html @@ -4,7 +4,7 @@ - Vite + React + Calculator
diff --git a/ui-calculator/src/App.css b/ui-calculator/src/App.css index b9d355d..7fb7417 100644 --- a/ui-calculator/src/App.css +++ b/ui-calculator/src/App.css @@ -1,42 +1,76 @@ #root { - max-width: 1280px; + max-width: 500px; margin: 0 auto; padding: 2rem; text-align: center; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background-color: #f4f6f8; + border-radius: 12px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; +h2 { + color: #2c3e50; + margin-bottom: 1.5rem; } -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); + +label { + display: block; + margin: 0.5rem 0 0.25rem; + font-weight: bold; + color: #34495e; } -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); + +input, select { + width: 100%; + padding: 0.5rem; + margin-bottom: 1rem; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 1rem; + box-sizing: border-box; } -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } +button { + padding: 0.6rem 1.2rem; + background-color: #2ecc71; + color: white; + border: none; + border-radius: 6px; + cursor: pointer; + font-size: 1rem; + transition: background-color 0.3s; } -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } +button:hover { + background-color: #2980b9; +} + +strong { + color: #27ae60; + font-size: 1.2rem; } -.card { - padding: 2em; +.result-container { + margin-top: 1.5rem; } -.read-the-docs { - color: #888; +.calculator-container { + background: #fff; + padding: 2rem; + border-radius: 12px; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); + margin-top: 2rem; +} + +button { + width: 100%; + margin-top: 1rem; +} + +@media (max-width: 480px) { + input, select, button { + font-size: 0.9rem; + padding: 0.5rem; + } } diff --git a/ui-calculator/src/App.jsx b/ui-calculator/src/App.jsx index 793b6f1..dc8c892 100644 --- a/ui-calculator/src/App.jsx +++ b/ui-calculator/src/App.jsx @@ -1,47 +1,69 @@ import { useState } from "react"; import "./App.css"; - function App() { - const [val1, setVal1] = useState(); - const [val2, setVal2] = useState(); - const [result, setResult] = useState(); + const [val1, setVal1] = useState(""); + const [val2, setVal2] = useState(""); + const [operation, setOperation] = useState("add"); + const [result, setResult] = useState(""); + const calculate = async () => { + if (val1 === "" || val2 === "") { + setResult("Please enter both values."); + return; + } - const calculate = async () => { - const apiResult = await fetch("/api/add", { - method: "POST", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - body: JSON.stringify({ - val1: parseInt(val1), - val2: parseInt(val2), - }), - }); - const jsonResult = await apiResult.json(); - setResult(jsonResult.result); - }; + const response = await fetch("/api/calculate", { + method: "POST", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + body: JSON.stringify({ + val1: parseFloat(val1), + val2: parseFloat(val2), + operation, + }), + }); + const data = await response.json(); + setResult(data.result ?? "Error occurred"); + }; - return ( - <> -

Awesome Calculator!

- - setVal1(e.target.value)} /> -
- - setVal2(e.target.value)} /> -
-
- -
-
- - - ); + return ( +
+

Awesome Calculator!

+ + + setVal1(e.target.value)} + /> + + + setVal2(e.target.value)} + /> + + + + + + +
+ +
+
+ ); + } - export default App; From 6d10beb3b3852bf26eb66c2fc107a32f61231238 Mon Sep 17 00:00:00 2001 From: Janudi Date: Thu, 8 May 2025 21:45:47 +0530 Subject: [PATCH 2/2] Add unit tests for calculator functions --- calculator-api/test/test-calculator.js | 40 ++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/calculator-api/test/test-calculator.js b/calculator-api/test/test-calculator.js index 282cc0f..1bdf363 100644 --- a/calculator-api/test/test-calculator.js +++ b/calculator-api/test/test-calculator.js @@ -1,14 +1,38 @@ import { expect } from "chai"; import calculator from "../util.js"; -it("Is 5 + 2 = 7", (done) => { - //define test assertion - expect(calculator.add(5, 2)).to.equal(7) +describe("Calculator Tests", () => { + // ADDITION + it("Is 5 + 2 = 7", (done) => { + expect(calculator.add(5, 2)).to.equal(7); done(); -}); + }); + + it("Is undefined + undefined = NaN", (done) => { + expect(calculator.add(undefined, undefined)).to.be.NaN; + done(); + }); + + // SUBTRACTION + it("Is 10 - 3 = 7", (done) => { + expect(calculator.subtract(10, 3)).to.equal(7); + done(); + }); -it("Is undefined + undefined = 0", (done) => { - //define test assertion - expect(calculator.add(undefined, undefined)).to.equal(0) + // MULTIPLICATION + it("Is 4 * 3 = 12", (done) => { + expect(calculator.multiply(4, 3)).to.equal(12); done(); -}); \ No newline at end of file + }); + + // DIVISION + it("Is 9 / 3 = 3", (done) => { + expect(calculator.divide(9, 3)).to.equal(3); + done(); + }); + + it("Is 5 / 0 = 'Cannot divide by zero'", (done) => { + expect(calculator.divide(5, 0)).to.equal("Cannot divide by zero"); + done(); + }); +});