diff --git a/src/components/apps/calculator/Calculator.jsx b/src/components/apps/calculator/Calculator.jsx index 0ef4897..60da984 100644 --- a/src/components/apps/calculator/Calculator.jsx +++ b/src/components/apps/calculator/Calculator.jsx @@ -1,7 +1,207 @@ -// import styles from "./Calculator.module.css"; +import { useCallback, useEffect, useState } from "react"; +import { Button } from "../../_utils/button/Button.jsx"; +import styles from "./Calculator.module.css"; -export function Calculator() { - return ( -
- ); +/** @type {import("../../windows/WindowView.jsx").windowProps} */ +export function Calculator({ active }) { + const [input, setInput] = useState("0"); + const [firstNumber, setFirstNumber] = useState(null); + const [secondNumber, setSecondNumber] = useState(null); + const [operation, setOperation] = useState(null); + const [isIntermediate, setIsIntermediate] = useState(false); + + const log = useCallback(() => { + console.info({ input, firstNumber, secondNumber, operation }); + }, [firstNumber, input, operation, secondNumber]); + + const reset = useCallback(() => { + setInput("0"); + setFirstNumber(null); + setSecondNumber(null); + setOperation(null); + + log(); + }, [log]); + + const addInput = useCallback((string) => { + let hasReset = false; + if (secondNumber != null) { + if (isIntermediate) { + setFirstNumber(input); + setSecondNumber(null); + setInput(null); + } else { + reset(); + } + hasReset = true; + } + + if (string === "." && input?.includes(".")) + return; + + if (string === "-") { + if (input === "0") { + setInput("-0"); + } else { + setInput((parseFloat(input) * -1).toString()); + } + } else if (string === "%") { + setInput((parseFloat(input) / 100).toString()); + } else if (input === "0" || input === "-0" || input == null || hasReset) { + if (string === ".") { + setInput(input === "-0" ? "0." : "0."); + } else { + setInput(input === "-0" ? `-${string}` : string); + } + } else { + setInput(input + string); + } + + log(); + }, [input, isIntermediate, log, reset, secondNumber]); + + const calculate = useCallback((intermediate = false) => { + if (firstNumber == null) { + + } else { + setSecondNumber(input); + + const a = parseFloat(firstNumber); + const b = parseFloat(input); + + let result = 0; + switch (operation) { + case "×": + result = a * b; + break; + case "÷": + result = a / b; + break; + case "+": + result = a + b; + break; + case "-": + result = a - b; + break; + } + + setInput(result.toString()); + } + + setIsIntermediate(intermediate); + + log(); + }, [firstNumber, input, log, operation]); + + const changeOperation = useCallback((operation) => { + if (firstNumber != null && secondNumber == null) { + calculate(true); + } else { + setFirstNumber(input); + setSecondNumber(null); + setInput(null); + } + + setOperation(operation); + + log(); + }, [calculate, firstNumber, input, log, secondNumber]); + + useEffect(() => { + const onKeyDown = (event) => { + if (!active) + return; + + console.log(event.key); + + event.preventDefault(); + + switch (event.key) { + case "0": + case "1": + case "2": + case "3": + case "4": + case "5": + case "6": + case "7": + case "8": + case "9": + addInput(event.key); + break; + case ".": + case ",": + addInput("."); + break; + case "Escape": + reset(); + break; + case "=": + case "Enter": + calculate(); + break; + case "*": + changeOperation("×"); + break; + case "/": + changeOperation("÷"); + break; + case "+": + case "-": + changeOperation(event.key); + break; + case "%": + addInput("%"); + break; + } + }; + + document.addEventListener("keydown", onKeyDown); + + return () => { + document.removeEventListener("keydown", onKeyDown); + }; + }, [active, addInput, calculate, changeOperation, reset]); + + let calculation = ""; + if (operation != null) + calculation = `${firstNumber} ${operation} ${secondNumber != null ? secondNumber + " =" : ""}`; + + return ({calculation}
+{input ?? firstNumber}
+