Form validation for Sign In & Sign Up

This commit is contained in:
Andrew Revinsky (DART)
2016-09-13 18:49:40 +03:00
parent 0b39ba658a
commit 20cc17c68c
11 changed files with 216 additions and 46 deletions

View File

@@ -175,7 +175,7 @@ webpackJsonp([0,3],{
{ path: "/", component: App },
_react2.default.createElement(_reactRouter.IndexRoute, { component: (0, _AuthComponent.requireAuthentication)(_MyAccounts2.default) }),
_react2.default.createElement(_reactRouter.Route, { path: "signin", component: _SignIn2.default, onEnter: onEnter }),
_react2.default.createElement(_reactRouter.Route, { path: "register", component: _SignUp2.default }),
_react2.default.createElement(_reactRouter.Route, { path: "register", component: _SignUp2.default, onEnter: onEnter }),
_react2.default.createElement(_reactRouter.Route, { path: "account/:accountId", component: (0, _AuthComponent.requireAuthentication)(_Account2.default) })
);
@@ -1101,7 +1101,7 @@ webpackJsonp([0,3],{
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.signUpReducer = undefined;
exports.signUpReducer = exports.internalSignUpReducer = undefined;
var _ACTION_TYPES = __webpack_require__(295);
@@ -1116,7 +1116,30 @@ webpackJsonp([0,3],{
/**
* Created by andrew on 25/02/16.
*/
var signUpReducer = exports.signUpReducer = (0, _createFormReducer2.default)([_ACTION_TYPES2.default.AUTH.SIGN_UP_START, _ACTION_TYPES2.default.AUTH.SIGN_UP_COMPLETE, _ACTION_TYPES2.default.AUTH.SIGN_UP_ERROR, _ACTION_TYPES2.default.AUTH.SIGN_UP_FORM_UPDATE]);
var internalSignUpReducer = exports.internalSignUpReducer = (0, _createFormReducer2.default)([_ACTION_TYPES2.default.AUTH.SIGN_UP_START, _ACTION_TYPES2.default.AUTH.SIGN_UP_COMPLETE, _ACTION_TYPES2.default.AUTH.SIGN_UP_ERROR, _ACTION_TYPES2.default.AUTH.SIGN_UP_FORM_UPDATE]);
var signUpReducer = exports.signUpReducer = function signUpReducer(state, action) {
switch (action.type) {
case _ACTION_TYPES2.default.LOCATION.ENTER:
{
var location = action.location;
var pathname = location.pathname;
if (pathname == '/register') {
return internalSignUpReducer(state, {
type: _ACTION_TYPES2.default.AUTH.SIGN_UP_ERROR,
error: null
});
}
return state;
}
default:
{
return internalSignUpReducer(state, action);
}
}
};
/* REACT HOT LOADER */ }).call(this); } finally { if (false) { (function () { var foundReactClasses = module.hot.data && module.hot.data.foundReactClasses || false; if (module.exports && module.makeHot) { var makeExportsHot = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/makeExportsHot.js"); if (makeExportsHot(module, require("react"))) { foundReactClasses = true; } var shouldAcceptModule = true && foundReactClasses; if (shouldAcceptModule) { module.hot.accept(function (err) { if (err) { console.error("Cannot not apply hot update to " + "signup.js" + ": " + err.message); } }); } } module.hot.dispose(function (data) { data.makeHot = module.makeHot; data.foundReactClasses = foundReactClasses; }); })(); } }
@@ -6168,7 +6191,7 @@ webpackJsonp([0,3],{
if (v.entryType == 'account') {
balance = v.initialBalance;
} else if (v.entryType == 'transaction') {
} else if (v.entryType == 'transaction' && v.status !== 'FAILED_DUE_TO_INSUFFICIENT_FUNDS') {
var isOriginating = v.fromAccountId == currentAccountId;
balance += (isOriginating ? -1 : 1) * v.amount;
}
@@ -6583,6 +6606,8 @@ webpackJsonp([0,3],{
var _signIn = __webpack_require__(606);
var AS = _interopRequireWildcard(_signIn);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -6596,17 +6621,26 @@ webpackJsonp([0,3],{
*/
/*
<Input type="password"
label="Password"
className="email-sign-in-password"
placeholder="Password"
disabled={disabled}
value={this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "form", "password"])}
errors={this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "errors", "password"])}
onChange={this.handleInput.bind(this, "password")}
{...this.props.inputProps.password} />
*/
var formValidation = function formValidation(payload) {
return ['email', 'password'].reduce(function (memo, prop) {
var result = [];
var value = (payload[prop] || '').replace(/(^\s+)|(\s+$)/g, '');
switch (prop) {
case 'email':
case 'password':
if (/^$/.test(value)) {
result.push('required');
}
}
if (result.length) {
memo[prop] = result;
memo.hasErrors = true;
}
return memo;
}, {});
};
var EmailSignInForm = exports.EmailSignInForm = function (_React$Component) {
_inherits(EmailSignInForm, _React$Component);
@@ -6620,7 +6654,7 @@ webpackJsonp([0,3],{
_createClass(EmailSignInForm, [{
key: "handleInput",
value: function handleInput(key, val) {
this.props.dispatch((0, _signIn.emailSignInFormUpdate)(key, val));
this.props.dispatch(AS.emailSignInFormUpdate(key, val));
}
}, {
key: "handleSubmit",
@@ -6628,7 +6662,14 @@ webpackJsonp([0,3],{
event.preventDefault();
var formData = (0, _readProp2.default)(this.props.auth, 'signIn.form');
this.props.dispatch((0, _signIn.emailSignIn)(formData));
var validationErrors = formValidation(formData);
if (validationErrors.hasErrors) {
this.props.dispatch(AS.emailSignInError(validationErrors));
return;
}
this.props.dispatch(AS.emailSignIn(formData));
}
}, {
key: "render",
@@ -6940,6 +6981,10 @@ webpackJsonp([0,3],{
var _signUp = __webpack_require__(610);
var AS = _interopRequireWildcard(_signUp);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -6951,6 +6996,38 @@ webpackJsonp([0,3],{
*/
var formValidation = function formValidation(payload) {
return ['fname', 'lname', 'email', 'password', 'passwordConfirm', 'ssn', 'phoneNumber', 'address1', 'address2', 'city', 'state', 'zip'].reduce(function (memo, prop) {
var result = [];
var value = (payload[prop] || '').replace(/(^\s+)|(\s+$)/g, '');
switch (prop) {
case 'fname':
case 'lname':
case 'email':
case 'ssn':
case 'password':
case 'passwordConfirm':
if (/^$/.test(value)) {
result.push('required');
}
}
switch (prop) {
case 'passwordConfirm':
if (value != payload['password']) {
result.push('need to be equal to password');
}
}
if (result.length) {
memo[prop] = result;
memo.hasErrors = true;
}
return memo;
}, {});
};
var EmailSignUpForm = function (_React$Component) {
_inherits(EmailSignUpForm, _React$Component);
@@ -6963,7 +7040,7 @@ webpackJsonp([0,3],{
_createClass(EmailSignUpForm, [{
key: "handleInput",
value: function handleInput(key, val) {
this.props.dispatch((0, _signUp.emailSignUpFormUpdate)(key, val));
this.props.dispatch(AS.emailSignUpFormUpdate(key, val));
}
}, {
key: "handleSubmit",
@@ -6971,7 +7048,13 @@ webpackJsonp([0,3],{
event.preventDefault();
var formData = (0, _readProp2.default)(this.props.auth, 'signUp.form');
this.props.dispatch((0, _signUp.emailSignUp)((0, _formToPayloadMappers.customerInfoMap)(formData)));
var validationErrors = formValidation(formData);
if (validationErrors.hasErrors) {
this.props.dispatch(AS.emailSignUpError(validationErrors));
return;
}
this.props.dispatch(AS.emailSignUp((0, _formToPayloadMappers.customerInfoMap)(formData)));
}
}, {
key: "render",
@@ -7256,4 +7339,4 @@ webpackJsonp([0,3],{
/***/ }
});
//# sourceMappingURL=app.d5e626aaea52a2dac6cb.js.map
//# sourceMappingURL=app.4d33d25a9b5872086180.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -13,7 +13,7 @@
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap-theme.min.css"><link href="/style.6734b6ac5d23d61b8e5f.css" rel="stylesheet"></head>
<body><div id="root"></div><script src="/manifest.4fffd5bbc120d3bf86c4.js"></script><script src="/vendor.829a6cd5501868837732.js"></script><script src="/style.6734b6ac5d23d61b8e5f.js"></script><script src="/app.d5e626aaea52a2dac6cb.js"></script><script>
<body><div id="root"></div><script src="/manifest.9a73c590403a64f40c41.js"></script><script src="/vendor.829a6cd5501868837732.js"></script><script src="/style.6734b6ac5d23d61b8e5f.js"></script><script src="/app.4d33d25a9b5872086180.js"></script><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
@@ -27,5 +27,5 @@
ga('send', 'pageview');
</script><!--{"files":{"publicPath":"/","chunks":{"manifest":{"size":0,"entry":"/manifest.4fffd5bbc120d3bf86c4.js","hash":"4fffd5bbc120d3bf86c4","css":[]},"vendor":{"size":1670874,"entry":"/vendor.829a6cd5501868837732.js","hash":"829a6cd5501868837732","css":[]},"style":{"size":122,"entry":"/style.6734b6ac5d23d61b8e5f.js","hash":"6734b6ac5d23d61b8e5f","css":["/style.6734b6ac5d23d61b8e5f.css"]},"app":{"size":349686,"entry":"/app.d5e626aaea52a2dac6cb.js","hash":"d5e626aaea52a2dac6cb","css":[]}},"js":["/manifest.4fffd5bbc120d3bf86c4.js","/vendor.829a6cd5501868837732.js","/style.6734b6ac5d23d61b8e5f.js","/app.d5e626aaea52a2dac6cb.js"],"css":["/style.6734b6ac5d23d61b8e5f.css"]},"options":{"template":"/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/html-webpack-plugin/lib/loader.js!/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/public/index.ejs","filename":"index.html","hash":false,"inject":false,"compile":true,"favicon":false,"minify":false,"cache":true,"showErrors":true,"chunks":"all","excludeChunks":[],"title":"Money Transfer App","xhtml":false,"description":"ES Money Transfer App","appMountId":"root","googleAnalytics":{"trackingId":"UA-XXXX-XX","pageViewOnLoad":true},"mobile":true}}--></body>
</script><!--{"files":{"publicPath":"/","chunks":{"manifest":{"size":0,"entry":"/manifest.9a73c590403a64f40c41.js","hash":"9a73c590403a64f40c41","css":[]},"vendor":{"size":1670874,"entry":"/vendor.829a6cd5501868837732.js","hash":"829a6cd5501868837732","css":[]},"style":{"size":122,"entry":"/style.6734b6ac5d23d61b8e5f.js","hash":"6734b6ac5d23d61b8e5f","css":["/style.6734b6ac5d23d61b8e5f.css"]},"app":{"size":351970,"entry":"/app.4d33d25a9b5872086180.js","hash":"4d33d25a9b5872086180","css":[]}},"js":["/manifest.9a73c590403a64f40c41.js","/vendor.829a6cd5501868837732.js","/style.6734b6ac5d23d61b8e5f.js","/app.4d33d25a9b5872086180.js"],"css":["/style.6734b6ac5d23d61b8e5f.css"]},"options":{"template":"/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/html-webpack-plugin/lib/loader.js!/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/public/index.ejs","filename":"index.html","hash":false,"inject":false,"compile":true,"favicon":false,"minify":false,"cache":true,"showErrors":true,"chunks":"all","excludeChunks":[],"title":"Money Transfer App","xhtml":false,"description":"ES Money Transfer App","appMountId":"root","googleAnalytics":{"trackingId":"UA-XXXX-XX","pageViewOnLoad":true},"mobile":true}}--></body>
</html>

View File

@@ -76,7 +76,7 @@
/******/ script.charset = 'utf-8';
/******/ script.async = true;
/******/
/******/ script.src = __webpack_require__.p + "" + {"0":"d5e626aaea52a2dac6cb","1":"6734b6ac5d23d61b8e5f","2":"829a6cd5501868837732"}[chunkId] + ".js";
/******/ script.src = __webpack_require__.p + "" + {"0":"4d33d25a9b5872086180","1":"6734b6ac5d23d61b8e5f","2":"829a6cd5501868837732"}[chunkId] + ".js";
/******/ head.appendChild(script);
/******/ }
/******/ };
@@ -92,4 +92,4 @@
/******/ })
/************************************************************************/
/******/ ([]);
//# sourceMappingURL=manifest.4fffd5bbc120d3bf86c4.js.map
//# sourceMappingURL=manifest.9a73c590403a64f40c41.js.map

View File

@@ -1 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap 931e2528f98ce8b6334a?"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,uDAA+C,iFAAiF;AAChI;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA","file":"manifest.4fffd5bbc120d3bf86c4.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, callbacks = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId])\n \t\t\t\tcallbacks.push.apply(callbacks, installedChunks[chunkId]);\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);\n \t\twhile(callbacks.length)\n \t\t\tcallbacks.shift().call(null, __webpack_require__);\n \t\tif(moreModules[0]) {\n \t\t\tinstalledModules[0] = 0;\n \t\t\treturn __webpack_require__(0);\n \t\t}\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// \"0\" means \"already loaded\"\n \t// Array means \"loading\", array contains callbacks\n \tvar installedChunks = {\n \t\t3:0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId, callback) {\n \t\t// \"0\" is the signal for \"already loaded\"\n \t\tif(installedChunks[chunkId] === 0)\n \t\t\treturn callback.call(null, __webpack_require__);\n\n \t\t// an array means \"currently loading\".\n \t\tif(installedChunks[chunkId] !== undefined) {\n \t\t\tinstalledChunks[chunkId].push(callback);\n \t\t} else {\n \t\t\t// start chunk loading\n \t\t\tinstalledChunks[chunkId] = [callback];\n \t\t\tvar head = document.getElementsByTagName('head')[0];\n \t\t\tvar script = document.createElement('script');\n \t\t\tscript.type = 'text/javascript';\n \t\t\tscript.charset = 'utf-8';\n \t\t\tscript.async = true;\n\n \t\t\tscript.src = __webpack_require__.p + \"\" + {\"0\":\"d5e626aaea52a2dac6cb\",\"1\":\"6734b6ac5d23d61b8e5f\",\"2\":\"829a6cd5501868837732\"}[chunkId] + \".js\";\n \t\t\thead.appendChild(script);\n \t\t}\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap 931e2528f98ce8b6334a\n **/"],"sourceRoot":""}
{"version":3,"sources":["webpack:///webpack/bootstrap 20c37f476a1d80966b41?"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,uDAA+C,iFAAiF;AAChI;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA","file":"manifest.9a73c590403a64f40c41.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, callbacks = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId])\n \t\t\t\tcallbacks.push.apply(callbacks, installedChunks[chunkId]);\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);\n \t\twhile(callbacks.length)\n \t\t\tcallbacks.shift().call(null, __webpack_require__);\n \t\tif(moreModules[0]) {\n \t\t\tinstalledModules[0] = 0;\n \t\t\treturn __webpack_require__(0);\n \t\t}\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// \"0\" means \"already loaded\"\n \t// Array means \"loading\", array contains callbacks\n \tvar installedChunks = {\n \t\t3:0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId, callback) {\n \t\t// \"0\" is the signal for \"already loaded\"\n \t\tif(installedChunks[chunkId] === 0)\n \t\t\treturn callback.call(null, __webpack_require__);\n\n \t\t// an array means \"currently loading\".\n \t\tif(installedChunks[chunkId] !== undefined) {\n \t\t\tinstalledChunks[chunkId].push(callback);\n \t\t} else {\n \t\t\t// start chunk loading\n \t\t\tinstalledChunks[chunkId] = [callback];\n \t\t\tvar head = document.getElementsByTagName('head')[0];\n \t\t\tvar script = document.createElement('script');\n \t\t\tscript.type = 'text/javascript';\n \t\t\tscript.charset = 'utf-8';\n \t\t\tscript.async = true;\n\n \t\t\tscript.src = __webpack_require__.p + \"\" + {\"0\":\"4d33d25a9b5872086180\",\"1\":\"6734b6ac5d23d61b8e5f\",\"2\":\"829a6cd5501868837732\"}[chunkId] + \".js\";\n \t\t\thead.appendChild(script);\n \t\t}\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap 20c37f476a1d80966b41\n **/"],"sourceRoot":""}

View File

@@ -52,7 +52,7 @@ export function initialize({cookies, isServer, currentLocation, userAgent} = {})
<Route path="/" component={ App }>
<IndexRoute component={ requireAuthentication(MyAccounts) } />
<Route path="signin" component={ SignIn } onEnter={ onEnter } />
<Route path="register" component={ SignUp } />
<Route path="register" component={ SignUp } onEnter={ onEnter } />
<Route path="account/:accountId" component={ requireAuthentication(Account) } />
</Route>
);

View File

@@ -20,7 +20,7 @@ export class TransfersTable extends React.Component {
}, v) => {
if (v.entryType == 'account') {
balance = v.initialBalance;
} else if (v.entryType == 'transaction') {
} else if (v.entryType == 'transaction' && (v.status !== 'FAILED_DUE_TO_INSUFFICIENT_FUNDS')) {
const isOriginating = v.fromAccountId == currentAccountId;
balance += (isOriginating ? -1 : 1) * v.amount;
}

View File

@@ -10,31 +10,48 @@ import Input from "./Input";
import ButtonLoader from "./ButtonLoader";
import AuxErrorLabel from './AuxErrorLabel';
import { emailSignInFormUpdate, emailSignIn } from "../../actions/signIn";
import * as AS from "../../actions/signIn";
/*
<Input type="password"
label="Password"
className="email-sign-in-password"
placeholder="Password"
disabled={disabled}
value={this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "form", "password"])}
errors={this.props.auth.getIn(["emailSignIn", this.getEndpoint(), "errors", "password"])}
onChange={this.handleInput.bind(this, "password")}
{...this.props.inputProps.password} />
*/
const formValidation = (payload) => [
'email',
'password'
].reduce((memo, prop) => {
let result = [];
const value = (payload[prop] || '').replace(/(^\s+)|(\s+$)/g, '');
switch (prop) {
case 'email':
case 'password':
if (/^$/.test(value)) {
result.push('required');
}
}
if (result.length) {
memo[prop] = result;
memo.hasErrors = true;
}
return memo;
}, {});
export class EmailSignInForm extends React.Component {
handleInput (key, val) {
this.props.dispatch(emailSignInFormUpdate(key, val));
this.props.dispatch(AS.emailSignInFormUpdate(key, val));
}
handleSubmit (event) {
event.preventDefault();
const formData = read(this.props.auth, 'signIn.form');
this.props.dispatch(emailSignIn(formData));
const validationErrors = formValidation(formData);
if (validationErrors.hasErrors) {
this.props.dispatch(AS.emailSignInError(validationErrors));
return;
}
this.props.dispatch(AS.emailSignIn(formData));
}
render () {

View File

@@ -10,20 +10,69 @@ import IndexPanel from "./../../components/partials/IndexPanel";
import AuxErrorLabel from './AuxErrorLabel';
import { customerInfoMap } from '../../entities/formToPayloadMappers';
import read from '../../utils/readProp';
import { emailSignUpFormUpdate, emailSignUp } from '../../actions/signUp';
import * as AS from '../../actions/signUp';
const formValidation = (payload) => [
'fname',
'lname',
'email',
'password',
'passwordConfirm',
'ssn',
'phoneNumber',
'address1',
'address2',
'city',
'state',
'zip'
].reduce((memo, prop) => {
let result = [];
const value = (payload[prop] || '').replace(/(^\s+)|(\s+$)/g, '');
switch (prop) {
case 'fname':
case 'lname':
case 'email':
case 'ssn':
case 'password':
case 'passwordConfirm':
if (/^$/.test(value)) {
result.push('required');
}
}
switch (prop) {
case 'passwordConfirm':
if (value != payload['password']) {
result.push('need to be equal to password');
}
}
if (result.length) {
memo[prop] = result;
memo.hasErrors = true;
}
return memo;
}, {});
class EmailSignUpForm extends React.Component {
handleInput (key, val) {
this.props.dispatch(emailSignUpFormUpdate(key, val));
this.props.dispatch(AS.emailSignUpFormUpdate(key, val));
}
handleSubmit (event) {
event.preventDefault();
const formData = read(this.props.auth, 'signUp.form');
this.props.dispatch(emailSignUp(customerInfoMap(formData)));
const validationErrors = formValidation(formData);
if (validationErrors.hasErrors) {
this.props.dispatch(AS.emailSignUpError(validationErrors));
return;
}
this.props.dispatch(AS.emailSignUp(customerInfoMap(formData)));
}
render () {

View File

@@ -4,9 +4,30 @@
import T from '../../constants/ACTION_TYPES';
import createFormReducer from '../createFormReducer';
export const signUpReducer = createFormReducer([
export const internalSignUpReducer = createFormReducer([
T.AUTH.SIGN_UP_START,
T.AUTH.SIGN_UP_COMPLETE,
T.AUTH.SIGN_UP_ERROR,
T.AUTH.SIGN_UP_FORM_UPDATE
]);
export const signUpReducer = (state, action) => {
switch (action.type) {
case T.LOCATION.ENTER: {
const { location } = action;
const { pathname } = location;
if (pathname == '/register') {
return internalSignUpReducer(state, {
type: T.AUTH.SIGN_UP_ERROR,
error: null
});
}
return state;
}
default: {
return internalSignUpReducer(state, action);
}
}
};