Validations for all forms: SIGN UP, SIGN IN, FORGOT PASSWORD, RESET PASSWORD

This commit is contained in:
Belén Curcio
2018-08-13 00:20:15 -03:00
parent 7e081bbf07
commit 4c86d842dd
8 changed files with 299 additions and 99 deletions
@@ -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 (
<Flex itemGutter direction="column" className={styles.root}>
<Typography variant="heading1" align="center">
Forgot Password
</Typography>
<Typography variant="bodyCopy">
Enter your email address below and we will send you a link to reset your
password.
</Typography>
<FormField>
<InputLabel>Email Address</InputLabel>
<TextField />
</FormField>
<div className={styles.footer}>
<Button variant="filled" color="primary" size="large" fullWidth>
Send Email
</Button>
</div>
</Flex>
// TODO (bc) add functionality when Forgot Password is done on the backend
// tslint:disable-next-line:no-empty
<Form onSubmit={() => {}}>
{({ handleSubmit, submitting }) => (
<form autoComplete="off" onSubmit={handleSubmit}>
<Flex itemGutter direction="column" className={styles.root}>
<Typography variant="heading1" align="center">
Forgot Password
</Typography>
<Typography variant="bodyCopy">
Enter your email address below and we will send you a link to
reset your password.
</Typography>
<Field
name="email"
validate={composeValidators(required, validateEmail)}
>
{({ input, meta }) => (
<FormField>
<InputLabel>Email Address</InputLabel>
<TextField
name={input.name}
onChange={input.onChange}
value={input.value}
placeholder="Email Address"
/>
{meta.touched &&
(meta.error || meta.submitError) && (
<ValidationMessage>
{meta.error || meta.submitError}
</ValidationMessage>
)}
</FormField>
)}
</Field>
<div className={styles.footer}>
<Button variant="filled" color="primary" size="large" fullWidth>
Send Email
</Button>
</div>
</Flex>
</form>
)}
</Form>
);
};
@@ -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 (
<Flex itemGutter direction="column" className={styles.root}>
<Typography variant="heading1" align="center">
Reset Password
</Typography>
<FormField>
<InputLabel>Password</InputLabel>
<Typography>Must be at least 8 characters</Typography>
<TextField />
</FormField>
<FormField>
<InputLabel>Confirm Password</InputLabel>
<TextField />
</FormField>
<div className={styles.footer}>
<Button variant="filled" color="primary" size="large" fullWidth>
Reset Password
</Button>
</div>
</Flex>
// TODO (bc) add functionality when Reset Password is done on the backend
// tslint:disable-next-line:no-empty
<Form onSubmit={() => {}}>
{({ handleSubmit, submitting }) => (
<form autoComplete="off" onSubmit={handleSubmit}>
<Flex itemGutter direction="column" className={styles.root}>
<Typography variant="heading1" align="center">
Reset Password
</Typography>
<Field
name="password"
validate={composeValidators(required, validatePassword)}
>
{({ input, meta }) => (
<FormField>
<InputLabel>Password</InputLabel>
<Typography variant="inputDescription">
Must be at least 8 characters
</Typography>
<TextField
name={input.name}
onChange={input.onChange}
value={input.value}
placeholder="Password"
type="password"
/>
{meta.touched &&
(meta.error || meta.submitError) && (
<ValidationMessage>
{meta.error || meta.submitError}
</ValidationMessage>
)}
</FormField>
)}
</Field>
<Field
name="confirmPassword"
validate={composeValidators(
required,
validatePassword,
validateEqualPasswords
)}
>
{({ input, meta }) => (
<FormField>
<InputLabel>Confirm Password</InputLabel>
<Typography variant="inputDescription">
Must be at least 8 characters
</Typography>
<TextField
name={input.name}
onChange={input.onChange}
value={input.value}
placeholder="Confirm Password"
type="password"
/>
{meta.touched &&
(meta.error || meta.submitError) && (
<ValidationMessage>
{meta.error || meta.submitError}
</ValidationMessage>
)}
</FormField>
)}
</Field>
<div className={styles.footer}>
<Button variant="filled" color="primary" size="large" fullWidth>
Reset Password
</Button>
</div>
</Flex>
</form>
)}
</Form>
);
};
+108 -34
View File
@@ -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<FormProps>;
}
const SignIn: StatelessComponent<SignInForm> = props => {
return (
<Flex itemGutter direction="column" className={styles.root}>
<Typography variant="heading1" align="center">
Sign in to join the conversation
</Typography>
<FormField>
<InputLabel>Email Address</InputLabel>
<TextField />
</FormField>
<FormField>
<InputLabel>Password</InputLabel>
<TextField />
<span className={styles.forgotPassword}>
<Button variant="underlined" color="primary" size="small">
Forgot your password?
</Button>
</span>
</FormField>
<div className={styles.footer}>
<Button variant="filled" color="primary" size="large" fullWidth>
Sign in and join the conversation
</Button>
<Flex
itemGutter="half"
justifyContent="center"
className={styles.subFooter}
>
<Typography>Don't have an account?</Typography>
<Button variant="underlined" size="small" color="primary">
Sign Up
</Button>
</Flex>
</div>
</Flex>
<Form onSubmit={props.onSubmit}>
{({ handleSubmit, submitting }) => (
<form autoComplete="off" onSubmit={handleSubmit}>
<Flex itemGutter direction="column" className={styles.root}>
<Typography variant="heading1" align="center">
Sign in to join the conversation
</Typography>
<Field
name="email"
validate={composeValidators(required, validateEmail)}
>
{({ input, meta }) => (
<FormField>
<InputLabel>Email Address</InputLabel>
<TextField
name={input.name}
onChange={input.onChange}
value={input.value}
placeholder="Email Address"
/>
{meta.touched &&
(meta.error || meta.submitError) && (
<ValidationMessage>
{meta.error || meta.submitError}
</ValidationMessage>
)}
</FormField>
)}
</Field>
<Field
name="password"
validate={composeValidators(required, validatePassword)}
>
{({ input, meta }) => (
<FormField>
<InputLabel>Password</InputLabel>
<Typography variant="inputDescription">
Must be at least 8 characters
</Typography>
<TextField
name={input.name}
onChange={input.onChange}
value={input.value}
placeholder="Password"
type="password"
/>
{meta.touched &&
(meta.error || meta.submitError) && (
<ValidationMessage>
{meta.error || meta.submitError}
</ValidationMessage>
)}
<span className={styles.forgotPassword}>
<Button variant="underlined" color="primary" size="small">
Forgot your password?
</Button>
</span>
</FormField>
)}
</Field>
<div className={styles.footer}>
<Button
variant="filled"
color="primary"
size="large"
fullWidth
type="submit"
>
Sign in and join the conversation
</Button>
<Flex
itemGutter="half"
justifyContent="center"
className={styles.subFooter}
>
<Typography>Don't have an account?</Typography>
<Button variant="underlined" size="small" color="primary">
Sign Up
</Button>
</Flex>
</div>
</Flex>
</form>
)}
</Form>
);
};
+7 -1
View File
@@ -153,7 +153,13 @@ const SignUp: StatelessComponent<SignUpForm> = props => {
</Field>
</Flex>
<div className={styles.footer}>
<Button variant="filled" color="primary" size="large" fullWidth>
<Button
variant="filled"
color="primary"
size="large"
fullWidth
type="submit"
>
Sign up and join the conversation
</Button>
<Flex
@@ -1,10 +1,10 @@
import * as React from "react";
import { StatelessComponent } from "react";
import React, { Component } from "react";
import ForgotPassword from "../components/ForgotPassword";
const ForgotPasswordContainer: StatelessComponent = () => {
return <ForgotPassword />;
};
class ForgotPasswordContainer extends Component {
public render() {
return <ForgotPassword />;
}
}
export default ForgotPasswordContainer;
@@ -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 <ResetPassword />;
};
class ResetPasswordContainer extends Component {
public render() {
return <ResetPassword />;
}
}
export default ResetPasswordContainer;
@@ -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 <SignIn />;
};
interface SignInContainerProps {
signIn: SignInMutation;
}
export default SignInContainer;
class SignInContainer extends Component<SignInContainerProps> {
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 <SignIn onSubmit={this.onSubmit} />;
}
}
const enhanced = withSignInMutation(SignInContainer);
export default enhanced;
@@ -38,14 +38,14 @@ export class UserBoxContainer extends Component<InnerProps> {
<Popup
href={`/auth.html?view=${view}`}
title="Talk Auth"
features="menubar=0,resizable=0,width=350,height=600,top=200,left=500"
features="menubar=0,resizable=0,width=350,height=720,top=200,left=500"
open={open}
focus={focus}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
onClose={this.handleClose}
/>
{/* <UserBoxAuthenticated onSignOut={this.handleRegister} /> */}
{/* <UserBoxAuthenticated onSignOut={this.handleSignOut} /> */}
<UserBoxUnauthenticated
onSignIn={this.handleSignIn}
onRegister={this.handleRegister}