updated logic

This commit is contained in:
pablodanswer 2024-12-19 20:09:14 -08:00
parent c2447dbb1c
commit 680ab9ea30
7 changed files with 259 additions and 254 deletions

View File

@ -26,72 +26,68 @@ const ForgotPasswordPage: React.FC = () => {
return (
<AuthFlowContainer>
<div className="flex flex-col w-full justify-center">
<CardSection className="mt-4 w-full">
{" "}
<div className="flex">
<Title className="mb-2 mx-auto font-bold">Forgot Password</Title>
</div>
{isWorking && <Spinner />}
{popup}
<Formik
initialValues={{
email: "",
}}
validationSchema={Yup.object().shape({
email: Yup.string().email().required(),
})}
onSubmit={async (values) => {
setIsWorking(true);
try {
await forgotPassword(values.email);
setPopup({
type: "success",
message:
"Password reset email sent. Please check your inbox.",
});
} catch (error) {
const errorMessage =
error instanceof Error
? error.message
: "An error occurred. Please try again.";
setPopup({
type: "error",
message: errorMessage,
});
} finally {
setIsWorking(false);
}
}}
>
{({ isSubmitting }) => (
<Form className="w-full flex flex-col items-stretch mt-2">
<TextFormField
name="email"
label="Email"
type="email"
placeholder="email@yourcompany.com"
/>
<div className="flex">
<Title className="mb-2 mx-auto font-bold">Forgot Password</Title>
</div>
{isWorking && <Spinner />}
{popup}
<Formik
initialValues={{
email: "",
}}
validationSchema={Yup.object().shape({
email: Yup.string().email().required(),
})}
onSubmit={async (values) => {
setIsWorking(true);
try {
await forgotPassword(values.email);
setPopup({
type: "success",
message: "Password reset email sent. Please check your inbox.",
});
} catch (error) {
const errorMessage =
error instanceof Error
? error.message
: "An error occurred. Please try again.";
setPopup({
type: "error",
message: errorMessage,
});
} finally {
setIsWorking(false);
}
}}
>
{({ isSubmitting }) => (
<Form className="w-full flex flex-col items-stretch mt-2">
<TextFormField
name="email"
label="Email"
type="email"
placeholder="email@yourcompany.com"
/>
<div className="flex">
<Button
type="submit"
disabled={isSubmitting}
className="mx-auto w-full"
>
Reset Password
</Button>
</div>
</Form>
)}
</Formik>
<div className="flex">
<Text className="mt-4 mx-auto">
<Link href="/auth/login" className="text-link font-medium">
Back to Login
</Link>
</Text>
</div>
</CardSection>
<div className="flex">
<Button
type="submit"
disabled={isSubmitting}
className="mx-auto w-full"
>
Reset Password
</Button>
</div>
</Form>
)}
</Formik>
<div className="flex">
<Text className="mt-4 mx-auto">
<Link href="/auth/login" className="text-link font-medium">
Back to Login
</Link>
</Text>
</div>
</div>
</AuthFlowContainer>
);

View File

@ -12,6 +12,7 @@ import { Spinner } from "@/components/Spinner";
import { set } from "lodash";
import { NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED } from "@/lib/constants";
import Link from "next/link";
import { useUser } from "@/components/user/UserProvider";
export function EmailPasswordForm({
isSignup = false,
@ -24,6 +25,7 @@ export function EmailPasswordForm({
referralSource?: string;
nextUrl?: string | null;
}) {
const { user } = useUser();
const { popup, setPopup } = usePopup();
const [isWorking, setIsWorking] = useState(false);
return (
@ -116,24 +118,29 @@ export function EmailPasswordForm({
name="password"
label="Password"
type="password"
includeForgotPassword={
NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED && !isSignup
}
placeholder="**************"
/>
{NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED && !isSignup && (
<Link
href="/auth/forgot-password"
className="text-sm text-link font-medium whitespace-nowrap"
>
Forgot Password?
</Link>
)}
<Button
type="submit"
disabled={isSubmitting}
className="mx-auto w-full"
className="mx-auto !py-4 w-full"
>
{isSignup ? "Sign Up" : "Log In"}
</Button>
{user?.is_anonymous_user && (
<Link
href="/chat"
className="text-xs text-blue-500 cursor-pointer text-center w-full text-link font-medium mx-auto"
>
<span className="hover:border-b hover:border-dotted hover:border-blue-500">
or continue as guest
</span>
</Link>
)}
</Form>
)}
</Formik>

View File

@ -77,67 +77,36 @@ const Page = async (props: {
}
return (
<AuthFlowContainer>
<div className="absolute top-10x w-full">
<HealthCheckBanner />
</div>
<div className="flex flex-col ">
<AuthFlowContainer authState="login">
<div className="absolute top-10x w-full">
<HealthCheckBanner />
</div>
<div className="flex flex-col w-full justify-center">
{authUrl && authTypeMetadata && (
<>
<h2 className="text-center text-xl text-strong font-bold">
<LoginText />
</h2>
<SignInButton
authorizeUrl={authUrl}
authType={authTypeMetadata?.authType}
/>
</>
)}
{authTypeMetadata?.authType === "cloud" && (
<div className="mt-4 w-full justify-center">
<div className="flex items-center w-full my-4">
<div className="flex-grow border-t border-gray-300"></div>
<span className="px-4 text-gray-500">or</span>
<div className="flex-grow border-t border-gray-300"></div>
</div>
<EmailPasswordForm shouldVerify={true} nextUrl={nextUrl} />
<div className="flex mt-4 justify-between">
<Link
href={`/auth/signup${
searchParams?.next ? `?next=${searchParams.next}` : ""
}`}
className="text-link font-medium"
>
Create an account
</Link>
{NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED && (
<Link
href="/auth/forgot-password"
className="text-link font-medium"
>
Reset Password
</Link>
)}
</div>
</div>
)}
{authTypeMetadata?.authType === "basic" && (
<CardSection className="mt-4 w-96">
<div className="flex">
<Title className="mb-2 mx-auto font-bold">
<div className="flex flex-col w-full justify-center">
{authUrl && authTypeMetadata && (
<>
<h2 className="text-center text-xl text-strong font-bold">
<LoginText />
</Title>
</div>
<EmailPasswordForm nextUrl={nextUrl} />
<div className="flex flex-col gap-y-2 items-center">
<Text className="mt-4 ">
Don&apos;t have an account?{" "}
</h2>
<SignInButton
authorizeUrl={authUrl}
authType={authTypeMetadata?.authType}
/>
</>
)}
{authTypeMetadata?.authType === "cloud" && (
<div className="mt-4 w-full justify-center">
<div className="flex items-center w-full my-4">
<div className="flex-grow border-t border-gray-300"></div>
<span className="px-4 text-gray-500">or</span>
<div className="flex-grow border-t border-gray-300"></div>
</div>
<EmailPasswordForm shouldVerify={true} nextUrl={nextUrl} />
<div className="flex mt-4 justify-between">
<Link
href={`/auth/signup${
searchParams?.next ? `?next=${searchParams.next}` : ""
@ -146,29 +115,44 @@ const Page = async (props: {
>
Create an account
</Link>
</Text>
{NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED && (
<Link
href="/auth/forgot-password"
className="text-link font-medium"
>
Reset Password
</Link>
)}
</div>
</div>
</CardSection>
)}
{currentUser?.is_anonymous_user && (
<div className="mt-4 w-full justify-center">
<Text className="mt-4 mx-auto">
You are currently logged in as an anonymous user. You can access
the chat experience{" "}
<Link
href={`/auth/login${
searchParams?.next ? `?next=${searchParams.next}` : ""
}`}
className="text-link font-medium"
>
here
</Link>
.
</Text>
</div>
)}
</div>
</AuthFlowContainer>
)}
{authTypeMetadata?.authType === "basic" && (
<>
<div className="flex">
<Title className="mb-2 mx-auto text-xl text-strong font-bold">
<LoginText />
</Title>
</div>
<EmailPasswordForm nextUrl={nextUrl} />
<div className="flex flex-col gap-y-2 items-center"></div>
</>
)}
</div>
</AuthFlowContainer>
<Text className="mt-4 ">
Don&apos;t have an account?{" "}
<Link
href={`/auth/signup${
searchParams?.next ? `?next=${searchParams.next}` : ""
}`}
className="text-link font-medium"
>
Create an account
</Link>
</Text>
</div>
);
};

View File

@ -28,87 +28,84 @@ const ResetPasswordPage: React.FC = () => {
return (
<AuthFlowContainer>
<div className="flex flex-col w-full justify-center">
<CardSection className="mt-4 w-full">
<div className="flex">
<Title className="mb-2 mx-auto font-bold">Reset Password</Title>
</div>
{isWorking && <Spinner />}
{popup}
<Formik
initialValues={{
password: "",
confirmPassword: "",
}}
validationSchema={Yup.object().shape({
password: Yup.string().required("Password is required"),
confirmPassword: Yup.string()
.oneOf([Yup.ref("password"), undefined], "Passwords must match")
.required("Confirm Password is required"),
})}
onSubmit={async (values) => {
if (!token) {
setPopup({
type: "error",
message: "Invalid or missing reset token.",
});
return;
}
setIsWorking(true);
try {
await resetPassword(token, values.password);
setPopup({
type: "success",
message:
"Password reset successfully. Redirecting to login...",
});
setTimeout(() => {
redirect("/auth/login");
}, 1000);
} catch (error) {
setPopup({
type: "error",
message: "An error occurred. Please try again.",
});
} finally {
setIsWorking(false);
}
}}
>
{({ isSubmitting }) => (
<Form className="w-full flex flex-col items-stretch mt-2">
<TextFormField
name="password"
label="New Password"
type="password"
placeholder="Enter your new password"
/>
<TextFormField
name="confirmPassword"
label="Confirm New Password"
type="password"
placeholder="Confirm your new password"
/>
<div className="flex">
<Title className="mb-2 mx-auto font-bold">Reset Password</Title>
</div>
{isWorking && <Spinner />}
{popup}
<Formik
initialValues={{
password: "",
confirmPassword: "",
}}
validationSchema={Yup.object().shape({
password: Yup.string().required("Password is required"),
confirmPassword: Yup.string()
.oneOf([Yup.ref("password"), undefined], "Passwords must match")
.required("Confirm Password is required"),
})}
onSubmit={async (values) => {
if (!token) {
setPopup({
type: "error",
message: "Invalid or missing reset token.",
});
return;
}
setIsWorking(true);
try {
await resetPassword(token, values.password);
setPopup({
type: "success",
message: "Password reset successfully. Redirecting to login...",
});
setTimeout(() => {
redirect("/auth/login");
}, 1000);
} catch (error) {
setPopup({
type: "error",
message: "An error occurred. Please try again.",
});
} finally {
setIsWorking(false);
}
}}
>
{({ isSubmitting }) => (
<Form className="w-full flex flex-col items-stretch mt-2">
<TextFormField
name="password"
label="New Password"
type="password"
placeholder="Enter your new password"
/>
<TextFormField
name="confirmPassword"
label="Confirm New Password"
type="password"
placeholder="Confirm your new password"
/>
<div className="flex">
<Button
type="submit"
disabled={isSubmitting}
className="mx-auto w-full"
>
Reset Password
</Button>
</div>
</Form>
)}
</Formik>
<div className="flex">
<Text className="mt-4 mx-auto">
<Link href="/auth/login" className="text-link font-medium">
Back to Login
</Link>
</Text>
</div>
</CardSection>
<div className="flex">
<Button
type="submit"
disabled={isSubmitting}
className="mx-auto w-full"
>
Reset Password
</Button>
</div>
</Form>
)}
</Formik>
<div className="flex">
<Text className="mt-4 mx-auto">
<Link href="/auth/login" className="text-link font-medium">
Back to Login
</Link>
</Text>
</div>
</div>
</AuthFlowContainer>
);

View File

@ -61,7 +61,7 @@ const Page = async (props: {
}
return (
<AuthFlowContainer>
<AuthFlowContainer authState="signup">
<HealthCheckBanner />
<>
@ -94,21 +94,6 @@ const Page = async (props: {
shouldVerify={authTypeMetadata?.requiresVerification}
nextUrl={nextUrl}
/>
<div className="flex">
<Text className="mt-4 mx-auto">
Already have an account?{" "}
<Link
href={{
pathname: "/auth/login",
query: { ...searchParams },
}}
className="text-link font-medium"
>
Log In
</Link>
</Text>
</div>
</div>
</>
</AuthFlowContainer>

View File

@ -29,6 +29,7 @@ import { useRef, useState } from "react";
import remarkGfm from "remark-gfm";
import { EditIcon } from "@/components/icons/icons";
import { Button } from "@/components/ui/button";
import Link from "next/link";
export function SectionHeader({
children,
@ -143,6 +144,7 @@ export function TextFormField({
small,
removeLabel,
min,
includeForgotPassword,
onChange,
width,
vertical,
@ -169,6 +171,7 @@ export function TextFormField({
explanationLink?: string;
small?: boolean;
min?: number;
includeForgotPassword?: boolean;
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
width?: string;
vertical?: boolean;
@ -238,7 +241,7 @@ export function TextFormField({
)}
</div>
{subtext && <SubLabel>{subtext}</SubLabel>}
<div className={`w-full flex ${includeRevert && "gap-x-2"}`}>
<div className={`w-full flex ${includeRevert && "gap-x-2"} relative`}>
<Field
onChange={handleChange}
min={min}
@ -269,6 +272,14 @@ export function TextFormField({
placeholder={placeholder}
autoComplete={autoCompleteDisabled ? "off" : undefined}
/>
{includeForgotPassword && (
<Link
href="/auth/forgot-password"
className="absolute right-3 top-1/2 mt-[3px] transform -translate-y-1/2 text-xs text-blue-500 cursor-pointer"
>
Forgot password?
</Link>
)}
</div>
{explanationText && (

View File

@ -1,16 +1,41 @@
import Link from "next/link";
import { Logo } from "../logo/Logo";
export default function AuthFlowContainer({
children,
authState,
}: {
children: React.ReactNode;
authState?: "signup" | "login";
}) {
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-background">
<div className="w-full max-w-md bg-black pt-8 pb-4 px-8 mx-4 gap-y-4 bg-white flex items-center flex-col rounded-xl shadow-lg border border-bacgkround-100">
<div className="p-4 flex flex-col items-center justify-center min-h-screen bg-background">
<div className="w-full max-w-md bg-black pt-8 pb-6 px-8 mx-4 gap-y-4 bg-white flex items-center flex-col rounded-xl shadow-lg border border-bacgkround-100">
<Logo width={70} height={70} />
{children}
</div>
{authState === "login" && (
<div className="text-sm mt-4 text-center w-full text-neutral-900 font-medium mx-auto">
Don&apos;t have an account?{" "}
<Link
href="/auth/signup"
className=" underline transition-colors duration-200"
>
Create one
</Link>
</div>
)}
{authState === "signup" && (
<div className="text-sm mt-4 text-center w-full text-neutral-900 font-medium mx-auto">
Already have an account?{" "}
<Link
href="/auth/login"
className=" underline transition-colors duration-200"
>
Log In
</Link>
</div>
)}
</div>
);
}