3
\$\begingroup\$

It is my first ReactJS App. If anyone can make me any code review? App was created to add currency transaction and display its value in Euro and PLN, the biggest transactions and the sum off all transactions. This app is available online here: https://nataliakielbicka.github.io/currency-converter-reactjs/

Thanks a lot!

import React from 'react';
import ReactDom from 'react-dom';
import App from './components/App';
import './main.css';

let list = [];
let storedList = localStorage.getItem("storedTasks");

if (storedList) {
  list = JSON.parse(storedList);
}

document
  .addEventListener('DOMContentLoaded', function () {
    ReactDom.render(
      <App storedList={list}/>, document.querySelector('#app'))
  });
  
//App.jsx
import React, { Component } from "react";
import axios from "axios";

import Title from "./views/Title";
import ExchangeRate from "./views/ExchangeRate";
import AddTransaction from "./views/AddTransaction";
import TransactionList from "./views/TransactionList";
import Footer from "./views/Footer";

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      exchangeRate: 0,
      list: this.props.storedList,
      name: "",
      amount: "",
      pln: "",
      validationNameError: false,
      validationAmountError: false
    };
    this.add = this.add.bind(this);
    this.handleNameChange = this.handleNameChange.bind(this);
    this.handleAmountChange = this.handleAmountChange.bind(this);
    this.remove = this.remove.bind(this);
    this.removeAll = this.removeAll.bind(this);
  }
  componentWillMount() {
    let apiURL = "https://api.nbp.pl/api/exchangerates/tables/A/?format=json";
    axios.get(apiURL).then(res => {
      const apiExchangeRate = res.data[0].rates[7].mid;
      this.setState({ exchangeRate: apiExchangeRate });
    });
  }
  handleNameChange(e) {
    let nameVal = e.target.value;
    this.setState({ name: nameVal, validationNameError: false });
  }
  handleAmountChange(e) {
    let amountVal = e.target.value;
    this.setState({
      amount: +amountVal,
      validationAmountError: false
    });
  }
  add(e) {
    e.preventDefault();
    let nameVal = document.getElementById("transactionName").value;
    let amountVal = document.getElementById("transactionValue").value;
    const nameValidator = new RegExp("^[a-zA-Z ]+$");
    const amountValidator = new RegExp("^(?!0.)\\d+$");
    const isNameValid = nameValidator.test(nameVal);
    const isAmountValid = amountValidator.test(amountVal);
    const newList = [
      {
        name: this.state.name,
        amount: this.state.amount,
        pln: +(this.state.amount * this.state.exchangeRate).toFixed(2)
      },
      ...this.state.list
    ];
    if (isNameValid && isAmountValid) {
      this.setState({ list: newList, name: "", amount: "" });
    } else if (isNameValid && !isAmountValid) {
      this.setState({
        validationAmountError: true,
        name: this.state.name,
        amount: ""
      });
    } else if (!isNameValid && isAmountValid) {
      this.setState({
        validationNameError: true,
        name: "",
        amount: this.state.amount
      });
    } else {
      this.setState({
        validationNameError: true,
        validationAmountError: true,
        name: "",
        amount: ""
      });
    }
    let updatedList = this.state.list;
    updatedList = newList;
    if (isNameValid && isAmountValid) {
      this.setState({ storedList: updatedList });
      this.updatedLocalStorage(updatedList);
    }
  }
  remove(index) {
    this.setState({
      list: this.state.list.filter((e, i) => i !== index)
    });
    let updatedList = this.state.list;
    updatedList = updatedList.filter((e, i) => i !== index);
    this.setState({ storedList: updatedList });
    this.updatedLocalStorage(updatedList);
  }
  removeAll(e) {
    e.preventDefault();
    this.setState({ list: [] });
    let updatedList = this.state.list;
    updatedList = [];
    this.setState({ storedList: updatedList });
    this.updatedLocalStorage(updatedList);
  }
  updatedLocalStorage(updatedList) {
    //console.log("task updated")
    localStorage.setItem("storedTasks", JSON.stringify(updatedList));
  }
  render() {
    return (
      <div className="currency">
        <Title />
        <ExchangeRate exchangeRate={this.state.exchangeRate} />
        <AddTransaction
          addItem={this.add}
          name={this.state.name}
          amount={this.state.amount}
          pln={this.state.pln}
          handleNameChange={this.handleNameChange}
          handleAmountChange={this.handleAmountChange}
          list={this.state.list}
          validationNameError={this.state.validationNameError}
          validationAmountError={this.state.validationAmountError}
        />
        <TransactionList
          list={this.state.list}
          removeListItem={this.remove}
          removeAll={this.removeAll}
        />
        <Footer />
      </div>
    );
  }
}

//AddTransaction
import React, { Component } from "react";
import PropTypes from "prop-types";

import ValidationNameError from "./ValidationNameError";
import ValidationAmountError from "./ValidationAmountError";

export default class AddTransaction extends Component {
  render() {
    return (
      <div className="currency__add-transation add-transaction">
        <h2 className="add-transaction__title">Add Transaction</h2>
        <form className="add-transaction__form form">
          <div className="form__col">
            <label htmlFor="transactionName" className="form__label">
              Name:
            </label>
            <input
              type="text"
              name="transactionName"
              id="transactionName"
              value={this.props.name}
              onChange={this.props.handleNameChange}
              className="form__input"
            />
          </div>
          <div className="form__col">
            <label htmlFor="transactionValue" className="form__label">
              Amount in Euro:
            </label>
            <input
              type="number"
              id="transactionValue"
              value={this.props.amount}
              onChange={this.props.handleAmountChange}
              className="form__input"
            />
          </div>
          <button className="form__btn" onClick={this.props.addItem}>
            add transaction
          </button>
          <div className="form__errors">
            {this.props.validationNameError ? <ValidationNameError /> : null}
            {this.props.validationAmountError ? (
              <ValidationAmountError />
            ) : null}
          </div>
        </form>
      </div>
    );
  }
}
AddTransaction.propTypes = {
  name: PropTypes.string
};

//Biggest Transaction
import React, { Component } from "react";

export default class BiggestTransaction extends Component {
  render() {
    return (
      <div className="currency__max-transaction max-transaction">
        <h3 className="max-transaction__title">The biggest transaction(s)</h3>
        <h4 className="max-transaction__name">{this.props.maxValueName}</h4>
        <div className="max-transaction__amount">
          Amount in Euro:
          <span className="max-transaction__value">
            {this.props.maxElementEuro}
          </span>
        </div>
        <div className="max-transaction__amount">
          Amount in PLN:
          <span className="max-transaction__value">
            {this.props.maxElementPln}
          </span>
        </div>
      </div>
    );
  }
}

//Exchange Rate
import React, { Component } from "react";

export default class ExchangeRate extends Component {
  render() {
    return (
      <h3 className="currency__exchange">
        1 EURO ={" "}
        <span className="currency__rate">{this.props.exchangeRate}</span>
        PLN
      </h3>
    );
  }
}

//Footer 
import React, { Component } from "react";

export default class Footer extends Component {
  render() {
    return (
      <footer className="currency__footer">
        <small>&copy; Copyright 2017 by Natalia Kiełbicka</small>
      </footer>
    );
  }
}

//Remove All
import React, { Component } from "react";

export default class RemoveAll extends Component {
  render() {
    return (
      <a
        href="#remove"
        className="currency__remove-all"
        title="remove all"
        onClick={this.props.removeAll}
      >
        Remove all transactions
      </a>
    );
  }
}

//SumTransaction
import React, { Component } from "react";

export default class SumTransaction extends Component {
  render() {
    return (
      <div className="currency__total total">
        <div className="total__container">
          <h3 className="total__desc">Total sum of all transactions:</h3>
          <div className="total__amount">
            in Euro:
            <span className="total__value">{this.props.totalAmountEuro}</span>
          </div>
          <div className="total__amount">
            in PLN:
            <span className="total__value">{this.props.totalAmountPln}</span>
          </div>
        </div>
      </div>
    );
  }
}

//Title
import React, { Component } from "react";

export default class Title extends Component {
  render() {
    return <h1 className="currency__title">Currency App</h1>;
  }
}

//Transaction Item
import React, { Component } from "react";

export default class TransactionItem extends Component {
  render() {
    return (
      <li className="transaction-list__item item">
        <span className="item__name">{this.props.name}</span>
        <span className="item__amount">
          Amount in Euro:
          <span className="item__value">{this.props.amount}</span>
        </span>
        <span className="item__amount">
          Amount in PLN:
          <span className="item__value">{this.props.pln}</span>
        </span>
        <button className="item__remove" onClick={this.props.removeItem}>
          x
        </button>
      </li>
    );
  }
}

//Transaction List
import React, { Component } from "react";
import TransactionItem from "./TransactionItem";
import SumTransaction from "./SumTransaction";
import BiggestTransaction from "./BiggestTransaction";
import RemoveAll from "./RemoveAll";

export default class TransactionList extends Component {
  render() {
    const listItems = this.props.list.map((elem, i) => {
      return (
        <TransactionItem
          key={i}
          name={elem.name}
          amount={elem.amount}
          pln={elem.pln}
          removeItem={this.props.removeListItem.bind(this, i)}
        />
      );
    });

    const maxElementEuro = Math.max.apply(
      Math,
      listItems.map(item => item.props.amount)
    );
    const maxElementPln = Math.max.apply(
      Math,
      listItems.map(item => item.props.pln)
    );
    const maxValueObject = listItems.filter(
      item => item.props.amount === maxElementEuro
    );
    const maxValueNameArr = maxValueObject.map(item => item.props.name);
    const maxValueName = maxValueNameArr.join(", ");

    function sumProperty(arr, type) {
      return arr.reduce((total, obj) => {
        return total + obj.props[type];
      }, 0);
    }
    let totalAmountEuro = sumProperty(listItems, "amount");
    let totalAmountPln = sumProperty(listItems, "pln").toFixed(2);
    return (
      <div className="currency__transaction-list transaction-list">
        <ul className="transaction-list__list">{listItems}</ul>
        {listItems.length ? (
          <div>
            <BiggestTransaction
              maxElementPln={maxElementPln}
              maxElementEuro={maxElementEuro}
              maxValueName={maxValueName}
            />
            <SumTransaction
              totalAmountEuro={totalAmountEuro}
              totalAmountPln={totalAmountPln}
            />
            <RemoveAll removeAll={this.props.removeAll} />
          </div>
        ) : null}
      </div>
    );
  }
}

//ValidationAmountError
import React, { Component } from "react";

export default class ValidationAmountError extends Component {
  render() {
    return (
      <span className="form__error">
        The amount should be an integer number.
      </span>
    );
  }
}

//ValidationNameError
import React, { Component } from "react";

export default class ValidationNameError extends Component {
  render() {
    return (
      <span className="form__error">
        Please, fill in the name of a transaction.
      </span>
    );
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

\$\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.