-
Notifications
You must be signed in to change notification settings - Fork 988
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #203 from Infisical/signup-flow
Refactor of the signup flow
- Loading branch information
Showing
16 changed files
with
716 additions
and
516 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import React, { useState } from "react"; | ||
import ReactCodeInput from "react-code-input"; | ||
import { useTranslation } from "next-i18next"; | ||
|
||
import sendVerificationEmail from "~/pages/api/auth/SendVerificationEmail"; | ||
|
||
import Button from "../basic/buttons/Button"; | ||
import Error from "../basic/Error"; | ||
|
||
|
||
// The style for the verification code input | ||
const props = { | ||
inputStyle: { | ||
fontFamily: "monospace", | ||
margin: "4px", | ||
MozAppearance: "textfield", | ||
width: "55px", | ||
borderRadius: "5px", | ||
fontSize: "24px", | ||
height: "55px", | ||
paddingLeft: "7", | ||
backgroundColor: "#0d1117", | ||
color: "white", | ||
border: "1px solid #2d2f33", | ||
textAlign: "center", | ||
outlineColor: "#8ca542", | ||
borderColor: "#2d2f33" | ||
}, | ||
} as const; | ||
const propsPhone = { | ||
inputStyle: { | ||
fontFamily: "monospace", | ||
margin: "4px", | ||
MozAppearance: "textfield", | ||
width: "40px", | ||
borderRadius: "5px", | ||
fontSize: "24px", | ||
height: "40px", | ||
paddingLeft: "7", | ||
backgroundColor: "#0d1117", | ||
color: "white", | ||
border: "1px solid #2d2f33", | ||
textAlign: "center", | ||
outlineColor: "#8ca542", | ||
borderColor: "#2d2f33" | ||
}, | ||
} as const; | ||
|
||
interface CodeInputStepProps { | ||
email: string; | ||
incrementStep: () => void; | ||
setCode: (value: string) => void; | ||
codeError: boolean; | ||
} | ||
|
||
/** | ||
* This is the second step of sign up where users need to verify their email | ||
* @param {object} obj | ||
* @param {string} obj.email - user's email to which we just sent a verification email | ||
* @param {function} obj.incrementStep - goes to the next step of signup | ||
* @param {function} obj.setCode - state updating function that set the current value of the emai verification code | ||
* @param {boolean} obj.codeError - whether the code was inputted wrong or now | ||
* @returns | ||
*/ | ||
export default function CodeInputStep({ email, incrementStep, setCode, codeError }: CodeInputStepProps): JSX.Element { | ||
const [isLoading, setIsLoading] = useState(false); | ||
const [isResendingVerificationEmail, setIsResendingVerificationEmail] = | ||
useState(false); | ||
const { t } = useTranslation(); | ||
|
||
const resendVerificationEmail = async () => { | ||
setIsResendingVerificationEmail(true); | ||
setIsLoading(true); | ||
sendVerificationEmail(email); | ||
setTimeout(() => { | ||
setIsLoading(false); | ||
setIsResendingVerificationEmail(false); | ||
}, 2000); | ||
}; | ||
|
||
return ( | ||
<div className="bg-bunker w-max mx-auto h-7/12 pt-10 pb-4 px-8 rounded-xl drop-shadow-xl mb-64 md:mb-16"> | ||
<p className="text-l flex justify-center text-bunker-300"> | ||
{"We've"} sent a verification email to{" "} | ||
</p> | ||
<p className="text-l flex justify-center font-semibold my-2 text-bunker-300"> | ||
{email}{" "} | ||
</p> | ||
<div className="hidden md:block"> | ||
<ReactCodeInput | ||
name="" | ||
inputMode="tel" | ||
type="text" | ||
fields={6} | ||
onChange={setCode} | ||
{...props} | ||
className="mt-6 mb-2" | ||
/> | ||
</div> | ||
<div className="block md:hidden"> | ||
<ReactCodeInput | ||
name="" | ||
inputMode="tel" | ||
type="text" | ||
fields={6} | ||
onChange={setCode} | ||
{...propsPhone} | ||
className="mt-2 mb-6" | ||
/> | ||
</div> | ||
{codeError && <Error text={t("signup:step2-code-error")} />} | ||
<div className="flex max-w-max min-w-28 flex-col items-center justify-center md:p-2 max-h-24 mx-auto text-lg px-4 mt-4 mb-2"> | ||
<Button | ||
text={t("signup:verify") ?? ""} | ||
onButtonPressed={incrementStep} | ||
size="lg" | ||
/> | ||
</div> | ||
<div className="flex flex-col items-center justify-center w-full max-h-24 max-w-md mx-auto pt-2"> | ||
<div className="flex flex-row items-baseline gap-1 text-sm"> | ||
<span className="text-bunker-400"> | ||
Not seeing an email? | ||
</span> | ||
<u className={`font-normal ${isResendingVerificationEmail ? 'text-bunker-400' : 'text-primary-700 hover:text-primary duration-200'}`}> | ||
<button disabled={isLoading} onClick={resendVerificationEmail}> | ||
{isResendingVerificationEmail ? "Resending..." : "Resend"} | ||
</button> | ||
</u> | ||
</div> | ||
<p className="text-sm text-bunker-400 pb-2"> | ||
{t("signup:step2-spam-alert")} | ||
</p> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import React from "react"; | ||
import { useTranslation } from "next-i18next"; | ||
import { faWarning } from "@fortawesome/free-solid-svg-icons"; | ||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | ||
|
||
import Button from "../basic/buttons/Button"; | ||
import issueBackupKey from "../utilities/cryptography/issueBackupKey"; | ||
|
||
|
||
interface DownloadBackupPDFStepProps { | ||
incrementStep: () => void; | ||
email: string; | ||
password: string; | ||
name: string; | ||
} | ||
|
||
/** | ||
* This is the step of the signup flow where the user downloads the backup pdf | ||
* @param {object} obj | ||
* @param {function} obj.incrementStep - function that moves the user on to the next stage of signup | ||
* @param {string} obj.email - user's email | ||
* @param {string} obj.password - user's password | ||
* @param {string} obj.name - user's name | ||
* @returns | ||
*/ | ||
export default function DonwloadBackupPDFStep({ incrementStep, email, password, name }: DownloadBackupPDFStepProps): JSX.Element { | ||
const { t } = useTranslation(); | ||
|
||
return ( | ||
<div className="bg-bunker flex flex-col items-center w-full max-w-xs md:max-w-lg mx-auto h-7/12 py-8 px-4 md:px-6 mx-1 mb-36 md:mb-16 rounded-xl drop-shadow-xl"> | ||
<p className="text-4xl text-center font-semibold flex justify-center text-transparent bg-clip-text bg-gradient-to-br from-sky-400 to-primary"> | ||
{t("signup:step4-message")} | ||
</p> | ||
<div className="flex flex-col items-center justify-center w-full mt-4 md:mt-8 max-w-md text-gray-400 text-md rounded-md px-2"> | ||
<div>{t("signup:step4-description1")}</div> | ||
<div className="mt-3">{t("signup:step4-description2")}</div> | ||
</div> | ||
<div className="w-full p-2 flex flex-row items-center bg-white/10 text-gray-400 rounded-md max-w-xs md:max-w-md mx-auto mt-4"> | ||
<FontAwesomeIcon icon={faWarning} className="ml-2 mr-4 text-4xl" /> | ||
{t("signup:step4-description3")} | ||
</div> | ||
<div className="flex flex-col items-center justify-center md:px-4 md:py-5 mt-2 px-2 py-3 max-h-24 max-w-max mx-auto text-lg"> | ||
<Button | ||
text="Download PDF" | ||
onButtonPressed={async () => { | ||
await issueBackupKey({ | ||
email, | ||
password, | ||
personalName: name, | ||
setBackupKeyError: (value: boolean) => {}, | ||
setBackupKeyIssued: (value: boolean) => {}, | ||
}); | ||
incrementStep(); | ||
}} | ||
size="lg" | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import React, { useState } from "react"; | ||
import Link from "next/link"; | ||
import { useTranslation } from "next-i18next"; | ||
|
||
import sendVerificationEmail from "~/pages/api/auth/SendVerificationEmail"; | ||
|
||
import Button from "../basic/buttons/Button"; | ||
import InputField from "../basic/InputField"; | ||
|
||
|
||
interface DownloadBackupPDFStepProps { | ||
incrementStep: () => void; | ||
email: string; | ||
setEmail: (value: string) => void; | ||
} | ||
|
||
/** | ||
* This is the first step of the sign up process - users need to enter their email | ||
* @param {object} obj | ||
* @param {string} obj.email - email of a user signing up | ||
* @param {function} obj.setEmail - funciton that manages the state of the email variable | ||
* @param {function} obj.incrementStep - function to go to the next step of the signup flow | ||
* @returns | ||
*/ | ||
export default function EnterEmailStep({ email, setEmail, incrementStep }: DownloadBackupPDFStepProps): JSX.Element { | ||
const [emailError, setEmailError] = useState(false); | ||
const [emailErrorMessage, setEmailErrorMessage] = useState(""); | ||
const { t } = useTranslation(); | ||
|
||
/** | ||
* Verifies if the entered email "looks" correct | ||
*/ | ||
const emailCheck = () => { | ||
let emailCheckBool = false; | ||
if (!email) { | ||
setEmailError(true); | ||
setEmailErrorMessage("Please enter your email."); | ||
emailCheckBool = true; | ||
} else if ( | ||
!email.includes("@") || | ||
!email.includes(".") || | ||
!/[a-z]/.test(email) | ||
) { | ||
setEmailError(true); | ||
setEmailErrorMessage("Please enter a valid email."); | ||
emailCheckBool = true; | ||
} else { | ||
setEmailError(false); | ||
} | ||
|
||
// If everything is correct, go to the next step | ||
if (!emailCheckBool) { | ||
sendVerificationEmail(email); | ||
incrementStep(); | ||
} | ||
}; | ||
|
||
return ( | ||
<div> | ||
<div className="bg-bunker w-full max-w-md mx-auto h-7/12 py-8 md:px-6 mx-1 rounded-xl drop-shadow-xl"> | ||
<p className="text-4xl font-semibold flex justify-center text-primary"> | ||
{'Let\''}s get started | ||
</p> | ||
<div className="flex items-center justify-center w-5/6 md:w-full m-auto md:p-2 rounded-lg max-h-24 mt-4"> | ||
<InputField | ||
label="Email" | ||
onChangeHandler={setEmail} | ||
type="email" | ||
value={email} | ||
placeholder="" | ||
isRequired | ||
error={emailError} | ||
errorText={emailErrorMessage} | ||
autoComplete="username" | ||
/> | ||
</div> | ||
<div className="flex flex-col items-center justify-center w-5/6 md:w-full md:p-2 max-h-28 max-w-xs md:max-w-md mx-auto mt-4 md:mt-4 text-sm text-center md:text-left"> | ||
<p className="text-gray-400 mt-2 md:mx-0.5"> | ||
{t("signup:step1-privacy")} | ||
</p> | ||
<div className="text-l mt-6 m-2 md:m-8 px-8 py-1 text-lg"> | ||
<Button text="Get Started" type="submit" onButtonPressed={emailCheck} size="lg" /> | ||
</div> | ||
</div> | ||
</div> | ||
<div className="flex flex-col items-center justify-center w-full md:pb-2 max-w-md mx-auto pt-2 mb-48 md:mb-16 mt-2"> | ||
<Link href="/login"> | ||
<button type="button" className="w-max pb-3 hover:opacity-90 duration-200"> | ||
<u className="font-normal text-sm text-primary-500"> | ||
{t("signup:already-have-account")} | ||
</u> | ||
</button> | ||
</Link> | ||
</div> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.
0312891
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coverage report for
backend
Test suite run success
1 tests passing in 1 suite.
Report generated by 🧪jest coverage report action from 0312891
0312891
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coverage report for
backend
Test suite run success
1 tests passing in 1 suite.
Report generated by 🧪jest coverage report action from 0312891
0312891
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coverage report for
backend
Test suite run success
1 tests passing in 1 suite.
Report generated by 🧪jest coverage report action from 0312891
0312891
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coverage report for
backend
Test suite run success
1 tests passing in 1 suite.
Report generated by 🧪jest coverage report action from 0312891
0312891
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coverage report for
backend
Test suite run success
1 tests passing in 1 suite.
Report generated by 🧪jest coverage report action from 0312891