Account Detail page
This commit is contained in:
@@ -89,19 +89,19 @@ gulp.task('serve:start', ['serve:static'], () => {
|
||||
//}
|
||||
|
||||
proxy: {
|
||||
'/user' : {
|
||||
'/user*' : {
|
||||
target: 'http://localhost:8080'
|
||||
},
|
||||
'/login' : {
|
||||
target: 'http://localhost:8080'
|
||||
},
|
||||
'/customers' : {
|
||||
'/customers*' : {
|
||||
target: 'http://localhost:8080'
|
||||
},
|
||||
'/accounts' : {
|
||||
'/accounts*' : {
|
||||
target: 'http://localhost:8080'
|
||||
},
|
||||
'/transfers' : {
|
||||
'/transfers*' : {
|
||||
target: 'http://localhost:8080'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,10 @@ import { ReduxRouter} from "redux-router";
|
||||
|
||||
//import { configure as reduxAuthConfigure, authStateReducer } from "redux-auth";
|
||||
//import { authStateReducer } from "redux-auth";
|
||||
import authStateReducer from './reducers/auth';
|
||||
import appStateReducer from './reducers/data'
|
||||
//import authStateReducer from './reducers/auth';
|
||||
//import appStateReducer from './reducers/data';
|
||||
import mainReducer from './reducers';
|
||||
|
||||
import { configure as reduxAuthConfigure } from './actions/configure';
|
||||
//import { AuthGlobals } from "redux-auth/bootstrap-theme";
|
||||
|
||||
@@ -36,13 +38,11 @@ import Account from "./views/Account";
|
||||
import SignIn from "./views/SignIn";
|
||||
import SignUp from "./views/SignUp";
|
||||
//import GlobalComponents from "./views/partials/GlobalComponents";
|
||||
const AuthGlobals = () => (<div></div>);
|
||||
|
||||
class App extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Container>
|
||||
<AuthGlobals />
|
||||
{this.props.children}
|
||||
</Container>
|
||||
);
|
||||
@@ -52,8 +52,7 @@ class App extends React.Component {
|
||||
export function initialize({cookies, isServer, currentLocation, userAgent} = {}) {
|
||||
|
||||
const reducer = combineReducers({
|
||||
auth: authStateReducer,
|
||||
app: appStateReducer,
|
||||
app: mainReducer,
|
||||
router: routerStateReducer
|
||||
});
|
||||
|
||||
|
||||
@@ -27,6 +27,10 @@ export const accountRefCreateComplete = makeActionCreator(T.ACCOUNTS.CREATE_REF_
|
||||
export const accountRefCreateError = makeActionCreator(T.ACCOUNTS.CREATE_REF_ERROR, 'error');
|
||||
export const accountRefCreateFormUpdate = makeActionCreator(T.ACCOUNTS.CREATE_REF_FORM_UPDATE, 'key', 'value');
|
||||
|
||||
export const accountRequested = makeActionCreator(T.ACCOUNT.SINGLE_START);
|
||||
export const accountComplete = makeActionCreator(T.ACCOUNT.SINGLE_COMPLETE, 'payload');
|
||||
export const accountError = makeActionCreator(T.ACCOUNT.SINGLE_ERROR, 'error');
|
||||
|
||||
|
||||
export function accountsList(userId) {
|
||||
return dispatch => {
|
||||
@@ -70,4 +74,17 @@ export function fetchOwnAccounts(customerId) {
|
||||
dispatch(accountsListReceived(data));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchAccount(accountId) {
|
||||
return dispatch => {
|
||||
dispatch(accountRequested());
|
||||
return api.apiRetrieveAccount(accountId)
|
||||
.then(data => {
|
||||
dispatch(accountComplete(data));
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch(accountError(err));
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -50,7 +50,7 @@ export function requireAuthentication(Component) {
|
||||
//token: state.auth.token,
|
||||
//userName: state.auth.userName,
|
||||
//isAuthenticated: state.auth.isAuthenticated
|
||||
isAuthenticated: state.auth.user.isSignedIn
|
||||
isAuthenticated: state.app.auth.user.isSignedIn
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
@@ -57,9 +57,9 @@ export class HeaderLinks extends React.Component {
|
||||
export default connect(({
|
||||
//dispatch,
|
||||
router,
|
||||
auth
|
||||
app
|
||||
}) => ({
|
||||
//dispatch,
|
||||
router,
|
||||
auth
|
||||
auth: app.auth
|
||||
}))(HeaderLinks);
|
||||
|
||||
@@ -44,6 +44,12 @@ export default defineActionTypes({
|
||||
CREATE_REF_COMPLETE
|
||||
CREATE_REF_ERROR
|
||||
CREATE_REF_FORM_UPDATE
|
||||
`,
|
||||
|
||||
ACCOUNT: `
|
||||
SINGLE_START
|
||||
SINGLE_COMPLETE
|
||||
SINGLE_ERROR
|
||||
`
|
||||
|
||||
})
|
||||
|
||||
@@ -96,4 +96,4 @@ class EmailSignInForm extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(({auth}) => ({auth}))(EmailSignInForm);
|
||||
export default connect(({app}) => ({auth: app.auth}))(EmailSignInForm);
|
||||
@@ -205,4 +205,4 @@ class EmailSignUpForm extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(({auth}) => ({auth}))(EmailSignUpForm);
|
||||
export default connect(({app}) => ({auth: app.auth}))(EmailSignUpForm);
|
||||
@@ -52,6 +52,18 @@ export const entities = (state = {...initialState}, action) => {
|
||||
...hashMap
|
||||
};
|
||||
}
|
||||
|
||||
case T.ACCOUNT.SINGLE_COMPLETE: {
|
||||
const { payload = {} } = action;
|
||||
const { accountId } = payload;
|
||||
if (!accountId) {
|
||||
return state;
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
[accountId]: payload
|
||||
};
|
||||
}
|
||||
case T.ENTITIES.RECEIVED_LIST:
|
||||
default:
|
||||
return state;
|
||||
|
||||
@@ -11,9 +11,9 @@ import { transfers } from './transfers';
|
||||
import { entities } from './entities';
|
||||
|
||||
const dataReducer = combineReducers({
|
||||
accounts,
|
||||
transfers,
|
||||
entities
|
||||
entities,
|
||||
accounts
|
||||
});
|
||||
|
||||
export default dataReducer;
|
||||
16
js-frontend/src/reducers/index.js
Normal file
16
js-frontend/src/reducers/index.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Created by andrew on 18/03/16.
|
||||
*/
|
||||
import { combineReducers } from 'redux';
|
||||
|
||||
import authStateReducer from './auth';
|
||||
import appStateReducer from './data'
|
||||
import uiReducer from './ui'
|
||||
|
||||
const mainReducer = combineReducers({
|
||||
auth: authStateReducer,
|
||||
data: appStateReducer,
|
||||
ui: uiReducer
|
||||
});
|
||||
|
||||
export default mainReducer;
|
||||
42
js-frontend/src/reducers/ui/account.js
Normal file
42
js-frontend/src/reducers/ui/account.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
import T from '../../constants/ACTION_TYPES';
|
||||
import { combineReducers } from 'redux';
|
||||
|
||||
|
||||
const initialState = {
|
||||
loading: false,
|
||||
errors: []
|
||||
};
|
||||
|
||||
export const account = (state = { ...initialState }, action ) => {
|
||||
switch(action.type) {
|
||||
case T.ACCOUNT.SINGLE_START: {
|
||||
return {
|
||||
...state,
|
||||
loading: true
|
||||
};
|
||||
}
|
||||
case T.ACCOUNT.SINGLE_COMPLETE: {
|
||||
return {
|
||||
...initialState
|
||||
};
|
||||
}
|
||||
case T.ACCOUNT.SINGLE_ERROR: {
|
||||
const { error } = action;
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
errors: [ error ]
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
15
js-frontend/src/reducers/ui/index.js
Normal file
15
js-frontend/src/reducers/ui/index.js
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
/**
|
||||
* Created by andrew on 25/02/16.
|
||||
*/
|
||||
import { combineReducers } from 'redux';
|
||||
|
||||
import { account } from './account';
|
||||
|
||||
const uiReducer = combineReducers({
|
||||
account
|
||||
});
|
||||
|
||||
export default uiReducer;
|
||||
@@ -68,7 +68,9 @@ export function apiCreateAccount(customerId, {
|
||||
export function apiRetrieveAccounts(customerId) {
|
||||
|
||||
const params = {customerId };
|
||||
const query = Object.keys(params).map(key => [encodeURIComponent(key), encodeURIComponent(params[key])].join('=')).join('&')
|
||||
const query = Object.keys(params).map(key => [encodeURIComponent(key), encodeURIComponent(params[key])].join('=')).join('&');
|
||||
|
||||
|
||||
return fetch(`${getAccountsUrl()}?${query}`, {
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
@@ -82,7 +84,7 @@ export function apiRetrieveAccounts(customerId) {
|
||||
}
|
||||
|
||||
export function apiRetrieveAccount(accountId) {
|
||||
return fetch(`${getCurrentUserUrl()}/${accountId}`, {
|
||||
return fetch(`${getAccountsUrl()}/${accountId}`, {
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
|
||||
@@ -6,16 +6,18 @@ import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { PageHeader, OverlayTrigger, Tooltip, Grid, Col, Row, Nav, NavItem, ButtonGroup, Button, Table } from "react-bootstrap";
|
||||
import * as BS from "react-bootstrap";
|
||||
import Select from "react-select";
|
||||
import Spinner from "react-loader";
|
||||
import { Link, IndexLink} from "react-router";
|
||||
|
||||
|
||||
import IndexPanel from "./../components/partials/IndexPanel";
|
||||
import * as Modals from './modals';
|
||||
|
||||
import * as A from '../actions/entities';
|
||||
|
||||
const resetModals = {
|
||||
showAccountModal: false,
|
||||
show3rdPartyAccountModal: false,
|
||||
showDeleteAccountModal: false
|
||||
showAccountModal: false
|
||||
};
|
||||
|
||||
export class Account extends React.Component {
|
||||
@@ -24,6 +26,17 @@ export class Account extends React.Component {
|
||||
this.state = { ...resetModals };
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const {
|
||||
id: customerId
|
||||
} = this.props.auth.user.attributes;
|
||||
this.props.dispatch(A.fetchOwnAccounts(customerId));
|
||||
|
||||
const { dispatch, params } = this.props;
|
||||
const { accountId } = params;
|
||||
dispatch(A.fetchAccount(accountId));
|
||||
}
|
||||
|
||||
createAccountModal() {
|
||||
this.setState({
|
||||
showAccountModal: true
|
||||
@@ -31,10 +44,12 @@ export class Account extends React.Component {
|
||||
}
|
||||
|
||||
createAccountModalConfirmed() {
|
||||
|
||||
debugger;
|
||||
}
|
||||
|
||||
accountChanged(){}
|
||||
accountChanged(){
|
||||
|
||||
}
|
||||
|
||||
close() {
|
||||
this.setState({
|
||||
@@ -44,14 +59,58 @@ export class Account extends React.Component {
|
||||
|
||||
render () {
|
||||
|
||||
debugger;
|
||||
|
||||
const { showAccountModal } = this.state;
|
||||
const { params } = this.props;
|
||||
const { loading, errors } = this.props.ui;
|
||||
const { entities, accounts } = this.props.data;
|
||||
const { accountId } = params;
|
||||
|
||||
const account = entities[accountId];
|
||||
|
||||
|
||||
if (loading) {
|
||||
return (<h2><Spinner ref="spinner" loaded={false} /> Loading..</h2>);
|
||||
}
|
||||
|
||||
if (!account) {
|
||||
if (errors.length) {
|
||||
return (<h2>Error loading specified account</h2>);
|
||||
} else {
|
||||
return (<h2><Spinner ref="spinner" loaded={false} /> Loading..</h2>);
|
||||
}
|
||||
}
|
||||
|
||||
const transferTo = [].concat(accounts.own.reduce((memo, item, idx) => {
|
||||
const { balance, title, accountId: itemAccountId } = item;
|
||||
|
||||
if (itemAccountId != accountId) {
|
||||
memo.push({
|
||||
value: itemAccountId ,
|
||||
label: `${title}: $${ Number(balance).toFixed(2) }`
|
||||
});
|
||||
}
|
||||
return memo;
|
||||
}, []),
|
||||
accounts.other.reduce((memo, item, idx) => {
|
||||
if (!((item.id == accountId) || (item.accountId == accountId))) {
|
||||
memo.push({
|
||||
value: item.accountId || item.id,
|
||||
label: `${item.title}${ item.description ? ': ' + item.description.substr(0, 10): '' }`
|
||||
});
|
||||
}
|
||||
return memo;
|
||||
}, []));
|
||||
|
||||
const { title = '[No title]', description: descriptionRaw, balance: balanceRaw } = account;
|
||||
|
||||
const balance = ((balanceRaw > 0 && balanceRaw < 1) ? '$0' : '$') + Number(balanceRaw).toFixed(2);
|
||||
|
||||
const description = descriptionRaw || '[No description provided]';
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageHeader>
|
||||
Accounts
|
||||
Account
|
||||
<Nav pullRight={true}>
|
||||
<ButtonGroup>
|
||||
<Button bsStyle={"link"} onClick={this.createAccountModal.bind(this)}>Edit</Button>
|
||||
@@ -64,17 +123,17 @@ export class Account extends React.Component {
|
||||
|
||||
<Row>
|
||||
<Col xs={4}>Title:</Col>
|
||||
<Col xs={8}><strong>Account Title #1</strong></Col>
|
||||
<Col xs={8}><strong>{ title }</strong></Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Col xs={4}>Balance:</Col>
|
||||
<Col xs={8}><strong>$100.00</strong></Col>
|
||||
<Col xs={8}><strong>{ balance }</strong></Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Col xs={4}>Description:</Col>
|
||||
<Col xs={8}><strong>Savings with progressive interest (0.7%)</strong></Col>
|
||||
<Col xs={8}><strong>{ description }</strong></Col>
|
||||
</Row>
|
||||
|
||||
</IndexPanel>
|
||||
@@ -91,19 +150,17 @@ export class Account extends React.Component {
|
||||
<Select
|
||||
value={''}
|
||||
clearable={false}
|
||||
options={[
|
||||
{value: "default", label: "Default"},
|
||||
{value: "bootstrap", label: "Bootstrap"},
|
||||
{value: "materialUi", label: "Material UI"}
|
||||
]}
|
||||
options={transferTo}
|
||||
onChange={this.accountChanged.bind(this)} />
|
||||
</Col>
|
||||
<Col xs={3}>
|
||||
<label>Amount:</label>
|
||||
<BS.Input type="text" />
|
||||
</Col>
|
||||
<Col xs={3}>
|
||||
<label>Description:</label>
|
||||
</Col>
|
||||
<BS.Input type="textarea" />
|
||||
</Col>
|
||||
<Col xs={2}>
|
||||
<br/>
|
||||
<Button bsStyle="primary">Transfer</Button>
|
||||
@@ -140,6 +197,7 @@ export class Account extends React.Component {
|
||||
|
||||
<Modals.NewAccountModal show={showAccountModal}
|
||||
action={this.createAccountModalConfirmed.bind(this)}
|
||||
account={{ loading: true }}
|
||||
onHide={this.close.bind(this)}
|
||||
key={0} />
|
||||
|
||||
@@ -150,4 +208,10 @@ export class Account extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(({auth}) => ({auth}))(Account);
|
||||
export default connect(({
|
||||
app
|
||||
}) => ({
|
||||
auth: app.auth,
|
||||
data: app.data,
|
||||
ui: app.ui.account
|
||||
}))(Account);
|
||||
@@ -283,8 +283,9 @@ class MyAccounts extends React.Component {
|
||||
</IndexPanel>
|
||||
*/
|
||||
|
||||
export default connect(({ auth, app }) => {
|
||||
export default connect(({ app }) => {
|
||||
return ({
|
||||
auth, app
|
||||
auth: app.auth,
|
||||
app: app.data
|
||||
})
|
||||
})(MyAccounts);
|
||||
@@ -62,9 +62,9 @@ export class SignIn extends React.Component {
|
||||
export default connect(({
|
||||
//dispatch,
|
||||
routes,
|
||||
auth
|
||||
app
|
||||
}) => ({
|
||||
//dispatch,
|
||||
routes,
|
||||
auth
|
||||
auth: app.auth
|
||||
}))(SignIn);
|
||||
|
||||
Reference in New Issue
Block a user