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

View File

@ -12,6 +12,7 @@ import { Spinner } from "@/components/Spinner";
import { set } from "lodash"; import { set } from "lodash";
import { NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED } from "@/lib/constants"; import { NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED } from "@/lib/constants";
import Link from "next/link"; import Link from "next/link";
import { useUser } from "@/components/user/UserProvider";
export function EmailPasswordForm({ export function EmailPasswordForm({
isSignup = false, isSignup = false,
@ -24,6 +25,7 @@ export function EmailPasswordForm({
referralSource?: string; referralSource?: string;
nextUrl?: string | null; nextUrl?: string | null;
}) { }) {
const { user } = useUser();
const { popup, setPopup } = usePopup(); const { popup, setPopup } = usePopup();
const [isWorking, setIsWorking] = useState(false); const [isWorking, setIsWorking] = useState(false);
return ( return (
@ -116,24 +118,29 @@ export function EmailPasswordForm({
name="password" name="password"
label="Password" label="Password"
type="password" type="password"
includeForgotPassword={
NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED && !isSignup
}
placeholder="**************" 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 <Button
type="submit" type="submit"
disabled={isSubmitting} disabled={isSubmitting}
className="mx-auto w-full" className="mx-auto !py-4 w-full"
> >
{isSignup ? "Sign Up" : "Log In"} {isSignup ? "Sign Up" : "Log In"}
</Button> </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> </Form>
)} )}
</Formik> </Formik>

View File

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

View File

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

View File

@ -61,7 +61,7 @@ const Page = async (props: {
} }
return ( return (
<AuthFlowContainer> <AuthFlowContainer authState="signup">
<HealthCheckBanner /> <HealthCheckBanner />
<> <>
@ -94,21 +94,6 @@ const Page = async (props: {
shouldVerify={authTypeMetadata?.requiresVerification} shouldVerify={authTypeMetadata?.requiresVerification}
nextUrl={nextUrl} 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> </div>
</> </>
</AuthFlowContainer> </AuthFlowContainer>

View File

@ -29,6 +29,7 @@ import { useRef, useState } from "react";
import remarkGfm from "remark-gfm"; import remarkGfm from "remark-gfm";
import { EditIcon } from "@/components/icons/icons"; import { EditIcon } from "@/components/icons/icons";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import Link from "next/link";
export function SectionHeader({ export function SectionHeader({
children, children,
@ -143,6 +144,7 @@ export function TextFormField({
small, small,
removeLabel, removeLabel,
min, min,
includeForgotPassword,
onChange, onChange,
width, width,
vertical, vertical,
@ -169,6 +171,7 @@ export function TextFormField({
explanationLink?: string; explanationLink?: string;
small?: boolean; small?: boolean;
min?: number; min?: number;
includeForgotPassword?: boolean;
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void; onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
width?: string; width?: string;
vertical?: boolean; vertical?: boolean;
@ -238,7 +241,7 @@ export function TextFormField({
)} )}
</div> </div>
{subtext && <SubLabel>{subtext}</SubLabel>} {subtext && <SubLabel>{subtext}</SubLabel>}
<div className={`w-full flex ${includeRevert && "gap-x-2"}`}> <div className={`w-full flex ${includeRevert && "gap-x-2"} relative`}>
<Field <Field
onChange={handleChange} onChange={handleChange}
min={min} min={min}
@ -269,6 +272,14 @@ export function TextFormField({
placeholder={placeholder} placeholder={placeholder}
autoComplete={autoCompleteDisabled ? "off" : undefined} 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> </div>
{explanationText && ( {explanationText && (

View File

@ -1,16 +1,41 @@
import Link from "next/link";
import { Logo } from "../logo/Logo"; import { Logo } from "../logo/Logo";
export default function AuthFlowContainer({ export default function AuthFlowContainer({
children, children,
authState,
}: { }: {
children: React.ReactNode; children: React.ReactNode;
authState?: "signup" | "login";
}) { }) {
return ( return (
<div className="flex flex-col items-center justify-center min-h-screen bg-background"> <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-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="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} /> <Logo width={70} height={70} />
{children} {children}
</div> </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> </div>
); );
} }