feature: add TransactionsView module

This commit is contained in:
George Lima 2018-12-15 19:36:50 -03:00
parent 20e44f3f96
commit b5f5ca1fdb
6 changed files with 182 additions and 0 deletions

View File

@ -0,0 +1,61 @@
// @flow
import { connect } from 'react-redux';
import eres from 'eres';
import flow from 'lodash.flow';
import groupBy from 'lodash.groupby';
import dateFns from 'date-fns';
import { TransactionsView } from '../views/transactions';
import {
loadTransactions,
loadTransactionsSuccess,
loadTransactionsError,
} from '../redux/modules/transactions';
import rpc from '../../services/api';
import store from '../../config/electron-store';
import type { AppState } from '../types/app-state';
import type { Dispatch } from '../types/redux';
const mapStateToProps = ({ transactions }: AppState) => ({
transactions: transactions.list,
isLoading: transactions.isLoading,
error: transactions.error,
zecPrice: transactions.zecPrice,
});
const mapDispatchToProps = (dispatch: Dispatch) => ({
getTransactions: async () => {
dispatch(loadTransactions());
const [transactionsErr, transactions = []] = await eres(
rpc.listtransactions(),
);
if (transactionsErr) {
return dispatch(
loadTransactionsError({ error: transactionsErr.message }),
);
}
dispatch(
loadTransactionsSuccess({
list: flow([
arr => arr.map(transaction => ({
type: transaction.category,
date: new Date(transaction.time * 1000).toISOString(),
address: transaction.address,
amount: Math.abs(transaction.amount),
})),
arr => groupBy(arr, obj => dateFns.format(obj.date, 'MMM DD, YYYY')),
])(transactions),
zecPrice: store.get('ZEC_DOLLAR_PRICE'),
}),
);
},
});
export const TransactionsContainer = connect(
mapStateToProps,
mapDispatchToProps,
)(TransactionsView);

View File

@ -5,8 +5,10 @@ import { connectRouter } from 'connected-react-router';
import type { RouterHistory } from 'react-router-dom';
import wallet from './wallet';
import transactions from './transactions';
export const createRootReducer = (history: RouterHistory) => combineReducers({
walletSummary: wallet,
transactions,
router: connectRouter(history),
});

View File

@ -0,0 +1,64 @@
// @flow
import type { Action } from '../../types/redux';
import type { Transaction } from '../../components/transaction-item';
// Actions
export const LOAD_TRANSACTIONS = 'LOAD_TRANSACTIONS';
export const LOAD_TRANSACTIONS_SUCCESS = 'LOAD_TRANSACTIONS_SUCCESS';
export const LOAD_TRANSACTIONS_ERROR = 'LOAD_TRANSACTIONS_ERROR';
export const loadTransactions = () => ({
type: LOAD_TRANSACTIONS,
payload: {},
});
export const loadTransactionsSuccess = ({
list,
zecPrice,
}: {
list: { [day: string]: Transaction[] },
zecPrice: number,
}) => ({
type: LOAD_TRANSACTIONS_SUCCESS,
payload: {
list,
zecPrice,
},
});
export const loadTransactionsError = ({ error }: { error: string }) => ({
type: LOAD_TRANSACTIONS_ERROR,
payload: { error },
});
export type State = {
isLoading: boolean,
error: string | null,
list: { [day: string]: Transaction[] },
zecPrice: number,
};
const initialState = {
zecPrice: 0,
list: {},
error: null,
isLoading: false,
};
export default (state: State = initialState, action: Action) => {
switch (action.type) {
case LOAD_TRANSACTIONS:
return { ...state, error: null, isLoading: true };
case LOAD_TRANSACTIONS_SUCCESS:
return {
...state,
...action.payload,
isLoading: false,
error: null,
};
case LOAD_TRANSACTIONS_ERROR:
return { ...state, isLoading: false, error: action.payload.error };
default:
return state;
}
};

View File

@ -7,6 +7,7 @@ import styled from 'styled-components';
import { ScrollTopComponent } from './scroll-top';
import { SidebarContainer } from '../containers/sidebar';
import { DashboardContainer } from '../containers/dashboard';
import { TransactionsContainer } from '../containers/transactions';
import { SendView } from '../views/send';
import { ReceiveView } from '../views/receive';
import { SettingsView } from '../views/settings';
@ -21,6 +22,7 @@ import {
RECEIVE_ROUTE,
SETTINGS_ROUTE,
CONSOLE_ROUTE,
TRANSACTIONS_ROUTE,
} from '../constants/routes';
const FullWrapper = styled.div`
@ -59,6 +61,10 @@ export const RouterComponent = ({ location }: { location: Location }) => (
<Route path={RECEIVE_ROUTE} component={ReceiveView} />
<Route path={SETTINGS_ROUTE} component={SettingsView} />
<Route path={CONSOLE_ROUTE} component={ConsoleView} />
<Route
path={TRANSACTIONS_ROUTE}
component={TransactionsContainer}
/>
<Route component={NotFoundView} />
</Switch>
</LayoutComponent>

View File

@ -1,7 +1,9 @@
// @flow
import type { State as WalletSummaryState } from '../redux/modules/wallet';
import type { State as TransactionsState } from '../redux/modules/transactions';
export type AppState = {
walletSummary: WalletSummaryState,
transactions: TransactionsState,
};

47
app/views/transactions.js Normal file
View File

@ -0,0 +1,47 @@
// @flow
import React, { Component, Fragment } from 'react';
import { TransactionDailyComponent } from '../components/transaction-daily';
import type { Transaction } from '../components/transaction-item';
type Props = {
isLoading: boolean,
error: string | null,
transactions: { [day: string]: Transaction[] },
zecPrice: number,
getTransactions: () => void,
};
export class TransactionsView extends Component<Props> {
componentDidMount() {
// eslint-disable-next-line
this.props.getTransactions();
}
render() {
const {
error, isLoading, transactions, zecPrice,
} = this.props;
if (error) {
return error;
}
const days = Object.keys(transactions);
return (
<Fragment>
{isLoading
? 'Loading'
: days.map(day => (
<TransactionDailyComponent
transactionsDate={day}
transactions={transactions[day]}
zecPrice={zecPrice}
/>
))}
</Fragment>
);
}
}