2
\$\begingroup\$

One of the first React project which is building calculator with memory function. Could you please have a look is any changes should I make.

I would be great if you can suggest some best practice method for this calculator and memory functions

The Repo is in https://github.com/athimannil/calculator

index.js

import React from 'react';
import { render } from 'react-dom';
import App from './components/App';

import './scss/App.scss';

render(<App />, document.getElementById('app'));

App.js

import React from 'react';

import { Dashboard } from './dashboard/Dashboard';
import { Keypad } from './keypad/Keypad';
import calculate from '../logic/calculate';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      total: null,
      next: null,
      operation: null,
      memory: null
    };
  }

  handleClick = (buttonName) => {
    this.setState(calculate(this.state, buttonName));
  }

  render() {
    return (
      <main className="main">
        <Dashboard
          value={this.state.next || this.state.total || '0'}
        />

        <Keypad
          selectedValue={this.handleClick}
        />
      </main>
    );
  }
}

export default App;

Keypad.js

import React from 'react';
import PropTypes from 'prop-types';

export class Keypad extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      current: null,
      total: 0,
      operator: null
    }
  }

  handleButton = (event) => {
    const currentNumber = event.target.name;
    this.props.selectedValue(currentNumber);
  }

  render () {
    return (
      <div className="keypad">
        <h5 className="model">SL-300SV</h5>
        <a
          className="button"
          name="√"
          onClick={this.handleButton}
          >√</a>
        <a
          className="button"
          name="OFF"
          onClick={this.handleButton}
          >OFF</a>
        <a
          className="button"
          name="MC"
          onClick={this.handleButton}
          >MC</a>
        <a
          className="button"
          name="MR"
          onClick={this.handleButton}
          >MR</a>
        <a
          className="button"
          name="M-"
          onClick={this.handleButton}
          >M-</a>
        <a
          className="button"
          name="M+"
          onClick={this.handleButton}
          >M+</a>
        <a
          className="button"
          name="/"
          onClick={this.handleButton}
          >÷</a>
        <a
          className="button"
          name="%"
          onClick={this.handleButton}
          >%</a>
        <a
          className="button"
          name="7"
          onClick={this.handleButton}
          >7</a>
        <a
          className="button"
          name="8"
          onClick={this.handleButton}
          >8</a>
        <a
          className="button"
          name="9"
          onClick={this.handleButton}
          >9</a>
        <a
          className="button"
          name="*"
          onClick={this.handleButton}
          >x</a>
        <a
          className="button"
          name="+/-"
          onClick={this.handleButton}
          >+/-</a>
        <a
          className="button"
          name="4"
          onClick={this.handleButton}
          >4</a>
        <a
          className="button"
          name="5"
          onClick={this.handleButton}
          >5</a>
        <a
          className="button"
          name="6"
          onClick={this.handleButton}
          >6</a>
        <a
          className="button"
          name="-"
          onClick={this.handleButton}
          >–</a>
        <a
          className="button primary"
          name="C"
          onClick={this.handleButton}
          >C</a>
        <a
          className="button"
          name={"1"}
          onClick={this.handleButton}
          >1</a>
        <a
          className="button"
          name="2"
          onClick={this.handleButton}
          >2</a>
        <a
          className="button"
          name="3"
          onClick={this.handleButton}
          >3</a>
        <a
          className="button plus"
          name="+"
          onClick={this.handleButton}
          >+</a>
        <a
          className="button primary"
          name="AC"
          onClick={this.handleButton}
          >AC</a>
        <a
          className="button"
          name="0"
          onClick={this.handleButton}
          >0</a>
        <a
          className="button"
          name="."
          onClick={this.handleButton}
          >.</a>
        <a
          className="button"
          name="="
          onClick={this.handleButton}
          >=</a>
      </div>
    );
  }
}

Keypad.propTypes = {
  name: PropTypes.string
}

dashboard.js

export class Dashboard extends React.Component {
  render () {
    return (
      <div className="dashboard">
        <div className="brand">
          <h2>Casio</h2>
        </div>
        <div className="solar"></div>
        <div className="screen-wrap">
          <div className="screen">
            <h2>{this.props.value}</h2>
          </div>
        </div>
      </div>
    );
  }
}

Calculate.js

import operate from './operate';

export default function calculate(obj, buttonName) {
  if (buttonName === 'AC') {
    return {
      total: null,
      next: null,
      operation: null,
      memory: null
    };
  }

  if (buttonName === 'C') {
    return {
      total: null,
      next: null,
      operation: null
    };
  }

  if (/[0-9]+/.test(buttonName)) {
    if (buttonName === '0' && obj.next === '0') {
      return {};
    }
    if (obj.operation) {
      if (obj.next) {
        return { next: obj.next + buttonName };
      }
      return { next: buttonName };
    }
    if (obj.next) {
      return {
        next: obj.next + buttonName,
        total: null,
      };
    }
    return {
      next: buttonName,
      total: null,
    };
  }

  if (buttonName === '.') {
    if (obj.next) {
      if (obj.next.includes('.')) {
        return {};
      }
      return { next: obj.next + '.' };
    }
    if (obj.operation) {
      return { next: '0.' };
    }
    if (obj.total) {
      if (obj.total.includes('.')) {
        return {};
      }
      return { total: obj.total + '.' };
    }
    return { total: '0.' };
  }

  if (buttonName === '=') {
    if (obj.next && obj.operation) {
      return {
        total: operate(obj.total, obj.next, obj.operation),
        next: null,
        operation: null,
      };
    } else {
      return {};
    }
  }

  if (buttonName === '+/-') {
    if (obj.next) {
      return { next: (-1 * parseFloat(obj.next)).toString() };
    }
    if (obj.total) {
      return { total: (-1 * parseFloat(obj.total)).toString() };
    }
    return {};
  }

  if (buttonName === '√') {
    if (obj.next) {
      return {
        total: operate(obj.next, obj.next, buttonName),
        next: null,
        operation: buttonName,
      };
    }
  }

  if (buttonName === 'OFF') {
    return {
      total: null,
      next: null,
      operation: null,
    };
  }

  if (buttonName === 'MC') {
    return {
      memory: null
    };
  }
  if (buttonName === 'MR') {
    return {
      next: obj.memory
    };
  }
  if (buttonName === 'M-') {
    return {
      memory: Number(obj.memory) - Number(obj.total)
    };
  }
  if (buttonName === 'M+') {
    return {
      memory: Number(obj.memory) + Number(obj.total)
    };
  }
  // Button must be an operation


  if (obj.operation) {
    return {
      total: operate(obj.total, obj.next, obj.operation),
      next: null,
      operation: buttonName,
    };
  }


  if (!obj.next) {
    return { operation: buttonName };
  }

  return {
    total: obj.next,
    next: null,
    operation: buttonName,
  };
}

Operate.js

import Big from 'big.js';

export default function operate(numberOne, numberTwo, operation) {
  const one = Big(numberOne);
  const two = Big(numberTwo);
  if (operation === '+') {
    return one.plus(two).toString();
  }
  if (operation === '-') {
    return one.minus(two).toString();
  }
  if (operation === '*') {
    return one.times(two).toString();
  }
  if (operation === '/') {
    return one.div(two).toString();
  }
  if (operation === '%') {
    return one.mod(two).toString();
  }
  if (operation === '√') {
    return one.sqrt().toString();
  }
  throw Error(`Unknown operation '${operation}'`);
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.