mirror of
https://github.com/rjNemo/devbook_ts
synced 2026-06-12 13:36:43 +00:00
enable interactive form
This commit is contained in:
parent
d6d1b706c2
commit
5aa90a6047
3 changed files with 113 additions and 25 deletions
40
src/components/InputField.tsx
Normal file
40
src/components/InputField.tsx
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
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;
|
||||||
|
|
@ -1,35 +1,76 @@
|
||||||
import React, {FC} from 'react';
|
import React, {FC, useState} from 'react';
|
||||||
|
// Routing
|
||||||
import {Link} from 'react-router-dom';
|
import {Link} from 'react-router-dom';
|
||||||
import Header from '../components/Header';
|
|
||||||
import * as ROUTES from '../constants/routes';
|
import * as ROUTES from '../constants/routes';
|
||||||
|
// Style
|
||||||
|
import Header from '../components/Header';
|
||||||
|
import InputField from '../components/InputField';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign up form
|
* Sign up form
|
||||||
*/
|
*/
|
||||||
const SignUp: FC = () => (
|
const SignUp: FC = () => {
|
||||||
<section className="container">
|
const [name, setName] = useState('');
|
||||||
<Header title="Sign Up" lead="Create your account" />
|
const [email, setEmail] = useState('');
|
||||||
<form action="dashboard.html" className="form">
|
const [password1, setPassword1] = useState('');
|
||||||
<div className="form-group">
|
const [password2, setPassword2] = useState('');
|
||||||
<input type="text" placeholder="Name" required />
|
const [error, setError] = useState(false);
|
||||||
</div>
|
|
||||||
<div className="form-group">
|
const isDisabled: boolean =
|
||||||
<input type="email" placeholder="Email Address" />
|
name === '' || email === '' || password1 === '' || password1 !== password2;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="container">
|
||||||
|
{error && <div className="alert alert-danger">Invalid credentials</div>}
|
||||||
|
<Header title="Sign Up" lead="Create your account" />
|
||||||
|
<form action="dashboard.html" className="form">
|
||||||
|
<InputField
|
||||||
|
state={name}
|
||||||
|
setState={setName}
|
||||||
|
placeholder="Name"
|
||||||
|
required
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputField
|
||||||
|
state={email}
|
||||||
|
setState={setEmail}
|
||||||
|
placeholder="Email Address"
|
||||||
|
required
|
||||||
|
/>
|
||||||
<small className="form-text">
|
<small className="form-text">
|
||||||
This site uses Gravatar, so use a Gravatar email.
|
This site uses Gravatar, so use a Gravatar email.
|
||||||
</small>
|
</small>
|
||||||
</div>
|
|
||||||
<div className="form-group">
|
<InputField
|
||||||
<input type="password" placeholder="Password" minLength={6} />
|
state={password1}
|
||||||
</div>
|
setState={setPassword1}
|
||||||
<div className="form-group">
|
placeholder="Password"
|
||||||
<input type="password" placeholder="Confirm Password" minLength={6} />
|
type="password"
|
||||||
</div>
|
minLength={6}
|
||||||
<input type="submit" value="Register" className="btn btn-primary" />
|
required
|
||||||
</form>
|
/>
|
||||||
<p className="my-1">
|
<InputField
|
||||||
Already have an account? <Link to={ROUTES.SIGN_IN}>Sign in</Link>
|
state={password2}
|
||||||
</p>
|
setState={setPassword2}
|
||||||
</section>
|
placeholder="Confirm Password"
|
||||||
);
|
type="password"
|
||||||
|
minLength={6}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="submit"
|
||||||
|
value="Register"
|
||||||
|
className="btn btn-primary"
|
||||||
|
disabled={isDisabled}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
<p className="my-1">
|
||||||
|
Already have an account? <Link to={ROUTES.SIGN_IN}>Sign in</Link>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default SignUp;
|
export default SignUp;
|
||||||
|
|
|
||||||
7
src/pages/__tests__/SignUp.spec.tsx
Normal file
7
src/pages/__tests__/SignUp.spec.tsx
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import SignUp from '../SignUp';
|
||||||
|
|
||||||
|
describe('Signup Page', () => {
|
||||||
|
it('calls loadUser function', () => {});
|
||||||
|
it('redirects to dashboard if signed up', () => {});
|
||||||
|
it('call signup function on click', () => {});
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue