"use client"; import { observer } from "mobx-react"; import Image from "next/image"; import Link from "next/link"; import { useSearchParams } from "next/navigation"; import { useTheme } from "next-themes"; import { Controller, useForm } from "react-hook-form"; // icons import { CircleCheck } from "lucide-react"; // plane imports import { AUTH_TRACKER_ELEMENTS, AUTH_TRACKER_EVENTS } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { Button, Input, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui"; import { cn, checkEmailValidity } from "@plane/utils"; // helpers import { EPageTypes } from "@/helpers/authentication.helper"; // hooks import { captureError, captureSuccess } from "@/helpers/event-tracker.helper"; import { useInstance } from "@/hooks/store"; import useTimer from "@/hooks/use-timer"; // wrappers import { AuthenticationWrapper } from "@/lib/wrappers"; // images import PlaneBackgroundPatternDark from "@/public/auth/background-pattern-dark.svg"; import PlaneBackgroundPattern from "@/public/auth/background-pattern.svg"; import BlackHorizontalLogo from "@/public/plane-logos/black-horizontal-with-blue-logo.png"; import WhiteHorizontalLogo from "@/public/plane-logos/white-horizontal-with-blue-logo.png"; // services import { AuthService } from "@/services/auth.service"; type TForgotPasswordFormValues = { email: string; }; const defaultValues: TForgotPasswordFormValues = { email: "", }; // services const authService = new AuthService(); const ForgotPasswordPage = observer(() => { // search params const searchParams = useSearchParams(); const email = searchParams.get("email"); // plane hooks const { t } = useTranslation(); const { config } = useInstance(); // hooks const { resolvedTheme } = useTheme(); // timer const { timer: resendTimerCode, setTimer: setResendCodeTimer } = useTimer(0); // form info const { control, formState: { errors, isSubmitting, isValid }, handleSubmit, } = useForm({ defaultValues: { ...defaultValues, email: email?.toString() ?? "", }, }); const handleForgotPassword = async (formData: TForgotPasswordFormValues) => { await authService .sendResetPasswordLink({ email: formData.email, }) .then(() => { captureSuccess({ eventName: AUTH_TRACKER_EVENTS.forgot_password, payload: { email: formData.email, }, }); setToast({ type: TOAST_TYPE.SUCCESS, title: t("auth.forgot_password.toast.success.title"), message: t("auth.forgot_password.toast.success.message"), }); setResendCodeTimer(30); }) .catch((err) => { captureError({ eventName: AUTH_TRACKER_EVENTS.forgot_password, payload: { email: formData.email, }, }); setToast({ type: TOAST_TYPE.ERROR, title: t("auth.forgot_password.toast.error.title"), message: err?.error ?? t("auth.forgot_password.toast.error.message"), }); }); }; // derived values const enableSignUpConfig = config?.enable_signup ?? false; const logo = resolvedTheme === "light" ? BlackHorizontalLogo : WhiteHorizontalLogo; return (
Plane background pattern
Plane logo
{enableSignUpConfig && (
{t("auth.common.new_to_plane")} {t("auth.common.create_account")}
)}

{t("auth.forgot_password.title")}

{t("auth.forgot_password.description")}

checkEmailValidity(value) || t("auth.common.email.errors.invalid"), }} render={({ field: { value, onChange, ref } }) => ( 0} /> )} /> {resendTimerCode > 0 && (

{t("auth.forgot_password.email_sent")}

)}
{t("auth.common.back_to_sign_in")}
); }); export default ForgotPasswordPage;