From 4c86d842dd16601fba31c50fc17f7f51b2214034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Mon, 13 Aug 2018 00:20:15 -0300 Subject: [PATCH] Validations for all forms: SIGN UP, SIGN IN, FORGOT PASSWORD, RESET PASSWORD --- .../client/auth/components/ForgotPassword.tsx | 76 +++++++--- .../client/auth/components/ResetPassword.tsx | 109 +++++++++++--- src/core/client/auth/components/SignIn.tsx | 142 +++++++++++++----- src/core/client/auth/components/SignUp.tsx | 8 +- .../containers/ForgotPasswordContainer.tsx | 12 +- .../containers/ResetPasswordContainer.tsx | 12 +- .../auth/containers/SignInContainer.tsx | 35 ++++- .../stream/containers/UserBoxContainer.tsx | 4 +- 8 files changed, 299 insertions(+), 99 deletions(-) diff --git a/src/core/client/auth/components/ForgotPassword.tsx b/src/core/client/auth/components/ForgotPassword.tsx index 4c06dcbc4..288887d7f 100644 --- a/src/core/client/auth/components/ForgotPassword.tsx +++ b/src/core/client/auth/components/ForgotPassword.tsx @@ -1,6 +1,11 @@ -import * as React from "react"; -import { StatelessComponent } from "react"; -import * as styles from "./SignIn.css"; +import React, { StatelessComponent } from "react"; +import { Field, Form } from "react-final-form"; + +import { + composeValidators, + required, + validateEmail, +} from "talk-framework/lib/validation"; import { Button, @@ -9,28 +14,57 @@ import { InputLabel, TextField, Typography, + ValidationMessage, } from "talk-ui/components"; +import * as styles from "./ForgotPassword.css"; + const ForgotPassword: StatelessComponent = props => { return ( - - - Forgot Password - - - Enter your email address below and we will send you a link to reset your - password. - - - Email Address - - -
- -
-
+ // TODO (bc) add functionality when Forgot Password is done on the backend + // tslint:disable-next-line:no-empty +
{}}> + {({ handleSubmit, submitting }) => ( + + + + Forgot Password + + + Enter your email address below and we will send you a link to + reset your password. + + + {({ input, meta }) => ( + + Email Address + + {meta.touched && + (meta.error || meta.submitError) && ( + + {meta.error || meta.submitError} + + )} + + )} + +
+ +
+
+
+ )} + ); }; diff --git a/src/core/client/auth/components/ResetPassword.tsx b/src/core/client/auth/components/ResetPassword.tsx index 5f000d091..8500c07db 100644 --- a/src/core/client/auth/components/ResetPassword.tsx +++ b/src/core/client/auth/components/ResetPassword.tsx @@ -1,6 +1,12 @@ -import * as React from "react"; -import { StatelessComponent } from "react"; -import * as styles from "./SignIn.css"; +import React, { StatelessComponent } from "react"; +import { Field, Form } from "react-final-form"; + +import { + composeValidators, + required, + validateEqualPasswords, + validatePassword, +} from "talk-framework/lib/validation"; import { Button, @@ -9,29 +15,88 @@ import { InputLabel, TextField, Typography, + ValidationMessage, } from "talk-ui/components"; +import * as styles from "./ResetPassword.css"; + const ResetPassword: StatelessComponent = props => { return ( - - - Reset Password - - - Password - Must be at least 8 characters - - - - Confirm Password - - -
- -
-
+ // TODO (bc) add functionality when Reset Password is done on the backend + // tslint:disable-next-line:no-empty +
{}}> + {({ handleSubmit, submitting }) => ( + + + + Reset Password + + + {({ input, meta }) => ( + + Password + + Must be at least 8 characters + + + {meta.touched && + (meta.error || meta.submitError) && ( + + {meta.error || meta.submitError} + + )} + + )} + + + + {({ input, meta }) => ( + + Confirm Password + + Must be at least 8 characters + + + {meta.touched && + (meta.error || meta.submitError) && ( + + {meta.error || meta.submitError} + + )} + + )} + +
+ +
+
+
+ )} + ); }; diff --git a/src/core/client/auth/components/SignIn.tsx b/src/core/client/auth/components/SignIn.tsx index 9244aa2af..042233df1 100644 --- a/src/core/client/auth/components/SignIn.tsx +++ b/src/core/client/auth/components/SignIn.tsx @@ -1,7 +1,16 @@ import * as React from "react"; import { StatelessComponent } from "react"; +import { Field, Form } from "react-final-form"; +import { OnSubmit } from "talk-framework/lib/form"; import * as styles from "./SignIn.css"; +import { + composeValidators, + required, + validateEmail, + validatePassword, +} from "talk-framework/lib/validation"; + import { Button, Flex, @@ -9,43 +18,108 @@ import { InputLabel, TextField, Typography, + ValidationMessage, } from "talk-ui/components"; -const SignIn: StatelessComponent = props => { +interface FormProps { + email: string; + password: string; +} + +export interface SignInForm { + onSubmit: OnSubmit; +} + +const SignIn: StatelessComponent = props => { return ( - - - Sign in to join the conversation - - - Email Address - - - - Password - - - - - -
- - - Don't have an account? - - -
-
+
+ {({ handleSubmit, submitting }) => ( + + + + Sign in to join the conversation + + + + {({ input, meta }) => ( + + Email Address + + {meta.touched && + (meta.error || meta.submitError) && ( + + {meta.error || meta.submitError} + + )} + + )} + + + + {({ input, meta }) => ( + + Password + + Must be at least 8 characters + + + {meta.touched && + (meta.error || meta.submitError) && ( + + {meta.error || meta.submitError} + + )} + + + + + )} + + +
+ + + Don't have an account? + + +
+
+
+ )} + ); }; diff --git a/src/core/client/auth/components/SignUp.tsx b/src/core/client/auth/components/SignUp.tsx index d4c8a7d55..64d632f74 100644 --- a/src/core/client/auth/components/SignUp.tsx +++ b/src/core/client/auth/components/SignUp.tsx @@ -153,7 +153,13 @@ const SignUp: StatelessComponent = props => {
- { - return ; -}; +class ForgotPasswordContainer extends Component { + public render() { + return ; + } +} export default ForgotPasswordContainer; diff --git a/src/core/client/auth/containers/ResetPasswordContainer.tsx b/src/core/client/auth/containers/ResetPasswordContainer.tsx index 6dab0eef1..ae5006eb0 100644 --- a/src/core/client/auth/containers/ResetPasswordContainer.tsx +++ b/src/core/client/auth/containers/ResetPasswordContainer.tsx @@ -1,10 +1,10 @@ -import * as React from "react"; -import { StatelessComponent } from "react"; - +import React, { Component } from "react"; import ResetPassword from "../components/ResetPassword"; -const ResetPasswordContainer: StatelessComponent = () => { - return ; -}; +class ResetPasswordContainer extends Component { + public render() { + return ; + } +} export default ResetPasswordContainer; diff --git a/src/core/client/auth/containers/SignInContainer.tsx b/src/core/client/auth/containers/SignInContainer.tsx index aabf4641d..fa4fa2d80 100644 --- a/src/core/client/auth/containers/SignInContainer.tsx +++ b/src/core/client/auth/containers/SignInContainer.tsx @@ -1,10 +1,31 @@ -import * as React from "react"; -import { StatelessComponent } from "react"; +import { BadUserInputError } from "talk-framework/lib/errors"; +import SignIn, { SignInForm } from "../components/SignIn"; -import SignIn from "../components/SignIn"; +import React, { Component } from "react"; +import { SignInMutation, withSignInMutation } from "../mutations"; -const SignInContainer: StatelessComponent = () => { - return ; -}; +interface SignInContainerProps { + signIn: SignInMutation; +} -export default SignInContainer; +class SignInContainer extends Component { + private onSubmit: SignInForm["onSubmit"] = async (input, form) => { + try { + await this.props.signIn(input); + form.reset(); + } catch (error) { + if (error instanceof BadUserInputError) { + return error.invalidArgsLocalized; + } + // tslint:disable-next-line:no-console + console.error(error); + } + return undefined; + }; + public render() { + return ; + } +} + +const enhanced = withSignInMutation(SignInContainer); +export default enhanced; diff --git a/src/core/client/stream/containers/UserBoxContainer.tsx b/src/core/client/stream/containers/UserBoxContainer.tsx index a1f2bb87b..b719902cd 100644 --- a/src/core/client/stream/containers/UserBoxContainer.tsx +++ b/src/core/client/stream/containers/UserBoxContainer.tsx @@ -38,14 +38,14 @@ export class UserBoxContainer extends Component { - {/* */} + {/* */}