Skip to content

Commit

Permalink
feat: implementation of crypto currency calculator
Browse files Browse the repository at this point in the history
  • Loading branch information
yashwin committed Sep 26, 2019
1 parent e7f29dd commit b4a45bf
Show file tree
Hide file tree
Showing 19 changed files with 1,067 additions and 76 deletions.
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.19.0",
"bootstrap": "^4.3.1",
"node-sass": "^4.12.0",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-scripts": "3.1.2"
"react-redux": "^7.1.1",
"react-scripts": "3.1.2",
"react-select": "^3.0.5",
"reactstrap": "^8.0.1",
"redux": "^4.0.4",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts start",
Expand Down
Binary file modified public/favicon.ico
Binary file not shown.
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>Crypto Currency Calculator</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
22 changes: 0 additions & 22 deletions src/App.css

This file was deleted.

19 changes: 3 additions & 16 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import React from 'react';
import logo from './logo.svg';
import './App.css';
import './App.scss';
import Currencies from './modules/calculator/components/Currencies';

function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
<Currencies />
</div>
);
}
Expand Down
Empty file added src/App.scss
Empty file.
2 changes: 2 additions & 0 deletions src/config/service/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const API_BASE_PATH = "https://api.coinlore.com/api";
export const CURRENCY_LIST_URL = "tickers/";
31 changes: 31 additions & 0 deletions src/helpers/apiService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import axios from "axios";
import {API_BASE_PATH} from '../config/service';
export const WEB_REQUEST_TYPE = { POST: "POST", GET: "GET", DELETE: "DELETE", PUT: "PUT" };
/**
* Method for handling all api call to the server
* @param method
* @param url
* @param params
*/
axios.interceptors.response.use((response) => {
return response;
}, error => {
return Promise.reject(error.response);
});

export const getApiService = ( method, url) => {
return axios({
method: method,
url: url,
baseURL: API_BASE_PATH,
headers: {
"Content-Type": "application/json"
}
})
.then(response => {
return response;
})
.catch(error => {
throw JSON.stringify(error);
});
};
35 changes: 29 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import React from "react";
import axios from "axios";
import { API_BASE_PATH } from "./config/service";
import ReactDOM from "react-dom";
import ReduxThunk from "redux-thunk";
import { Provider } from "react-redux";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import { createStore, applyMiddleware, compose } from "redux";
import reducers from "./root-reducer";
import "bootstrap/dist/css/bootstrap.min.css";

ReactDOM.render(<App />, document.getElementById('root'));
axios.defaults.baseURL = API_BASE_PATH;
axios.defaults.headers.common["Content-Type"] = "application/json";

const composeEnhancers =
typeof window === "object" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
: compose;

const enhancer = composeEnhancers(applyMiddleware(ReduxThunk));
const store = createStore(reducers, enhancer);

ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
Expand Down
1 change: 0 additions & 1 deletion src/logo.svg

This file was deleted.

3 changes: 3 additions & 0 deletions src/modules/calculator/actionTypes/currencies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const GET_CURRENCY_LIST_REQUEST = "GET_CURRENCY_LIST_REQUEST";
export const GET_CURRENCY_LIST_SUCCESS = "GET_CURRENCY_LIST_SUCCESS";
export const GET_CURRENCY_LIST_FAILURE = "GET_CURRENCY_LIST_FAILURE";
27 changes: 27 additions & 0 deletions src/modules/calculator/actions/currencies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
GET_CURRENCY_LIST_REQUEST,
GET_CURRENCY_LIST_SUCCESS,
GET_CURRENCY_LIST_FAILURE
} from "../actionTypes/currencies";

import { getAllCurrencies } from "../services/currencies";

export const getCurrencies = () => dispatch => {
const params = "start=0&limit=30";
dispatch({
type: GET_CURRENCY_LIST_REQUEST
});
getAllCurrencies(params)
.then(data => {
dispatch({
type: GET_CURRENCY_LIST_SUCCESS,
payload: data.data
});
})
.catch(err => {
dispatch({
type: GET_CURRENCY_LIST_FAILURE,
payload: err
});
});
};
67 changes: 67 additions & 0 deletions src/modules/calculator/components/Calculator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { useEffect, useState, useRef } from "react";
import { Badge, FormGroup, Label, Input, InputGroup } from "reactstrap";

function Calculator(props) {

const [count, setCount] = useState();
const [price, setPrice] = useState();

const {currency} = props;

const handleCountChange = e => {
setCount(e.target.value);
const price = (e.target.value * currency.priceUSD).toFixed(2);
setPrice(price);
}

const handlePriceChange = (e) => {
setPrice(e.target.value);
const count = (e.target.value / currency.priceUSD).toFixed(2);
setCount(count);
}

const ref = useRef();

useEffect(() => {
setPrice((ref.current.props.value * currency.priceUSD).toFixed(2));
}, [currency]);

return (
<React.Fragment>
<h5 className="mt-5">{currency.symbol} to USD Converter</h5>
<FormGroup className="mt-4">
<Label for="coin-count-input">{currency.symbol}</Label>
<Badge className="ml-2" color="info">
PRICE - ${currency.priceUSD}
</Badge>
<InputGroup>
<Input
ref={ref}
value={count}
onChange={handleCountChange}
type="number"
name="count"
id="coin-count-input"
placeholder="Amount"
/>
</InputGroup>
</FormGroup>
<FormGroup className="mt-4">
<Label for="usd-input">USD</Label>
<InputGroup>
<Input
value={price}
onChange={handlePriceChange}
type="number"
name="usd"
id="usd-input"
placeholder="Price"
/>
</InputGroup>
</FormGroup>
</React.Fragment>
);

}

export default Calculator;
7 changes: 7 additions & 0 deletions src/modules/calculator/components/Calculator.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.SelectBox {
width: 20em;
}

.Container {
padding: 5em 10em;
}
89 changes: 89 additions & 0 deletions src/modules/calculator/components/Currencies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import { getCurrencies } from "../actions/currencies";
import { Row, Col, Badge } from "reactstrap";
import Select from "react-select";
import Calculator from "./Calculator";
import s from "./Calculator.module.scss";

function Currencies(props) {
const { currencyList, isFetchingCurrencies } = props;

const currencies = currencyList.map(currency => {
return {
value: currency.id,
label: currency.name,
priceUSD: currency.price_usd,
currentChange24Hours: currency.percent_change_24h,
symbol: currency.symbol
};
});

const [currency, setCurrency] = useState(0);

useEffect(() => {
if (!currencyList.length) {
props.getCurrencies();
}
});

function handleChange(selectedOption) {
setCurrency(selectedOption);
}

return (
<div className={s.Container}>
<h3 className="mt-2"> Crypto Currency Calculator</h3>
<Row className="mt-3">
<Col xl={4}>
<Select
className={s.SelectBox}
value={currency}
onChange={handleChange}
isDisabled={isFetchingCurrencies}
options={currencies}
placeholder={
isFetchingCurrencies ? "Loading, please wait" : "Select Currency"
}
/>
</Col>
<Col>
{currency.value && (
<div>
<span className="mr-1">Price</span>
<Badge color="primary" pill>
${currency.priceUSD}
</Badge>
<span className="ml-4">Current Change(24 Hours)</span>
<Badge className="ml-1" color="primary" pill>
{currency.currentChange24Hours} %
</Badge>
</div>
)}
</Col>
</Row>
{currency.value && (
<Row>
<Col xl={4}>
<Calculator currency={currency} />
</Col>
</Row>
)}
</div>
);
}

const mapStateToProps = ({ currencies }) => {
const { isFetchingCurrencies, currencyList, errorMessage } = currencies;

return {
isFetchingCurrencies,
currencyList,
errorMessage
};
};

export default connect(
mapStateToProps,
{ getCurrencies }
)(Currencies);
37 changes: 37 additions & 0 deletions src/modules/calculator/reducers/currencies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {
GET_CURRENCY_LIST_REQUEST,
GET_CURRENCY_LIST_SUCCESS,
GET_CURRENCY_LIST_FAILURE
} from "../actionTypes/currencies";

const initialState = {
isFetchingCurrencies: false,
currencyList: [],
errorMessage: ""
};

const currencies = (state = initialState, action) => {
switch (action.type) {
case GET_CURRENCY_LIST_REQUEST:
return {
...state,
isFetchingCurrencies: true
};
case GET_CURRENCY_LIST_SUCCESS:
return {
...state,
isFetchingCurrencies: false,
currencyList: action.payload
};
case GET_CURRENCY_LIST_FAILURE:
return {
...state,
isFetchingCurrencies: false,
errorMessage: action.payload
};
default:
return state;
}
};

export default currencies;
Loading

0 comments on commit b4a45bf

Please sign in to comment.