import { ReactElement, useEffect, useMemo, useState } from "react"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; import { Controller, useForm } from "react-hook-form"; import { Eye, EyeOff } from "lucide-react"; // ui import { Button, Input, Spinner, TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui"; // components import { PasswordStrengthMeter } from "@/components/account"; import { PageHead } from "@/components/core"; import { SidebarHamburgerToggle } from "@/components/core/sidebar"; import { getPasswordStrength } from "@/helpers/password.helper"; // hooks import { useAppTheme, useUser } from "@/hooks/store"; // layout import { ProfileSettingsLayout } from "@/layouts/settings-layout"; // types import { NextPageWithLayout } from "@/lib/types"; // services import { AuthService } from "@/services/auth.service"; import { UserService } from "@/services/user.service"; export interface FormValues { old_password: string; new_password: string; confirm_password: string; } const defaultValues: FormValues = { old_password: "", new_password: "", confirm_password: "", }; export const userService = new UserService(); export const authService = new AuthService(); const ChangePasswordPage: NextPageWithLayout = observer(() => { const [csrfToken, setCsrfToken] = useState(undefined); const [isPageLoading, setIsPageLoading] = useState(true); const [showPassword, setShowPassword] = useState({ oldPassword: false, password: false, retypePassword: false, }); const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false); // router const router = useRouter(); // store hooks const { toggleSidebar } = useAppTheme(); const { data: currentUser } = useUser(); // use form const { control, handleSubmit, watch, formState: { errors, isSubmitting }, reset, } = useForm({ defaultValues }); const oldPassword = watch("old_password"); const password = watch("new_password"); const retypePassword = watch("confirm_password"); const handleShowPassword = (key: keyof typeof showPassword) => setShowPassword((prev) => ({ ...prev, [key]: !prev[key] })); const handleChangePassword = async (formData: FormValues) => { try { if (!csrfToken) throw new Error("csrf token not found"); const changePasswordPromise = userService .changePassword(csrfToken, { old_password: formData.old_password, new_password: formData.new_password, }) .then(() => { reset(defaultValues); }); setPromiseToast(changePasswordPromise, { loading: "Changing password...", success: { title: "Success!", message: () => "Password changed successfully.", }, error: { title: "Error!", message: () => "Something went wrong. Please try again 1.", }, }); } catch (err: any) { setToast({ type: TOAST_TYPE.ERROR, title: "Error!", message: err?.error ?? "Something went wrong. Please try again 2.", }); } }; useEffect(() => { if (csrfToken === undefined) authService.requestCSRFToken().then((data) => data?.csrf_token && setCsrfToken(data.csrf_token)); }, [csrfToken]); useEffect(() => { if (!currentUser) return; if (currentUser.is_password_autoset) router.push("/profile"); else setIsPageLoading(false); }, [currentUser, router]); const isButtonDisabled = useMemo( () => !isSubmitting && !!oldPassword && !!password && !!retypePassword && getPasswordStrength(password) >= 3 && password === retypePassword && password !== oldPassword ? false : true, [isSubmitting, oldPassword, password, retypePassword] ); const passwordSupport = password.length > 0 && (getPasswordStrength(password) < 3 || isPasswordInputFocused) && ( ); if (isPageLoading) return (
); return ( <>
toggleSidebar()} />

Change password

Current password

( )} /> {showPassword?.oldPassword ? ( handleShowPassword("oldPassword")} /> ) : ( handleShowPassword("oldPassword")} /> )}
{errors.old_password && {errors.old_password.message}}

New password

( setIsPasswordInputFocused(true)} onBlur={() => setIsPasswordInputFocused(false)} /> )} /> {showPassword?.password ? ( handleShowPassword("password")} /> ) : ( handleShowPassword("password")} /> )}
{passwordSupport}

Confirm password

( )} /> {showPassword?.retypePassword ? ( handleShowPassword("retypePassword")} /> ) : ( handleShowPassword("retypePassword")} /> )}
{!!retypePassword && password !== retypePassword && ( Passwords don{"'"}t match )}
); }); ChangePasswordPage.getLayout = function getLayout(page: ReactElement) { return {page}; }; export default ChangePasswordPage;