signup page functional

This commit is contained in:
Ruidy Nemausat 2020-05-14 09:45:26 +02:00
parent 5aa90a6047
commit b1039eb959
7 changed files with 150 additions and 636 deletions

View file

@ -24,6 +24,7 @@
"moment": "^2.25.3",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-google-button": "^0.7.1",
"react-redux": "^7.2.0",
"react-redux-firebase": "^3.4.0",
"react-router-dom": "^5.2.0",

View file

@ -1,40 +0,0 @@
import React, {FC} from 'react';
interface IProps {
state: string | number | string[] | undefined;
setState: React.Dispatch<React.SetStateAction<string>>;
placeholder: string;
type?: string;
required?: boolean;
autoFocus?: boolean;
minLength?: number;
}
const InputField: FC<IProps> = ({
state,
setState,
placeholder,
autoFocus,
required,
minLength,
type = 'text',
}) => {
const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
setState(e.target.value);
};
return (
<div className="form-group">
<input
value={state}
onChange={handleChange}
placeholder={placeholder}
type={type}
autoFocus={autoFocus}
required={required}
minLength={minLength}
/>
</div>
);
};
export default InputField;

View file

@ -1,8 +1,20 @@
interface User {
name: string;
displayName: string;
email: string;
picture: string;
avatarUrl: string;
createdAt: Date;
}
/** User constructor */
export const newUser = (
displayName: string,
email: string,
avatarUrl: string = '',
): User => ({
displayName,
email,
avatarUrl,
createdAt: new Date(),
});
export default User;

View file

@ -1,63 +1,140 @@
import React, {FC, useState} from 'react';
// Routing
import {Link} from 'react-router-dom';
import {Link, useHistory, Redirect} from 'react-router-dom';
import * as ROUTES from '../constants/routes';
// Redux
import {compose} from 'redux';
import {connect} from 'react-redux';
import {withFirebase, WithFirebaseProps} from 'react-redux-firebase';
import {selectProfile} from '../store/firebase';
import User, {newUser} from '../models/User';
// Style
import Header from '../components/Header';
import InputField from '../components/InputField';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faExclamationTriangle} from '@fortawesome/free-solid-svg-icons';
import GoogleButton from 'react-google-button';
// extends withFirebaseProps type to ad profile info
interface IProps extends WithFirebaseProps<User> {
isEmpty: boolean;
isLoaded: boolean;
}
/**
* Sign up form
* Sign up form recieves firebase from withFirebase HOC
*/
const SignUp: FC = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password1, setPassword1] = useState('');
const [password2, setPassword2] = useState('');
const [error, setError] = useState(false);
const SignUp: FC<IProps> = ({firebase, isEmpty, isLoaded}) => {
const history = useHistory();
const isDisabled: boolean =
name === '' || email === '' || password1 === '' || password1 !== password2;
const initFormData = {
name: '',
email: '',
password: '',
password2: '',
error: false,
};
const [formData, setFormData] = useState(initFormData);
/** update each input state value onChange */
const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void =>
setFormData({
...formData,
[e.target.name]: e.target.value,
});
/** clean form after successful submition */
const resetForm = () => setFormData(initFormData);
const {name, email, password, password2, error} = formData;
// prevent submitting invalid forms
const isDisabled: boolean = name === '' || email === '' || password === '';
/** create user with password */
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (password !== password2) {
setFormData({...formData, error: true});
} else {
// pass the info to store into the second argument
firebase
.createUser({email, password}, newUser(name, email))
.then(() => {
resetForm();
// redirect to dashboard
history.push(ROUTES.DASHBOARD);
})
.catch(err => console.error(err));
}
};
const loginWithGoogle = () =>
firebase.login({provider: 'google', type: 'popup'});
if (isLoaded && !isEmpty) {
return <Redirect to={ROUTES.DASHBOARD} />;
}
return (
<section className="container">
{error && <div className="alert alert-danger">Invalid credentials</div>}
{error && (
<div className="alert alert-danger">
<FontAwesomeIcon icon={faExclamationTriangle} /> Passwords don't
match!
</div>
)}
<Header title="Sign Up" lead="Create your account" />
<form action="dashboard.html" className="form">
<InputField
state={name}
setState={setName}
placeholder="Name"
required
autoFocus
/>
<GoogleButton type="light" className="my-1" onClick={loginWithGoogle} />
<form className="form" onSubmit={handleSubmit}>
<div className="form-group">
<input
name="name"
value={name}
onChange={handleChange}
placeholder="Name"
type="text"
required
autoFocus
/>
</div>
<InputField
state={email}
setState={setEmail}
placeholder="Email Address"
required
/>
<small className="form-text">
This site uses Gravatar, so use a Gravatar email.
</small>
<div className="form-group">
<input
name="email"
value={email}
onChange={handleChange}
placeholder="Email Address"
type="email"
required
/>
<small className="form-text">
This site uses Gravatar, so use a Gravatar email.
</small>
</div>
<InputField
state={password1}
setState={setPassword1}
placeholder="Password"
type="password"
minLength={6}
required
/>
<InputField
state={password2}
setState={setPassword2}
placeholder="Confirm Password"
type="password"
minLength={6}
required
/>
<div className="form-group">
<input
name="password"
value={password}
onChange={handleChange}
placeholder="Password"
type="password"
minLength={6}
required
/>
</div>
<div className="form-group">
<input
name="password2"
value={password2}
onChange={handleChange}
placeholder="Confirm Password"
type="password"
minLength={6}
required
/>
</div>
<input
type="submit"
@ -73,4 +150,7 @@ const SignUp: FC = () => {
);
};
export default SignUp;
/** subscribe to store and firebase */
const enhance = compose<FC<IProps>>(connect(selectProfile), withFirebase);
export default enhance(SignUp);

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
@import "_config";
@import '_config';
// Backgrounds

View file

@ -9558,6 +9558,13 @@ react-error-overlay@^6.0.7:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108"
integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA==
react-google-button@^0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/react-google-button/-/react-google-button-0.7.1.tgz#e84b4ce270a66e345489dc86e47235e877fcc81a"
integrity sha512-FN8/9Va6oAGKL561yddNzcjz0iGlt2GZFwiDPczEu0fDVnR21/nBrPs7Y5x97V1S4//nvtkvv6ohfwtxIHpbfg==
dependencies:
prop-types "^15.7.2"
react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"