mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 12:26:38 +00:00
Merge pull request #3905 from Infisical/password-reset-ui
improvement(password-reset): re-vamp password reset flow pages/steps to match login
This commit is contained in:
@@ -1,19 +1,33 @@
|
|||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
|
import { Link } from "@tanstack/react-router";
|
||||||
|
|
||||||
export const EmailNotVerifiedPage = () => {
|
export const EmailNotVerifiedPage = () => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col justify-between bg-bunker-800 md:h-screen">
|
<div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>Request a New Invite</title>
|
<title>Request a New Invite</title>
|
||||||
<link rel="icon" href="/infisical.ico" />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className="flex h-screen w-screen flex-col items-center justify-center text-gray-200">
|
<Link to="/">
|
||||||
<p className="text-6xl">Oops.</p>
|
<div className="mb-4 mt-20 flex justify-center">
|
||||||
<p className="mb-1 mt-2 text-xl">Your email was not verified. </p>
|
<img src="/images/gradientLogo.svg" className="h-[90px] w-[120px]" alt="Infisical Logo" />
|
||||||
<p className="text-xl">Please try again.</p>
|
</div>
|
||||||
<p className="text-md mt-8 max-w-sm text-center text-gray-600">
|
</Link>
|
||||||
Note: If it still doesn't work, please reach out to us at support@infisical.com
|
<div className="mx-auto flex w-full flex-col items-center justify-center">
|
||||||
|
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
|
||||||
|
Your email was not verified
|
||||||
|
</h1>
|
||||||
|
<p className="w-max justify-center text-center text-sm text-gray-400">
|
||||||
|
Please try again. <br /> Note: If it still doesn't work, please reach out to us at
|
||||||
|
support@infisical.com
|
||||||
</p>
|
</p>
|
||||||
|
<div className="mt-6 flex flex-row text-sm text-bunker-400">
|
||||||
|
<Link to="/login">
|
||||||
|
<span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
|
||||||
|
Back to Login
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useNavigate } from "@tanstack/react-router";
|
import { Link, useNavigate } from "@tanstack/react-router";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { UserEncryptionVersion } from "@app/hooks/api/auth/types";
|
import { UserEncryptionVersion } from "@app/hooks/api/auth/types";
|
||||||
@@ -36,7 +36,12 @@ export const PasswordResetPage = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen w-full flex-col items-center justify-center bg-bunker-800">
|
<div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
|
||||||
|
<Link to="/">
|
||||||
|
<div className="mb-4 mt-20 flex justify-center">
|
||||||
|
<img src="/images/gradientLogo.svg" className="h-[90px] w-[120px]" alt="Infisical Logo" />
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
{step === Steps.ConfirmEmail && (
|
{step === Steps.ConfirmEmail && (
|
||||||
<ConfirmEmailStep
|
<ConfirmEmailStep
|
||||||
onComplete={(verifyToken, userEncryptionVersion) => {
|
onComplete={(verifyToken, userEncryptionVersion) => {
|
||||||
|
|||||||
@@ -19,17 +19,21 @@ export const ConfirmEmailStep = ({ onComplete }: Props) => {
|
|||||||
isPending: isVerifyPasswordResetLoading
|
isPending: isVerifyPasswordResetLoading
|
||||||
} = useVerifyPasswordResetCode();
|
} = useVerifyPasswordResetCode();
|
||||||
return (
|
return (
|
||||||
<div className="mx-1 my-32 flex w-full max-w-xs flex-col items-center rounded-xl bg-bunker px-4 py-6 drop-shadow-xl md:max-w-lg md:px-6">
|
<div className="mx-auto flex w-full flex-col items-center justify-center">
|
||||||
<p className="mb-8 flex justify-center bg-gradient-to-br from-sky-400 to-primary bg-clip-text text-center text-4xl font-semibold text-transparent">
|
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
|
||||||
Confirm your email
|
Confirm your email
|
||||||
|
</h1>
|
||||||
|
<p className="mb-8 w-max justify-center text-center text-sm text-gray-400">
|
||||||
|
Reset password for <span className="italic">{email}</span>.
|
||||||
</p>
|
</p>
|
||||||
<img
|
<div className="w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
|
||||||
src="/images/envelope.svg"
|
|
||||||
style={{ height: "262px", width: "410px" }}
|
|
||||||
alt="verify email"
|
|
||||||
/>
|
|
||||||
<div className="mx-auto mb-2 mt-4 flex max-h-24 max-w-md flex-col items-center justify-center px-4 text-lg md:p-2">
|
|
||||||
<Button
|
<Button
|
||||||
|
type="submit"
|
||||||
|
size="sm"
|
||||||
|
isFullWidth
|
||||||
|
className="h-10"
|
||||||
|
colorSchema="primary"
|
||||||
|
variant="solid"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
try {
|
try {
|
||||||
const response = await verifyPasswordResetCodeMutateAsync({
|
const response = await verifyPasswordResetCodeMutateAsync({
|
||||||
@@ -44,7 +48,6 @@ export const ConfirmEmailStep = ({ onComplete }: Props) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
isLoading={isVerifyPasswordResetLoading}
|
isLoading={isVerifyPasswordResetLoading}
|
||||||
size="lg"
|
|
||||||
>
|
>
|
||||||
Confirm Email
|
Confirm Email
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
|
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { faCheck, faX } from "@fortawesome/free-solid-svg-icons";
|
import { faCheck, faXmark } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useSearch } from "@tanstack/react-router";
|
import { useSearch } from "@tanstack/react-router";
|
||||||
@@ -169,17 +169,15 @@ export const EnterPasswordStep = ({
|
|||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit(resetPasswordHandler)}
|
onSubmit={handleSubmit(resetPasswordHandler)}
|
||||||
className="mx-1 my-32 flex w-full max-w-xs flex-col items-center rounded-xl bg-bunker px-4 pb-3 pt-6 drop-shadow-xl md:max-w-lg md:px-6"
|
className="mx-auto flex w-full flex-col items-center justify-center"
|
||||||
>
|
>
|
||||||
<p className="mx-auto flex w-max justify-center text-2xl font-semibold text-bunker-100 md:text-3xl">
|
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
|
||||||
Enter new password
|
Enter new password
|
||||||
|
</h1>
|
||||||
|
<p className="w-max justify-center text-center text-sm text-gray-400">
|
||||||
|
Make sure you save it somewhere safe.
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-1 flex flex-row items-center justify-center md:mx-2 md:pb-4">
|
<div className="mt-8 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
|
||||||
<p className="flex w-max max-w-md justify-center text-sm text-gray-400">
|
|
||||||
Make sure you save it somewhere safe.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 flex max-h-24 w-full items-center justify-center rounded-lg md:mt-0 md:max-h-28 md:p-2">
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="password"
|
name="password"
|
||||||
@@ -202,6 +200,20 @@ export const EnterPasswordStep = ({
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
size="sm"
|
||||||
|
isFullWidth
|
||||||
|
className="h-10"
|
||||||
|
colorSchema="primary"
|
||||||
|
variant="solid"
|
||||||
|
isLoading={isSubmitting || isLoading || isLoadingV2}
|
||||||
|
isDisabled={isSubmitting || isLoading || isLoadingV2}
|
||||||
|
>
|
||||||
|
Change Password
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
{passwordErrorTooShort ||
|
{passwordErrorTooShort ||
|
||||||
passwordErrorTooLong ||
|
passwordErrorTooLong ||
|
||||||
passwordErrorNoLetterChar ||
|
passwordErrorNoLetterChar ||
|
||||||
@@ -210,33 +222,33 @@ export const EnterPasswordStep = ({
|
|||||||
passwordErrorEscapeChar ||
|
passwordErrorEscapeChar ||
|
||||||
passwordErrorLowEntropy ||
|
passwordErrorLowEntropy ||
|
||||||
passwordErrorBreached ? (
|
passwordErrorBreached ? (
|
||||||
<div className="mx-2 mb-2 mt-3 flex w-full max-w-md flex-col items-start rounded-md bg-white/5 px-2 py-2">
|
<div className="mt-4 rounded border border-mineshaft-600 bg-mineshaft-800 p-4 drop-shadow">
|
||||||
<div className="mb-1 text-sm text-gray-400">Password should contain:</div>
|
<div className="mb-1 ml-2 text-sm text-gray-300">Password should contain:</div>
|
||||||
<div className="ml-1 flex flex-row items-center justify-start">
|
<div className="ml-2 flex flex-row items-center justify-start">
|
||||||
{passwordErrorTooShort ? (
|
{passwordErrorTooShort ? (
|
||||||
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
|
<FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
|
||||||
) : (
|
) : (
|
||||||
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
|
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
|
||||||
)}
|
)}
|
||||||
<div className={`${passwordErrorTooShort ? "text-gray-400" : "text-gray-600"} text-sm`}>
|
<div className={`${passwordErrorTooShort ? "text-gray-400" : "text-gray-600"} text-sm`}>
|
||||||
at least 14 characters
|
at least 14 characters
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 flex flex-row items-center justify-start">
|
<div className="ml-2 flex flex-row items-center justify-start">
|
||||||
{passwordErrorTooLong ? (
|
{passwordErrorTooLong ? (
|
||||||
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
|
<FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
|
||||||
) : (
|
) : (
|
||||||
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
|
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
|
||||||
)}
|
)}
|
||||||
<div className={`${passwordErrorTooLong ? "text-gray-400" : "text-gray-600"} text-sm`}>
|
<div className={`${passwordErrorTooLong ? "text-gray-400" : "text-gray-600"} text-sm`}>
|
||||||
at most 100 characters
|
at most 100 characters
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 flex flex-row items-center justify-start">
|
<div className="ml-2 flex flex-row items-center justify-start">
|
||||||
{passwordErrorNoLetterChar ? (
|
{passwordErrorNoLetterChar ? (
|
||||||
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
|
<FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
|
||||||
) : (
|
) : (
|
||||||
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
|
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={`${passwordErrorNoLetterChar ? "text-gray-400" : "text-gray-600"} text-sm`}
|
className={`${passwordErrorNoLetterChar ? "text-gray-400" : "text-gray-600"} text-sm`}
|
||||||
@@ -244,11 +256,11 @@ export const EnterPasswordStep = ({
|
|||||||
at least 1 letter character
|
at least 1 letter character
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 flex flex-row items-center justify-start">
|
<div className="ml-2 flex flex-row items-center justify-start">
|
||||||
{passwordErrorNoNumOrSpecialChar ? (
|
{passwordErrorNoNumOrSpecialChar ? (
|
||||||
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
|
<FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
|
||||||
) : (
|
) : (
|
||||||
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
|
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={`${
|
className={`${
|
||||||
@@ -258,11 +270,11 @@ export const EnterPasswordStep = ({
|
|||||||
at least 1 number or special character
|
at least 1 number or special character
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 flex flex-row items-center justify-start">
|
<div className="ml-2 flex flex-row items-center justify-start">
|
||||||
{passwordErrorRepeatedChar ? (
|
{passwordErrorRepeatedChar ? (
|
||||||
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
|
<FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
|
||||||
) : (
|
) : (
|
||||||
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
|
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={`${passwordErrorRepeatedChar ? "text-gray-400" : "text-gray-600"} text-sm`}
|
className={`${passwordErrorRepeatedChar ? "text-gray-400" : "text-gray-600"} text-sm`}
|
||||||
@@ -270,11 +282,11 @@ export const EnterPasswordStep = ({
|
|||||||
at most 3 repeated, consecutive characters
|
at most 3 repeated, consecutive characters
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 flex flex-row items-center justify-start">
|
<div className="ml-2 flex flex-row items-center justify-start">
|
||||||
{passwordErrorEscapeChar ? (
|
{passwordErrorEscapeChar ? (
|
||||||
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
|
<FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
|
||||||
) : (
|
) : (
|
||||||
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
|
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={`${passwordErrorEscapeChar ? "text-gray-400" : "text-gray-600"} text-sm`}
|
className={`${passwordErrorEscapeChar ? "text-gray-400" : "text-gray-600"} text-sm`}
|
||||||
@@ -282,11 +294,11 @@ export const EnterPasswordStep = ({
|
|||||||
No escape characters allowed.
|
No escape characters allowed.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 flex flex-row items-center justify-start">
|
<div className="ml-2 flex flex-row items-center justify-start">
|
||||||
{passwordErrorLowEntropy ? (
|
{passwordErrorLowEntropy ? (
|
||||||
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
|
<FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
|
||||||
) : (
|
) : (
|
||||||
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
|
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={`${passwordErrorLowEntropy ? "text-gray-400" : "text-gray-600"} text-sm`}
|
className={`${passwordErrorLowEntropy ? "text-gray-400" : "text-gray-600"} text-sm`}
|
||||||
@@ -294,32 +306,18 @@ export const EnterPasswordStep = ({
|
|||||||
Password contains personal info.
|
Password contains personal info.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 flex flex-row items-center justify-start">
|
<div className="ml-2 flex flex-row items-center justify-start">
|
||||||
{passwordErrorBreached ? (
|
{passwordErrorBreached ? (
|
||||||
<FontAwesomeIcon icon={faX} className="text-md mr-2.5 text-red" />
|
<FontAwesomeIcon icon={faXmark} className="mr-2.5 text-lg text-red" />
|
||||||
) : (
|
) : (
|
||||||
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-primary" />
|
<FontAwesomeIcon icon={faCheck} className="text-md mr-2 text-green" />
|
||||||
)}
|
)}
|
||||||
<div className={`${passwordErrorBreached ? "text-gray-400" : "text-gray-600"} text-sm`}>
|
<div className={`${passwordErrorBreached ? "text-gray-400" : "text-gray-600"} text-sm`}>
|
||||||
Password was found in a data breach.
|
Password was found in a data breach.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : null}
|
||||||
<div className="py-2" />
|
|
||||||
)}
|
|
||||||
<div className="mx-auto mt-4 flex max-h-20 w-full max-w-md flex-col items-center justify-center text-sm md:p-2">
|
|
||||||
<div className="text-l m-8 mt-6 px-8 py-3 text-lg">
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
colorSchema="secondary"
|
|
||||||
isLoading={isSubmitting || isLoading || isLoadingV2}
|
|
||||||
isDisabled={isSubmitting || isLoading || isLoadingV2}
|
|
||||||
>
|
|
||||||
Change Password
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,18 +43,15 @@ export const InputBackupKeyStep = ({ verificationToken, onComplete }: Props) =>
|
|||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit(getEncryptedKeyHandler)}
|
onSubmit={handleSubmit(getEncryptedKeyHandler)}
|
||||||
className="mx-1 my-32 flex w-full max-w-xs flex-col items-center rounded-xl bg-bunker px-4 pb-3 pt-6 drop-shadow-xl md:max-w-lg md:px-6"
|
className="mx-auto flex w-full flex-col items-center justify-center"
|
||||||
>
|
>
|
||||||
<p className="mx-auto mb-4 flex w-max justify-center text-2xl font-semibold text-bunker-100">
|
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
|
||||||
Enter your backup key
|
Enter your backup key
|
||||||
|
</h1>
|
||||||
|
<p className="w-max justify-center text-center text-sm text-gray-400">
|
||||||
|
You can find it in your emergency kit you downloaded during signup.
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-4 flex flex-row items-center justify-center md:mx-2 md:pb-4">
|
<div className="mt-8 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
|
||||||
<p className="flex w-full px-4 text-center text-sm text-gray-400 sm:max-w-md">
|
|
||||||
You can find it in your emergency kit. You had to download the emergency kit during
|
|
||||||
signup.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 flex max-h-24 w-full items-center justify-center rounded-lg md:mt-0 md:max-h-28 md:p-2">
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="backupKey"
|
name="backupKey"
|
||||||
@@ -75,12 +72,17 @@ export const InputBackupKeyStep = ({ verificationToken, onComplete }: Props) =>
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx-auto mt-4 flex max-h-20 w-full max-w-md flex-col items-center justify-center text-sm md:p-2">
|
<div className="w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
|
||||||
<div className="text-l m-8 mt-6 px-8 py-3 text-lg">
|
<Button
|
||||||
<Button type="submit" colorSchema="secondary">
|
type="submit"
|
||||||
Submit Backup Key
|
size="sm"
|
||||||
</Button>
|
isFullWidth
|
||||||
</div>
|
className="h-10"
|
||||||
|
colorSchema="primary"
|
||||||
|
variant="solid"
|
||||||
|
>
|
||||||
|
Submit Backup Key
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ import { FormEvent, useState } from "react";
|
|||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
import { Link } from "@tanstack/react-router";
|
import { Link } from "@tanstack/react-router";
|
||||||
|
|
||||||
import InputField from "@app/components/basic/InputField";
|
import { Button, EmailServiceSetupModal, Input } from "@app/components/v2";
|
||||||
import { Button, EmailServiceSetupModal } from "@app/components/v2";
|
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import { useSendPasswordResetEmail } from "@app/hooks/api";
|
import { useSendPasswordResetEmail } from "@app/hooks/api";
|
||||||
import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
|
import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
|
||||||
@@ -44,9 +43,9 @@ export const VerifyEmailPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen flex-col justify-start bg-bunker-800 px-6">
|
<div className="flex min-h-screen flex-col justify-center bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700 px-6 pb-28">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>Login</title>
|
<title>Reset Password</title>
|
||||||
<link rel="icon" href="/infisical.ico" />
|
<link rel="icon" href="/infisical.ico" />
|
||||||
<meta property="og:image" content="/images/message.png" />
|
<meta property="og:image" content="/images/message.png" />
|
||||||
<meta property="og:title" content="Verify your email in Infisical" />
|
<meta property="og:title" content="Verify your email in Infisical" />
|
||||||
@@ -56,66 +55,80 @@ export const VerifyEmailPage = () => {
|
|||||||
/>
|
/>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<div className="mb-8 mt-20 flex cursor-pointer justify-center">
|
<div className="mb-4 mt-20 flex justify-center">
|
||||||
<img
|
<img
|
||||||
src="/images/biglogo.png"
|
src="/images/gradientLogo.svg"
|
||||||
style={{
|
style={{
|
||||||
height: "90px",
|
height: "90px",
|
||||||
width: "120px"
|
width: "120px"
|
||||||
}}
|
}}
|
||||||
alt="long logo"
|
alt="Infisical Logo"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
{step === 1 && (
|
{step === 1 && (
|
||||||
<form
|
<form
|
||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
className="h-7/12 mx-auto w-full max-w-md rounded-xl bg-bunker px-6 py-4 pt-8 drop-shadow-xl"
|
className="mx-auto flex w-full flex-col items-center justify-center"
|
||||||
>
|
>
|
||||||
<p className="mx-auto mb-6 flex w-max justify-center text-2xl font-semibold text-bunker-100 md:text-3xl">
|
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
|
||||||
Forgot your password?
|
Forgot your password?
|
||||||
|
</h1>
|
||||||
|
<p className="w-max justify-center text-center text-sm text-gray-400">
|
||||||
|
Enter your email to start the password reset process. <br /> You will receive an email
|
||||||
|
with instructions.
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-4 flex flex-row items-center justify-center md:mx-2 md:pb-4">
|
<div className="mt-8 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
|
||||||
<p className="flex w-max justify-center text-center text-sm text-gray-400">
|
<Input
|
||||||
Enter your email to start the password reset process. You will receive an email with
|
|
||||||
instructions.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 flex max-h-24 w-full items-center justify-center rounded-lg md:mt-0 md:max-h-28 md:p-2">
|
|
||||||
<InputField
|
|
||||||
label="Email"
|
|
||||||
onChangeHandler={setEmail}
|
|
||||||
type="email"
|
|
||||||
value={email}
|
value={email}
|
||||||
placeholder=""
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
type="email"
|
||||||
|
placeholder="Enter your email..."
|
||||||
isRequired
|
isRequired
|
||||||
autoComplete="username"
|
autoComplete="username"
|
||||||
|
className="h-10"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx-auto mt-4 flex max-h-20 w-full max-w-md flex-col items-center justify-center text-sm md:p-2">
|
<div className="mt-4 w-1/4 min-w-[21.2rem] rounded-md text-center md:min-w-[20.1rem] lg:w-1/6">
|
||||||
<div className="text-l m-8 mt-6 px-8 py-3 text-lg">
|
<Button
|
||||||
<Button type="submit" size="lg" onClick={() => {}} isLoading={loading}>
|
type="submit"
|
||||||
Continue
|
size="sm"
|
||||||
</Button>
|
isFullWidth
|
||||||
</div>
|
className="h-10"
|
||||||
|
colorSchema="primary"
|
||||||
|
variant="solid"
|
||||||
|
isLoading={loading}
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="mt-6 flex flex-row text-sm text-bunker-400">
|
||||||
|
<Link to="/login">
|
||||||
|
<span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
|
||||||
|
Back to Login
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
{step === 2 && (
|
{step === 2 && (
|
||||||
<div className="h-7/12 mx-auto w-full max-w-md rounded-xl bg-bunker px-6 py-4 pt-8 drop-shadow-xl">
|
<div className="mx-auto flex w-full flex-col items-center justify-center">
|
||||||
<p className="mx-auto mb-6 flex w-max justify-center text-xl font-semibold text-bunker-100 md:text-2xl">
|
<h1 className="mb-2 bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
|
||||||
Look for an email in your inbox.
|
Look for an email in your inbox
|
||||||
|
</h1>
|
||||||
|
<p className="w-max max-w-lg justify-center text-center text-sm text-gray-400">
|
||||||
|
If the email is in our system, you will receive an email at{" "}
|
||||||
|
<span className="italic">{email}</span> with instructions on how to reset your password.
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-4 flex flex-row items-center justify-center md:mx-2 md:pb-4">
|
<div className="mt-6 flex flex-row text-sm text-bunker-400">
|
||||||
<p className="w-max text-center text-sm text-gray-400">
|
<Link to="/login">
|
||||||
If the email is in our system, you will receive an email at{" "}
|
<span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
|
||||||
<span className="italic">{email}</span> with instructions on how to reset your
|
Back to Login
|
||||||
password.
|
</span>
|
||||||
</p>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<EmailServiceSetupModal
|
<EmailServiceSetupModal
|
||||||
isOpen={popUp.setUpEmail?.isOpen}
|
isOpen={popUp.setUpEmail?.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("setUpEmail", isOpen)}
|
onOpenChange={(isOpen) => handlePopUpToggle("setUpEmail", isOpen)}
|
||||||
|
|||||||
Reference in New Issue
Block a user