From 35fc8b8a1c2fc2938a356b5d35f8a36c4ee2a8d1 Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 26 Jul 2017 17:21:53 -0500 Subject: [PATCH] feature(balance + currency): dynamic balance in Nav plus add currency in reducer --- app/api/index.js | 10 ++++ app/reducers/activity.js | 6 +-- app/reducers/balance.js | 52 ++++++++++++++++++ app/reducers/index.js | 6 +++ app/reducers/info.js | 50 +++++++++++++++++ app/reducers/ticker.js | 54 +++++++++++++++++++ app/routes/activity/components/Activity.js | 25 +++++---- app/routes/activity/components/Activity.scss | 2 +- .../components/components/Invoices.js | 2 +- .../components/components/Invoices.scss | 1 - app/routes/app/components/App.js | 13 ++++- app/routes/app/components/components/Nav.js | 32 +++++++---- app/routes/app/components/components/Nav.scss | 31 ++++++++--- app/routes/app/containers/AppContainer.js | 14 ++++- package-lock.json | 30 +++++++++++ package.json | 1 + 16 files changed, 293 insertions(+), 36 deletions(-) create mode 100644 app/reducers/balance.js create mode 100644 app/reducers/info.js create mode 100644 app/reducers/ticker.js diff --git a/app/api/index.js b/app/api/index.js index c250ceec..c6e4fa41 100644 --- a/app/api/index.js +++ b/app/api/index.js @@ -31,4 +31,14 @@ export function callApi(endpoint, method = 'get', data = null) { export function callApis(endpoints) { const BASE_URL = 'http://localhost:3000/api/' return axios.all(endpoints.map(endpoint => callApi(endpoint))) +} + +export function requestTicker() { + const BASE_URL = 'https://api.coinmarketcap.com/v1/ticker/bitcoin/' + return axios({ + method: 'get', + url: BASE_URL + }) + .then(response => response.data) + .catch(error => error) } \ No newline at end of file diff --git a/app/reducers/activity.js b/app/reducers/activity.js index 7d5fd9e4..0521ef9a 100644 --- a/app/reducers/activity.js +++ b/app/reducers/activity.js @@ -32,15 +32,15 @@ export const fetchActivity = () => async (dispatch) => { // Action Handlers // ------------------------------------ const ACTION_HANDLERS = { - [GET_ACTIVITY]: (state) => ({ ...state, isLoading: true }), - [RECEIVE_ACTIVITY]: (state, { payments, invoices }) => ({ ...state, isLoading: false, payments, invoices }) + [GET_ACTIVITY]: (state) => ({ ...state, activityLoading: true }), + [RECEIVE_ACTIVITY]: (state, { payments, invoices }) => ({ ...state, activityLoading: false, payments, invoices }) } // ------------------------------------ // Reducer // ------------------------------------ const initialState = { - isLoading: false, + activityLoading: false, payments: [], invoices: [] } diff --git a/app/reducers/balance.js b/app/reducers/balance.js new file mode 100644 index 00000000..6acb54ab --- /dev/null +++ b/app/reducers/balance.js @@ -0,0 +1,52 @@ +import { callApis } from '../api' +// ------------------------------------ +// Constants +// ------------------------------------ +export const GET_BALANCE = 'GET_BALANCE' +export const RECEIVE_BALANCE = 'RECEIVE_BALANCE' + +// ------------------------------------ +// Actions +// ------------------------------------ +export function getBalance() { + return { + type: GET_BALANCE + } +} + +export function receiveBalance(data) { + return { + type: RECEIVE_BALANCE, + walletBalance: data[0].data.balance, + channelBalance: data[1].data.balance + } +} + +export const fetchBalance = () => async (dispatch) => { + dispatch(getBalance()) + const balance = await callApis(['wallet_balance', 'channel_balance']) + dispatch(receiveBalance(balance)) +} + +// ------------------------------------ +// Action Handlers +// ------------------------------------ +const ACTION_HANDLERS = { + [GET_BALANCE]: (state) => ({ ...state, balanceLoading: true }), + [RECEIVE_BALANCE]: (state, { walletBalance, channelBalance }) => ({ ...state, balanceLoading: false, walletBalance, channelBalance }) +} + +// ------------------------------------ +// Reducer +// ------------------------------------ +const initialState = { + balanceLoading: false, + walletBalance: null, + channelBalance: null +} + +export default function balanceReducer(state = initialState, action) { + const handler = ACTION_HANDLERS[action.type] + + return handler ? handler(state, action) : state +} \ No newline at end of file diff --git a/app/reducers/index.js b/app/reducers/index.js index ccb744d8..b58106c0 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -1,10 +1,16 @@ // @flow import { combineReducers } from 'redux' import { routerReducer as router } from 'react-router-redux' +import ticker from './ticker' +import info from './info' +import balance from './balance' import activity from './activity' const rootReducer = combineReducers({ router, + ticker, + info, + balance, activity }) diff --git a/app/reducers/info.js b/app/reducers/info.js new file mode 100644 index 00000000..1096762e --- /dev/null +++ b/app/reducers/info.js @@ -0,0 +1,50 @@ +import { callApi } from '../api' +// ------------------------------------ +// Constants +// ------------------------------------ +export const GET_INFO = 'GET_INFO' +export const RECEIVE_INFO = 'RECEIVE_INFO' + +// ------------------------------------ +// Actions +// ------------------------------------ +export function getInfo() { + return { + type: GET_INFO + } +} + +export function receiveInfo(data) { + return { + type: RECEIVE_INFO, + data + } +} + +export const fetchInfo = () => async (dispatch) => { + dispatch(getInfo()) + const info = await callApi('info') + dispatch(receiveInfo(info.data)) +} + +// ------------------------------------ +// Action Handlers +// ------------------------------------ +const ACTION_HANDLERS = { + [GET_INFO]: (state) => ({ ...state, infoLoading: true }), + [RECEIVE_INFO]: (state, { data }) => ({ ...state, infoLoading: false, data }) +} + +// ------------------------------------ +// Reducer +// ------------------------------------ +const initialState = { + infoLoading: false, + data: {} +} + +export default function infoReducer(state = initialState, action) { + const handler = ACTION_HANDLERS[action.type] + + return handler ? handler(state, action) : state +} \ No newline at end of file diff --git a/app/reducers/ticker.js b/app/reducers/ticker.js new file mode 100644 index 00000000..ea66d3b5 --- /dev/null +++ b/app/reducers/ticker.js @@ -0,0 +1,54 @@ +import { requestTicker } from '../api' +// ------------------------------------ +// Constants +// ------------------------------------ +export const GET_TICKER = 'GET_TICKER' +export const RECIEVE_TICKER = 'RECIEVE_TICKER' + +// ------------------------------------ +// Actions +// ------------------------------------ +export function getTicker() { + return { + type: GET_TICKER + } +} + +export function recieveTicker(ticker) { + return { + type: RECIEVE_TICKER, + ticker + } +} + +export const fetchTicker = () => async (dispatch) => { + dispatch(getTicker()) + const ticker = await requestTicker() + dispatch(recieveTicker(ticker)) + + return ticker +} + +// ------------------------------------ +// Action Handlers +// ------------------------------------ +const ACTION_HANDLERS = { + [GET_TICKER]: (state) => ({ ...state, tickerLoading: true }), + [RECIEVE_TICKER]: (state, { ticker }) => ({...state, btcTicker: ticker[0] }) +} + +// ------------------------------------ +// Reducer +// ------------------------------------ +const initialState = { + tickerLoading: false, + current: 'btc', + crypto: 'btc', + btcTicker: null +} + +export default function tickerReducer(state = initialState, action) { + const handler = ACTION_HANDLERS[action.type] + + return handler ? handler(state, action) : state +} \ No newline at end of file diff --git a/app/routes/activity/components/Activity.js b/app/routes/activity/components/Activity.js index 4f9c87b6..aafc6761 100644 --- a/app/routes/activity/components/Activity.js +++ b/app/routes/activity/components/Activity.js @@ -1,5 +1,6 @@ // @flow import React, { Component } from 'react' +import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup' import { MdSearch } from 'react-icons/lib/md' import Payments from './components/Payments' import Invoices from './components/Invoices' @@ -9,7 +10,7 @@ class Activity extends Component { constructor(props, context) { super(props, context) this.state = { - tab: 2 + tab: 1 } } @@ -19,9 +20,9 @@ class Activity extends Component { render() { const { tab } = this.state - const { activity: { isLoading, payments, invoices } } = this.props + const { activity: { activityLoading, payments, invoices } } = this.props - if (isLoading) { return
Loading...
} + if (activityLoading) { return
Loading...
} return (
@@ -47,12 +48,18 @@ class Activity extends Component {
- { - tab === 1 ? - - : - - } + + { + tab === 1 ? + + : + + } +
diff --git a/app/routes/activity/components/Activity.scss b/app/routes/activity/components/Activity.scss index 85a0585d..d3b30b42 100644 --- a/app/routes/activity/components/Activity.scss +++ b/app/routes/activity/components/Activity.scss @@ -98,4 +98,4 @@ .right { text-align: right; } -} +} \ No newline at end of file diff --git a/app/routes/activity/components/components/Invoices.js b/app/routes/activity/components/components/Invoices.js index 760c2243..5b27540e 100644 --- a/app/routes/activity/components/components/Invoices.js +++ b/app/routes/activity/components/components/Invoices.js @@ -25,7 +25,7 @@ class Invoices extends Component { invoices.map((invoice, index) => (
  • -
    {invoice.payment_request}
    +
    {`${invoice.payment_request.substring(0, 75)}...`}
    {invoice.memo}
    diff --git a/app/routes/activity/components/components/Invoices.scss b/app/routes/activity/components/components/Invoices.scss index 6a8b3239..9f1ae063 100644 --- a/app/routes/activity/components/components/Invoices.scss +++ b/app/routes/activity/components/components/Invoices.scss @@ -13,7 +13,6 @@ .left { flex: 7; - font-size: 12px; } .center { diff --git a/app/routes/app/components/App.js b/app/routes/app/components/App.js index 5c1c19c7..769b6c09 100644 --- a/app/routes/app/components/App.js +++ b/app/routes/app/components/App.js @@ -4,12 +4,20 @@ import Nav from './components/Nav.js' import styles from './App.scss' class App extends Component { + componentWillMount() { + const { fetchTicker, fetchBalance } = this.props + + fetchTicker() + fetchBalance() + } + render() { + const { ticker, balance, children } = this.props return (
    -
    ) @@ -17,6 +25,7 @@ class App extends Component { } App.propTypes = { + ticker: React.PropTypes.object, children: React.PropTypes.object } diff --git a/app/routes/app/components/components/Nav.js b/app/routes/app/components/components/Nav.js index cf79866d..e6acdfff 100644 --- a/app/routes/app/components/components/Nav.js +++ b/app/routes/app/components/components/Nav.js @@ -4,31 +4,40 @@ import { Link } from 'react-router-dom' import ReactSVG from 'react-svg' import { MdAccountBalanceWallet, MdSettings } from 'react-icons/lib/md' import { FaClockO, FaBitcoin, FaDollar } from 'react-icons/lib/fa' +import { satoshisToBtc } from '../../../../utils/bitcoin' import styles from './Nav.scss' class Nav extends Component { render() { + console.log('props: ', this.props) + const { ticker, balance } = this.props return (