2021-06-22 21:32:30 +03:00
|
|
|
/* eslint-disable jsx-a11y/no-autofocus */
|
2021-06-09 01:53:30 +03:00
|
|
|
import * as React from "react";
|
|
|
|
import * as System from "~/components/system";
|
|
|
|
import * as Validations from "~/common/validations";
|
2021-06-10 10:19:31 +03:00
|
|
|
import * as Actions from "~/common/actions";
|
2021-06-22 21:32:30 +03:00
|
|
|
import * as Styles from "~/common/styles";
|
2021-06-09 01:53:30 +03:00
|
|
|
|
|
|
|
import Field from "~/components/core/Field";
|
|
|
|
|
|
|
|
import { AnimateSharedLayout, motion } from "framer-motion";
|
2021-06-10 10:19:31 +03:00
|
|
|
import { LoaderSpinner } from "~/components/system/components/Loaders";
|
2021-06-09 01:53:30 +03:00
|
|
|
import { css } from "@emotion/react";
|
|
|
|
import { useForm } from "~/common/hooks";
|
|
|
|
|
|
|
|
import { SignUpPopover, Verification, AuthCheckBox } from "~/components/core/Auth/components";
|
|
|
|
|
2021-06-22 21:32:30 +03:00
|
|
|
const STYLES_LINK = css`
|
|
|
|
padding: 0;
|
|
|
|
margin: 0;
|
|
|
|
max-width: 224px;
|
2021-06-09 01:53:30 +03:00
|
|
|
text-align: center;
|
|
|
|
margin: 0 auto;
|
2021-06-22 21:32:30 +03:00
|
|
|
background-color: unset;
|
|
|
|
border: none;
|
2021-06-09 01:53:30 +03:00
|
|
|
`;
|
|
|
|
|
|
|
|
const useTwitterSignup = () => {
|
|
|
|
const [scene, setScene] = React.useState("accountCreation");
|
|
|
|
const handlers = React.useMemo(() => ({ goToVerification: () => setScene("verification") }), []);
|
|
|
|
return { ...handlers, scene };
|
|
|
|
};
|
|
|
|
|
2021-06-10 10:19:31 +03:00
|
|
|
const useCheckUser = () => {
|
|
|
|
const MESSAGE = "The username is taken.";
|
|
|
|
|
|
|
|
const usernamesAllowed = React.useRef([]);
|
|
|
|
const usernamesTaken = React.useRef([]);
|
|
|
|
|
|
|
|
return async ({ username }, errors) => {
|
|
|
|
if (usernamesAllowed.current.some((value) => value === username)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (usernamesTaken.current.some((value) => value === username)) {
|
|
|
|
errors.username = MESSAGE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const response = await Actions.checkUsername({
|
|
|
|
username,
|
|
|
|
});
|
|
|
|
if (response.data) {
|
|
|
|
errors.username = "The username is taken.";
|
|
|
|
usernamesTaken.current.push(username);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
usernamesAllowed.current.push(username);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2021-06-22 21:32:30 +03:00
|
|
|
const createValidations =
|
|
|
|
(validateUsername) =>
|
|
|
|
async ({ username, email, acceptTerms }, errors) => {
|
|
|
|
await validateUsername({ username }, errors);
|
2021-06-10 10:19:31 +03:00
|
|
|
|
2021-06-22 21:32:30 +03:00
|
|
|
if (!Validations.username(username)) errors.username = "Invalid username";
|
|
|
|
// Note(amine): username should not be an email
|
|
|
|
if (Validations.email(username)) errors.username = "Username shouldn't be an email";
|
2021-06-09 01:53:30 +03:00
|
|
|
|
2021-06-22 21:32:30 +03:00
|
|
|
if (!Validations.email(email)) errors.email = "Invalid email";
|
2021-06-09 01:53:30 +03:00
|
|
|
|
2021-06-22 21:32:30 +03:00
|
|
|
if (!acceptTerms) errors.acceptTerms = "Must accept terms and conditions";
|
2021-06-09 01:53:30 +03:00
|
|
|
|
2021-06-22 21:32:30 +03:00
|
|
|
return errors;
|
|
|
|
};
|
2021-06-09 01:53:30 +03:00
|
|
|
|
|
|
|
const MotionLayout = ({ children, ...props }) => (
|
|
|
|
<motion.div layout {...props}>
|
|
|
|
{children}
|
|
|
|
</motion.div>
|
|
|
|
);
|
|
|
|
|
|
|
|
export default function TwitterSignup({
|
|
|
|
initialEmail,
|
|
|
|
onSignup,
|
2021-06-22 21:32:30 +03:00
|
|
|
goToTwitterLinkingScene,
|
2021-06-09 01:53:30 +03:00
|
|
|
createVerification,
|
|
|
|
onSignupWithVerification,
|
|
|
|
}) {
|
|
|
|
const { scene, goToVerification } = useTwitterSignup();
|
2021-06-10 10:19:31 +03:00
|
|
|
|
|
|
|
const validateUsername = useCheckUser();
|
|
|
|
|
2021-06-09 01:53:30 +03:00
|
|
|
const {
|
|
|
|
getFieldProps,
|
|
|
|
getFormProps,
|
2021-06-22 21:32:30 +03:00
|
|
|
values: { username },
|
2021-06-09 01:53:30 +03:00
|
|
|
isSubmitting,
|
2021-06-10 10:19:31 +03:00
|
|
|
isValidating,
|
2021-06-09 01:53:30 +03:00
|
|
|
} = useForm({
|
|
|
|
initialValues: { username: "", email: initialEmail, acceptTerms: false },
|
2021-06-10 10:19:31 +03:00
|
|
|
validate: createValidations(validateUsername),
|
2021-06-09 01:53:30 +03:00
|
|
|
onSubmit: async ({ username, email }) => {
|
|
|
|
if (email !== initialEmail) {
|
|
|
|
const response = await createVerification({ email });
|
|
|
|
if (!response) return;
|
|
|
|
goToVerification();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
await onSignup({ email, username });
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
if (scene === "verification") {
|
|
|
|
const handleVerification = async ({ pin }) => {
|
|
|
|
await onSignupWithVerification({ username, pin });
|
|
|
|
};
|
|
|
|
return <Verification onVerify={handleVerification} />;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<SignUpPopover title="Create an account">
|
|
|
|
<form {...getFormProps()}>
|
|
|
|
<Field
|
|
|
|
autoFocus
|
|
|
|
containerStyle={{ marginTop: 41 }}
|
|
|
|
placeholder="Username"
|
2021-06-09 04:01:16 +03:00
|
|
|
name="username"
|
|
|
|
type="text"
|
2021-06-10 10:19:31 +03:00
|
|
|
success="The username is available."
|
|
|
|
icon={
|
|
|
|
isValidating
|
|
|
|
? () => (
|
|
|
|
<LoaderSpinner
|
|
|
|
style={{
|
|
|
|
height: 16,
|
|
|
|
width: 16,
|
|
|
|
marginLeft: 16,
|
|
|
|
position: "absolute",
|
|
|
|
right: 12,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
: null
|
|
|
|
}
|
2021-06-09 01:53:30 +03:00
|
|
|
{...getFieldProps("username")}
|
2021-06-22 21:32:30 +03:00
|
|
|
full
|
2021-06-09 01:53:30 +03:00
|
|
|
/>
|
|
|
|
<AnimateSharedLayout>
|
|
|
|
<Field
|
|
|
|
containerStyle={{ marginTop: 16 }}
|
|
|
|
containerAs={MotionLayout}
|
|
|
|
errorAs={MotionLayout}
|
|
|
|
placeholder="Email"
|
2021-06-09 04:01:16 +03:00
|
|
|
name="email"
|
2021-06-09 01:53:30 +03:00
|
|
|
type="email"
|
2021-06-22 21:32:30 +03:00
|
|
|
full
|
2021-06-09 01:53:30 +03:00
|
|
|
{...getFieldProps("email")}
|
|
|
|
/>
|
|
|
|
|
|
|
|
<motion.div layout>
|
|
|
|
<AuthCheckBox style={{ marginTop: 16 }} {...getFieldProps("acceptTerms")} />
|
|
|
|
<System.ButtonPrimary
|
|
|
|
full
|
|
|
|
style={{ marginTop: 36 }}
|
|
|
|
loading={isSubmitting}
|
|
|
|
type="submit"
|
|
|
|
>
|
|
|
|
Create account
|
|
|
|
</System.ButtonPrimary>
|
|
|
|
</motion.div>
|
2021-06-22 21:32:30 +03:00
|
|
|
|
|
|
|
<motion.div layout>
|
|
|
|
<div style={{ textAlign: "center", marginTop: 24 }}>
|
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
onClick={goToTwitterLinkingScene}
|
|
|
|
css={[Styles.LINK, STYLES_LINK]}
|
|
|
|
>
|
|
|
|
Already have an account? Connect your account to Twitter.
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</motion.div>
|
2021-06-09 01:53:30 +03:00
|
|
|
</AnimateSharedLayout>
|
|
|
|
</form>
|
|
|
|
</SignUpPopover>
|
|
|
|
);
|
|
|
|
}
|