sign up page

This commit is contained in:
BFlat authored and Brandon Thomas committed 2022-07-10 18:38:31 -04:00
1 parent f161655985
commit bd515b3cb7
3 files changed
+171 -120

No files matched your search

+3 -4
View File
@@ -133,18 +133,17 @@ nav {
font-size: 15px;
font-weight: 600;
padding: 0.5rem 1rem;
display: flex;
align-items: center;
&:active {
background-color: #fc6b68;
background-color: $primary;
}
}
.dropdown-menu {
border-color: #ffffff12 !important;
border-color: rgba($white, 0.12) !important;
border: 1px solid;
border-radius: 8px;
box-shadow: 0px 5px 20px rgba($black, 0.3);
}
.nav-bg-dark {
+10 -1
View File
@@ -174,6 +174,15 @@ code {
}
}
.form-text {
color: lighten($primary, 5%);
}
.alert {
border-radius: 5px;
font-weight: 400;
}
.input-icon {
.form-control {
padding-left: 2.375rem;
@@ -190,7 +199,7 @@ code {
display: block;
width: 2.375rem;
height: 2.375rem;
line-height: 2.375rem;
line-height: 2.6rem;
text-align: center;
pointer-events: none;
color: #212529;
+158 -115
View File
@@ -1,9 +1,17 @@
import React, { useState } from 'react';
import { CreateAccount, CreateAccountIsError, CreateAccountIsSuccess } from '@storyteller/components/src/api/user/CreateAccount';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Link } from 'react-router-dom';
import { SessionWrapper } from '@storyteller/components/src/session/SessionWrapper';
import { iconEmailField, iconPasswordField, iconUser } from '@storyteller/components/src/icons/SemanticIcons';
import React, { useState } from "react";
import {
CreateAccount,
CreateAccountIsError,
CreateAccountIsSuccess,
} from "@storyteller/components/src/api/user/CreateAccount";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Link } from "react-router-dom";
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
import {
iconEmailField,
iconPasswordField,
iconUser,
} from "@storyteller/components/src/icons/SemanticIcons";
enum FieldTriState {
EMPTY_FALSE,
@@ -12,27 +20,31 @@ enum FieldTriState {
}
interface Props {
sessionWrapper: SessionWrapper,
querySessionCallback : () => void,
sessionWrapper: SessionWrapper;
querySessionCallback: () => void;
}
function SignupPage(props: Props) {
const [username, setUsername] = useState('');
const [username, setUsername] = useState("");
const [usernameValid, setUsernameValid] = useState(FieldTriState.EMPTY_FALSE);
const [usernameInvalidReason, setUsernameInvalidReason] = useState('');
const [usernameInvalidReason, setUsernameInvalidReason] = useState("");
const [email, setEmail] = useState('');
const [email, setEmail] = useState("");
const [emailValid, setEmailValid] = useState(FieldTriState.EMPTY_FALSE);
const [emailInvalidReason, setEmailInvalidReason] = useState('');
const [emailInvalidReason, setEmailInvalidReason] = useState("");
const [password, setPassword] = useState('');
const [password, setPassword] = useState("");
const [passwordValid, setPasswordValid] = useState(FieldTriState.EMPTY_FALSE);
const [passwordInvalidReason, setPasswordInvalidReason] = useState('');
const [passwordInvalidReason, setPasswordInvalidReason] = useState("");
const [passwordConfirmation, setPasswordConfirmation] = useState('');
const [passwordConfirmationValid, setPasswordConfirmationValid] = useState(FieldTriState.EMPTY_FALSE);
const [passwordConfirmationInvalidReason, setPasswordConfirmationInvalidReason] = useState('');
const [passwordConfirmation, setPasswordConfirmation] = useState("");
const [passwordConfirmationValid, setPasswordConfirmationValid] = useState(
FieldTriState.EMPTY_FALSE
);
const [
passwordConfirmationInvalidReason,
setPasswordConfirmationInvalidReason,
] = useState("");
const handleUsernameChange = (ev: React.FormEvent<HTMLInputElement>) => {
ev.preventDefault();
@@ -59,7 +71,7 @@ function SignupPage(props: Props) {
setUsernameInvalidReason(usernameInvalidReason);
return false;
}
};
const handleEmailChange = (ev: React.FormEvent<HTMLInputElement>) => {
ev.preventDefault();
@@ -86,7 +98,7 @@ function SignupPage(props: Props) {
setEmailInvalidReason(emailInvalidReason);
return false;
}
};
const handlePasswordChange = (ev: React.FormEvent<HTMLInputElement>) => {
ev.preventDefault();
@@ -112,7 +124,6 @@ function SignupPage(props: Props) {
} else {
passwordConfirmationValid = FieldTriState.TRUE;
passwordConfirmationInvalidReason = "";
}
}
@@ -120,12 +131,14 @@ function SignupPage(props: Props) {
setPasswordValid(passwordValid);
setPasswordInvalidReason(passwordInvalidReason);
setPasswordConfirmationValid(passwordConfirmationValid);
setPasswordConfirmationInvalidReason(passwordConfirmationInvalidReason)
setPasswordConfirmationInvalidReason(passwordConfirmationInvalidReason);
return false;
}
};
const handlePasswordConfirmationChange = (ev: React.FormEvent<HTMLInputElement>) => {
const handlePasswordConfirmationChange = (
ev: React.FormEvent<HTMLInputElement>
) => {
ev.preventDefault();
const newPasswordConfirmation = (ev.target as HTMLInputElement).value;
@@ -134,14 +147,12 @@ function SignupPage(props: Props) {
let passwordConfirmationInvalidReason = "";
if (newPasswordConfirmation.length > 1) {
if (newPasswordConfirmation !== password) {
passwordConfirmationValid = FieldTriState.FALSE;
passwordConfirmationInvalidReason = "passwords do not match";
} else {
passwordConfirmationValid = FieldTriState.TRUE;
passwordConfirmationInvalidReason = "";
}
}
@@ -150,16 +161,20 @@ function SignupPage(props: Props) {
setPasswordConfirmationInvalidReason(passwordConfirmationInvalidReason);
return false;
}
};
const handleFormSubmit = async (ev: React.FormEvent<HTMLFormElement>) : Promise<boolean> => {
const handleFormSubmit = async (
ev: React.FormEvent<HTMLFormElement>
): Promise<boolean> => {
ev.preventDefault();
if (!usernameValid ||
!emailValid ||
!passwordValid ||
!passwordConfirmationValid) {
return false;
if (
!usernameValid ||
!emailValid ||
!passwordValid ||
!passwordConfirmationValid
) {
return false;
}
const request = {
@@ -172,32 +187,31 @@ function SignupPage(props: Props) {
const response = await CreateAccount(request);
if (CreateAccountIsError(response)) {
if ('email_address' in response.error_fields) {
if ("email_address" in response.error_fields) {
setEmailValid(FieldTriState.FALSE);
setEmailInvalidReason(response.error_fields['email_address'] || "");
setEmailInvalidReason(response.error_fields["email_address"] || "");
}
if ('username' in response.error_fields) {
if ("username" in response.error_fields) {
setUsernameValid(FieldTriState.FALSE);
setUsernameInvalidReason(response.error_fields['username'] || "");
setUsernameInvalidReason(response.error_fields["username"] || "");
}
} else if (CreateAccountIsSuccess(response)) {
console.log('querying new session');
console.log("querying new session");
props.querySessionCallback();
// TODO: Switch to functional component.
window.location.href = '/';
window.location.href = "/";
}
return false;
}
};
if (props.sessionWrapper.isLoggedIn()) {
return <div>Invalid view for logged in users.</div>;
}
let usernameInputClass = "input";
let usernameHelpClass = "help";
let usernameInputClass = "form-control";
let usernameHelpClass = "form-text";
switch (usernameValid) {
case FieldTriState.EMPTY_FALSE:
break;
@@ -211,8 +225,8 @@ function SignupPage(props: Props) {
break;
}
let emailInputClass = "input";
let emailHelpClass = "help";
let emailInputClass = "form-control";
let emailHelpClass = "form-text";
switch (emailValid) {
case FieldTriState.EMPTY_FALSE:
break;
@@ -226,8 +240,8 @@ function SignupPage(props: Props) {
break;
}
let passwordInputClass = "input";
let passwordHelpClass = "help";
let passwordInputClass = "form-control";
let passwordHelpClass = "form-text";
switch (passwordValid) {
case FieldTriState.EMPTY_FALSE:
break;
@@ -241,8 +255,8 @@ function SignupPage(props: Props) {
break;
}
let passwordConfirmationInputClass = "input";
let passwordConfirmationHelpClass = "help";
let passwordConfirmationInputClass = "form-control";
let passwordConfirmationHelpClass = "form-text";
switch (passwordConfirmationValid) {
case FieldTriState.EMPTY_FALSE:
break;
@@ -258,74 +272,103 @@ function SignupPage(props: Props) {
return (
<div>
<h1 className="title is-1"> Sign Up </h1>
<form onSubmit={handleFormSubmit}>
<div className="field">
<label className="label">Username</label>
<div className="control has-icons-left has-icons-right">
<input className={usernameInputClass} type="text" placeholder="Username" value={username} onChange={handleUsernameChange} />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={iconUser} />
</span>
<div className="container-panel pb-5 pt-lg-5 my-lg-5 login-panel">
<div className="panel p-3 p-lg-4 load-hidden mt-5 mt-lg-0">
<h1 className="panel-title fw-bold ">Sign Up</h1>
<div className="py-6">
<form onSubmit={handleFormSubmit}>
<div className="d-flex flex-column gap-4">
<div>
<label className="sub-title">Username</label>
<div className="form-group input-icon">
<span className="form-control-feedback">
<FontAwesomeIcon icon={iconUser} />
</span>
<input
className={usernameInputClass}
type="text"
placeholder="Username"
value={username}
onChange={handleUsernameChange}
/>
</div>
<p className={usernameHelpClass}>{usernameInvalidReason}</p>
</div>
<div>
<label className="sub-title">Email</label>
<div className="form-group input-icon">
<span className="form-control-feedback">
<FontAwesomeIcon icon={iconEmailField} />
</span>
<input
className={emailInputClass}
type="email"
placeholder="Email"
value={email}
onChange={handleEmailChange}
/>
</div>
<p className={emailHelpClass}>{emailInvalidReason}</p>
</div>
<div>
<label className="sub-title">Password</label>
<div className="form-group input-icon">
<span className="form-control-feedback">
<FontAwesomeIcon icon={iconPasswordField} />
</span>
<input
className={passwordInputClass}
type="password"
placeholder="Password"
value={password}
onChange={handlePasswordChange}
/>
</div>
<p className={passwordHelpClass}>{passwordInvalidReason}</p>
</div>
<div>
<label className="sub-title">Password Confirmation</label>
<div className="form-group input-icon">
<span className="form-control-feedback">
<FontAwesomeIcon icon={iconPasswordField} />
</span>
<input
className={passwordConfirmationInputClass}
type="password"
placeholder="Password confirmation"
value={passwordConfirmation}
onChange={handlePasswordConfirmationChange}
/>
</div>
<p className={passwordConfirmationHelpClass}>
{passwordConfirmationInvalidReason}
</p>
</div>
<div className="alert alert-warning mb-0">
<strong>Remember your password!</strong> We don't have
password reset currently, and it'll be a few more weeks before
it's added (there are more important features to work on). If
you lose your password, please let us know in Discord.
</div>
<button className="btn btn-primary btn-lg w-100 mt-2">
Sign up
</button>
<p>
Already have an account?
<Link
to="/login"
className="button is-info is-large is-fullwidth is-inverted"
>
Log in instead.
</Link>
</p>
</div>
</form>
</div>
<p className={usernameHelpClass}>{usernameInvalidReason}</p>
</div>
<div className="field">
<label className="label">Email</label>
<div className="control has-icons-left has-icons-right">
<input className={emailInputClass} type="email" placeholder="Email" value={email} onChange={handleEmailChange} />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={iconEmailField} />
</span>
</div>
<p className={emailHelpClass}>{emailInvalidReason}</p>
</div>
<div className="field">
<label className="label">Password</label>
<div className="control has-icons-left has-icons-right">
<input className={passwordInputClass} type="password" placeholder="Password" value={password} onChange={handlePasswordChange} />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={iconPasswordField} />
</span>
</div>
<p className={passwordHelpClass}>{passwordInvalidReason}</p>
</div>
<div className="field">
<label className="label">Password Confirmation</label>
<div className="control has-icons-left has-icons-right">
<input className={passwordConfirmationInputClass} type="password" placeholder="Password confirmation" value={passwordConfirmation} onChange={handlePasswordConfirmationChange} />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={iconPasswordField} />
</span>
</div>
<p className={passwordConfirmationHelpClass}>
{passwordConfirmationInvalidReason}
</p>
</div>
<br />
<div className="notification is-warning">
<strong>Remember your password!</strong> We don't have password reset currently, and it'll be a
few more weeks before it's added (there are more important features to work on). If you lose your
password, please let us know in Discord.
</div>
<button className="button is-link is-large is-fullwidth">Sign up</button>
</form>
<br />
<Link to="/login"
className="button is-info is-large is-fullwidth is-inverted"
>Already have an account? Log in instead!</Link>
</div>
</div>
)
);
}
export { SignupPage };
export { SignupPage };