feat: refactor password reset flow with new routes and forms
This commit is contained in:
parent
940b8e9dfc
commit
0d7e5ba6ae
15
src/app/auth/forgot-password/page.tsx
Normal file
15
src/app/auth/forgot-password/page.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import { ForgotPasswordForm } from "@/components/auth/forgot-password-form";
|
||||
import { siteConfig } from "@/config/site";
|
||||
import { constructMetadata } from "@/lib/metadata";
|
||||
|
||||
export const metadata = constructMetadata({
|
||||
title: "Forgot Password",
|
||||
description: "Forgot your password? Reset it.",
|
||||
canonicalUrl: `${siteConfig.url}/auth/forgot-password`,
|
||||
});
|
||||
|
||||
const ForgotPasswordPage = () => {
|
||||
return <ForgotPasswordForm />;
|
||||
};
|
||||
|
||||
export default ForgotPasswordPage;
|
@ -1,5 +1,4 @@
|
||||
import BackButtonSmall from "@/components/shared/back-button-small";
|
||||
import Image from "next/image";
|
||||
|
||||
/**
|
||||
* auth layout is different from other public layouts,
|
||||
@ -13,25 +12,9 @@ export default function AuthLayout({
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<div className="w-full lg:grid lg:min-h-screen lg:grid-cols-2">
|
||||
{/* auth form */}
|
||||
<div className="flex items-center justify-center relative w-full h-full min-h-screen">
|
||||
<BackButtonSmall className="absolute top-6 left-6" />
|
||||
<div className="w-full max-w-md px-4">{children}</div>
|
||||
</div>
|
||||
|
||||
{/* brand image */}
|
||||
<div className="hidden bg-muted lg:block">
|
||||
<Image
|
||||
src="/placeholder.svg"
|
||||
alt="Image"
|
||||
width="1920"
|
||||
height="1080"
|
||||
className="h-full w-full object-cover dark:brightness-[0.2] dark:grayscale"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-center relative w-full h-full min-h-screen">
|
||||
<BackButtonSmall className="absolute top-6 left-6" />
|
||||
<div className="w-full max-w-md px-4">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
import { NewPasswordForm } from "@/components/auth/new-password-form";
|
||||
import { siteConfig } from "@/config/site";
|
||||
import { constructMetadata } from "@/lib/metadata";
|
||||
|
||||
export const metadata = constructMetadata({
|
||||
title: "New Password",
|
||||
description: "Set a new password",
|
||||
canonicalUrl: `${siteConfig.url}/auth/new-password`,
|
||||
});
|
||||
|
||||
const NewPasswordPage = () => {
|
||||
return <NewPasswordForm />;
|
||||
};
|
||||
|
||||
export default NewPasswordPage;
|
@ -1,15 +1,15 @@
|
||||
import { ResetPasswordForm } from "@/components/auth/reset-form";
|
||||
import { ResetPasswordForm } from "@/components/auth/reset-password-form";
|
||||
import { siteConfig } from "@/config/site";
|
||||
import { constructMetadata } from "@/lib/metadata";
|
||||
|
||||
export const metadata = constructMetadata({
|
||||
title: "Reset Password",
|
||||
description: "Reset your password",
|
||||
canonicalUrl: `${siteConfig.url}/auth/reset`,
|
||||
description: "Set a new password",
|
||||
canonicalUrl: `${siteConfig.url}/auth/reset-password`,
|
||||
});
|
||||
|
||||
const ResetPage = () => {
|
||||
const ResetPasswordPage = () => {
|
||||
return <ResetPasswordForm />;
|
||||
};
|
||||
|
||||
export default ResetPage;
|
||||
export default ResetPasswordPage;
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { ResetPasswordSchema } from "@/lib/schemas";
|
||||
import { ForgotPasswordSchema } from "@/lib/schemas";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useState, useTransition } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
@ -21,39 +21,39 @@ import type * as z from "zod";
|
||||
import { Icons } from "@/components/icons/icons";
|
||||
import { authClient } from "@/lib/auth-client";
|
||||
|
||||
export const ResetPasswordForm = () => {
|
||||
export const ForgotPasswordForm = () => {
|
||||
const [error, setError] = useState<string | undefined>("");
|
||||
const [success, setSuccess] = useState<string | undefined>("");
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
|
||||
const form = useForm<z.infer<typeof ResetPasswordSchema>>({
|
||||
resolver: zodResolver(ResetPasswordSchema),
|
||||
const form = useForm<z.infer<typeof ForgotPasswordSchema>>({
|
||||
resolver: zodResolver(ForgotPasswordSchema),
|
||||
defaultValues: {
|
||||
email: "",
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (values: z.infer<typeof ResetPasswordSchema>) => {
|
||||
const onSubmit = async (values: z.infer<typeof ForgotPasswordSchema>) => {
|
||||
const { data, error } = await authClient.forgetPassword({
|
||||
email: values.email,
|
||||
redirectTo: "/auth/new-password",
|
||||
redirectTo: "/auth/reset-password",
|
||||
}, {
|
||||
onRequest: (ctx) => {
|
||||
// console.log("reset, request:", ctx.url);
|
||||
// console.log("forgotPassword, request:", ctx.url);
|
||||
setIsPending(true);
|
||||
setError("");
|
||||
setSuccess("");
|
||||
},
|
||||
onResponse: (ctx) => {
|
||||
// console.log("reset, response:", ctx.response);
|
||||
// console.log("forgotPassword, response:", ctx.response);
|
||||
setIsPending(false);
|
||||
},
|
||||
onSuccess: (ctx) => {
|
||||
// console.log("reset, success:", ctx.data);
|
||||
setSuccess("Please check your email for the reset password link");
|
||||
// console.log("forgotPassword, success:", ctx.data);
|
||||
setSuccess("Please check your email inbox");
|
||||
},
|
||||
onError: (ctx) => {
|
||||
console.log("reset, error:", ctx.error);
|
||||
console.log("forgotPassword, error:", ctx.error);
|
||||
setError(ctx.error.message);
|
||||
},
|
||||
});
|
||||
@ -101,7 +101,7 @@ export const ResetPasswordForm = () => {
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<span>Send reset email</span>
|
||||
<span>Send reset password email</span>
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
@ -119,7 +119,7 @@ export const LoginForm = ({ className }: { className?: string }) => {
|
||||
asChild
|
||||
className="px-0 font-normal text-muted-foreground"
|
||||
>
|
||||
<Link href="/auth/reset-password" className="text-xs underline">
|
||||
<Link href="/auth/forgot-password" className="text-xs underline">
|
||||
Forgot password?
|
||||
</Link>
|
||||
</Button>
|
||||
|
@ -15,14 +15,14 @@ import {
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { authClient } from "@/lib/auth-client";
|
||||
import { NewPasswordSchema } from "@/lib/schemas";
|
||||
import { ResetPasswordSchema } from "@/lib/schemas";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useState, useTransition } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import type * as z from "zod";
|
||||
|
||||
export const NewPasswordForm = () => {
|
||||
export const ResetPasswordForm = () => {
|
||||
const searchParams = useSearchParams();
|
||||
const token = searchParams.get("token");
|
||||
if (!token) {
|
||||
@ -36,14 +36,14 @@ export const NewPasswordForm = () => {
|
||||
const [success, setSuccess] = useState<string | undefined>("");
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
|
||||
const form = useForm<z.infer<typeof NewPasswordSchema>>({
|
||||
resolver: zodResolver(NewPasswordSchema),
|
||||
const form = useForm<z.infer<typeof ResetPasswordSchema>>({
|
||||
resolver: zodResolver(ResetPasswordSchema),
|
||||
defaultValues: {
|
||||
password: "",
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (values: z.infer<typeof NewPasswordSchema>) => {
|
||||
const onSubmit = async (values: z.infer<typeof ResetPasswordSchema>) => {
|
||||
const { data, error } = await authClient.resetPassword({
|
||||
newPassword: values.password,
|
||||
token,
|
@ -158,13 +158,13 @@ export type UserPasswordData = z.infer<typeof UserPasswordSchema>;
|
||||
/**
|
||||
* auth related schemas
|
||||
*/
|
||||
export const NewPasswordSchema = z.object({
|
||||
export const ResetPasswordSchema = z.object({
|
||||
password: z.string().min(8, {
|
||||
message: "Minimum 8 characters required",
|
||||
}),
|
||||
});
|
||||
|
||||
export const ResetPasswordSchema = z.object({
|
||||
export const ForgotPasswordSchema = z.object({
|
||||
email: z.string().email({
|
||||
message: "Email is required",
|
||||
}),
|
||||
|
Loading…
Reference in New Issue
Block a user